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_TopazDynamicMap.c
19* \brief NFC Ndef Mapping For Remote Devices.
20*
21* Project: NFC-FRI
22*
23* $Date: Wed Oct 27 10:21:29 2010 $
24* $Author: ing02260 $
25* $Revision: 1.41 $
26* $Aliases:  $
27*
28*/
29
30
31
32#include <phFriNfc_NdefMap.h>
33#include <phFriNfc_TopazMap.h>
34#include <phFriNfc_MapTools.h>
35#include <phFriNfc_OvrHal.h>
36
37#if !(defined(PH_FRINFC_MAP_TOPAZ_DISABLED ) || defined (PH_FRINFC_MAP_TOPAZ_DYNAMIC_DISABLED ))
38
39/*! \ingroup grp_file_attributes
40*  \name NDEF Mapping
41*
42* File: \ref phFriNfcNdefMap.c
43*
44*/
45/*@{*/
46#define PHFRINFCTOPAZMAP_FILEREVISION "$Revision: 1.41 $"
47#define PHFRINFCTOPAZMAP_FILEALIASES  "$Aliases:  $"
48/*@}*/
49/*!
50* \name Topaz Mapping - Helper data structures and macros
51*
52*/
53/*@{*/
54
55/********************************** Start of data structures *********************************/
56#ifdef FRINFC_READONLY_NDEF
57
58    #define DYN_CC_BLOCK_NUMBER                                     (0x01U)
59    #define DYN_STATIC_LOCK_BLOCK_NUM                               (0x0EU)
60
61    #define DYN_STATIC_LOCK0_BYTE_NUM                               (0x00U)
62    #define DYN_STATIC_LOCK0_BYTE_VALUE                             (0xFFU)
63
64    #define DYN_STATIC_LOCK1_BYTE_NUM                               (0x01U)
65    #define DYN_STATIC_LOCK1_BYTE_VALUE                             (0x7FU)
66
67    #define DYN_CC_RWA_BYTE_NUMBER                                  (0x03U)
68    #define DYN_CC_READ_ONLY_VALUE                                  (0x0FU)
69
70#endif /* #ifdef FRINFC_READONLY_NDEF */
71
72/*!
73* \brief \copydoc page_ovr enum for the topaz sequence of execution.
74*/
75typedef enum phFriNfc_Tpz_ParseSeq
76{
77    LOCK_T_TLV,
78    LOCK_L_TLV,
79    LOCK_V_TLV,
80    MEM_T_TLV,
81    MEM_L_TLV,
82    MEM_V_TLV,
83    NDEF_T_TLV,
84    NDEF_L_TLV,
85    NDEF_V_TLV
86}phFriNfc_Tpz_ParseSeq_t;
87
88typedef enum phFriNfc_Tpz_WrSeq
89{
90    WR_NDEF_T_TLV,
91    WR_NMN_0,
92    WR_LEN_1_0,
93    WR_LEN_2_0,
94    WR_LEN_3_0,
95    WR_DATA,
96    WR_DATA_READ_REQD,
97    WR_LEN_1_VALUE,
98    WR_LEN_2_VALUE,
99    WR_LEN_3_VALUE,
100    WR_NMN_E1
101}phFriNfc_Tpz_WrSeq_t;
102
103#ifdef FRINFC_READONLY_NDEF
104
105typedef enum phFriNfc_Tpz_RO_Seq
106{
107    WR_READONLY_CC,
108    RD_LOCK_BYTES,
109    WR_LOCK_BYTES,
110    RD_STATIC_LOCK_BYTE0,
111    WR_STATIC_LOCK_BYTE0,
112    WR_STATIC_LOCK_BYTE1
113}phFriNfc_Tpz_RO_Seq_t;
114
115#endif /* #ifdef FRINFC_READONLY_NDEF  */
116
117/********************************** End of data structures *********************************/
118
119/********************************** Start of Macros *********************************/
120/* New state for TOPAZ dynamic  card*/
121#define PH_FRINFC_TOPAZ_STATE_RD_FOR_WR_NDEF            (0x10U)
122
123#ifdef FRINFC_READONLY_NDEF
124    #define PH_FRINFC_TOPAZ_STATE_READ_ONLY             (0x11U)
125#endif /* #ifdef FRINFC_READONLY_NDEF */
126
127#define NIBBLE_SIZE                                     (0x04U)
128/* Byte shifting for the topaz */
129#define TOPAZ_BYTE_SHIFT                                (0x08U)
130/* Lock and memory control TLV length. Always 3 bytes */
131#define TOPAZ_MEM_LOCK_TLV_LENGTH                       (0x03U)
132/* UID byte length */
133#define TOPAZ_UID_BYTES_LENGTH                          (0x08U)
134
135/* Number os static lock and reserved bytes */
136#define TOPAZ_STATIC_LOCK_RES_BYTES                     (0x18U)
137/* Number of static lock and reserved memory. This value is 3 (because
138    block number D, E and F are lock and reserved blocks */
139#define TOPAZ_STATIC_LOCK_BLOCK_AREAS                   (0x03U)
140/* First lock or reserved block in the static area of the card */
141#define TOPAZ_STATIC_LOCK_FIRST_BLOCK_NO                (0x0DU)
142/* First lock or reserved byte number in the static area of the card */
143#define TOPAZ_STATIC_LOCK_RES_START                     (0x68U)
144/* End lock or reserved byte number in the static area of the card */
145#define TOPAZ_STATIC_LOCK_RES_END                       (0x78U)
146
147/* CC byte length */
148#define TOPAZ_CC_BYTES_LENGTH                           (0x04U)
149
150/* In TOPAZ card each block has 8 bytes */
151#define TOPAZ_BYTES_PER_BLOCK                           (0x08U)
152/* Each byte has 8 bites */
153#define TOPAZ_BYTE_SIZE_IN_BITS                         (0x08U)
154
155/* This mask is to get the least significant NIBBLE from a BYTE */
156#define TOPAZ_NIBBLE_MASK                               (0x0FU)
157/* This is used to mask the least significant BYTE from a TWO BYTE value */
158#define TOPAZ_BYTE_LENGTH_MASK                          (0x00FFU)
159
160/* Total segments in TOPAZ 512 bytes card. Each segment = 128 bytes,
161so there are 4 segements in the card */
162#define TOPAZ_TOTAL_SEG_TO_READ                         (0x04U)
163/* SPEC version value shall be 0x10 as per the TYPE 1 specification */
164#define TOPAZ_SPEC_VERSION                              (0x10U)
165
166/* Response length for READ SEGMENT command is 128 bytes */
167#define TOPAZ_SEGMENT_READ_LENGTH                       (0x80U)
168/* Response length for WRITE-1E command is 1 byte */
169#define TOPAZ_WRITE_1_RESPONSE                          (0x01U)
170/* Response length for WRITE-8E command is 8 bytes */
171#define TOPAZ_WRITE_8_RESPONSE                          (0x08U)
172/* Response length for READ-8 command is 8 bytes */
173#define TOPAZ_READ_8_RESPONSE                           (0x08U)
174
175/* Data bytes that can be written for the WRITE-8E command is 8 bytes */
176#define TOPAZ_WRITE_8_DATA_LENGTH                       (0x08U)
177
178/* Get the exact byte address of the card from the segment number
179    and the parse index of each segment */
180#define TOPAZ_BYTE_ADR_FROM_SEG(seg, parse_index) \
181    (((seg) * TOPAZ_SEGMENT_READ_LENGTH) + (parse_index))
182
183/* Get the segment number of the card from the byte address */
184#define TOPAZ_SEG_FROM_BYTE_ADR(byte_addr) \
185    ((byte_addr) / TOPAZ_SEGMENT_READ_LENGTH)
186/* Get the block number of the card from the byte address */
187#define TOPAZ_BLK_FROM_BYTE_ADR(byte_addr) \
188    ((byte_addr) / TOPAZ_BYTES_PER_BLOCK)
189/* Get the block offset of a block number of the card from the byte address */
190#define TOPAZ_BYTE_OFFSET_FROM_BYTE_ADR(byte_addr) \
191    ((byte_addr) % TOPAZ_BYTES_PER_BLOCK)
192/* Get the exact byte address of the card from the block number
193    and the byte offset of the block number */
194#define TOPAZ_BYTE_ADR_FROM_BLK(block_no, byte_offset) \
195    (((block_no) * TOPAZ_BYTES_PER_BLOCK) + (byte_offset))
196/* To increment the block number and if block number overlaps with the
197    static lock and reserved blocks, then skip the blocks */
198#define TOPAZ_INCREMENT_SKIP_STATIC_BLOCK(block_no) \
199    ((((block_no) + 1) == TOPAZ_STATIC_LOCK_FIRST_BLOCK_NO) ? \
200    (((block_no) + 1) + TOPAZ_STATIC_LOCK_BLOCK_AREAS) : \
201    ((block_no) + 1))
202/* Check topaz spec version number */
203#define TOPAZ_COMPARE_VERSION(device_ver, tag_ver) \
204    ((device_ver & 0xF0) >= (tag_ver & 0xF0))
205
206#ifdef FRINFC_READONLY_NDEF
207
208#define TOPAZ_CONVERT_BITS_TO_BYTES(bits_to_bytes) \
209            (((bits_to_bytes % TOPAZ_BYTE_SIZE_IN_BITS) > 0) ? \
210            ((bits_to_bytes / TOPAZ_BYTE_SIZE_IN_BITS) + 1) : \
211            (bits_to_bytes / TOPAZ_BYTE_SIZE_IN_BITS))
212
213#endif /* #ifdef FRINFC_READONLY_NDEF */
214/********************************** End of Macros *********************************/
215
216/*@}*/
217
218
219/*!
220* \name Topaz Mapping - Helper Functions
221*
222*/
223/*@{*/
224
225/*!
226* \brief \copydoc page_ovr Helper function for Topaz. This function shall read defined
227* bytes from the card.
228*/
229static
230NFCSTATUS
231phFriNfc_Tpz_H_NxpRead (
232    phFriNfc_NdefMap_t          *psNdefMap);
233
234/*!
235* \brief \copydoc page_ovr Helper function for Topaz. This function shall process
236* received read id command.
237*/
238static
239NFCSTATUS
240phFriNfc_Tpz_H_ChkReadID (
241    phFriNfc_NdefMap_t          *psNdefMap);
242
243
244/*!
245* \brief \copydoc page_ovr Helper function for Topaz. This function shall process
246* read response.
247*/
248static
249NFCSTATUS
250phFriNfc_Tpz_H_ProReadResp (
251    phFriNfc_NdefMap_t  *psNdefMap);
252
253/*!
254* \brief \copydoc page_ovr Helper function for Topaz. This function calls the
255* completion routine
256*/
257static
258void
259phFriNfc_Tpz_H_Complete (
260    phFriNfc_NdefMap_t  *NdefMap,
261    NFCSTATUS           Status);
262
263
264/*!
265* \brief \copydoc page_ovr Helper function for Topaz check ndef. This function checks
266* the lock bits and set a card state
267*/
268static
269NFCSTATUS
270phFriNfc_Tpz_H_ChkLockBits (
271    phFriNfc_NdefMap_t  *psNdefMap);
272
273/*!
274* \brief \copydoc page_ovr Helper function for Topaz. This function writes defined
275* bytes into the card
276*/
277static
278NFCSTATUS
279phFriNfc_Tpz_H_NxpWrite (
280    phFriNfc_NdefMap_t          *psNdefMap,
281    uint8_t                     *p_write_data,
282    uint8_t                     wr_data_len);
283
284
285/*!
286* \brief \copydoc page_ovr Helper function for Topaz. This function parses the read bytes
287* till the NDEF TLV is found. Also, it returns error if it founds wrong TLVs.
288*/
289static
290NFCSTATUS
291phFriNfc_Tpz_H_ParseTLVs (
292    phFriNfc_NdefMap_t          *psNdefMap);
293
294/*!
295 * \brief \copydoc page_ovr Helper function for Topaz. This function parses the read bytes
296 * till the TYPE of the LOCK control TLV is found.
297 * Also, it returns error if it founds wrong TYPE.
298 */
299static
300NFCSTATUS
301phFriNfc_Tpz_H_ParseLockTLVType (
302    phFriNfc_NdefMap_t          *psNdefMap,
303    uint8_t                     *p_parse_data,
304    uint16_t                    *p_parse_index,
305    uint16_t                    total_len_to_parse,
306    phFriNfc_Tpz_ParseSeq_t     *seq_to_execute);
307
308/*!
309 * \brief \copydoc page_ovr Helper function for Topaz. This function parses the read bytes
310 * till the TYPE of the MEMORY control TLV is found.
311 * Also, it returns error if it founds wrong TYPE.
312 */
313static
314NFCSTATUS
315phFriNfc_Tpz_H_ParseMemTLVType (
316    phFriNfc_NdefMap_t          *psNdefMap,
317    uint8_t                     *p_parse_data,
318    uint16_t                    *p_parse_index,
319    uint16_t                    total_len_to_parse,
320    phFriNfc_Tpz_ParseSeq_t     *seq_to_execute);
321
322/*!
323 * \brief \copydoc page_ovr Helper function for Topaz. This function parses the read bytes
324 * till the TYPE of the NDEF control TLV is found.
325 * Also, it returns error if it founds wrong TYPE.
326 */
327static
328NFCSTATUS
329phFriNfc_Tpz_H_ParseNdefTLVType (
330    phFriNfc_NdefMap_t          *psNdefMap,
331    uint8_t                     *p_parse_data,
332    uint16_t                    *p_parse_index,
333    uint16_t                    total_len_to_parse,
334    phFriNfc_Tpz_ParseSeq_t     *seq_to_execute);
335
336/*!
337 * \brief \copydoc page_ovr Helper function for Topaz. This function gets the lock bytes
338 * information.
339 */
340static
341NFCSTATUS
342phFriNfc_Tpz_H_GetLockBytesInfo (
343    phFriNfc_NdefMap_t          *psNdefMap,
344    uint8_t                     *p_lock_info);
345
346/*!
347 * \brief \copydoc page_ovr Helper function for Topaz. This function gets the reserved bytes
348 * information.
349 */
350static
351NFCSTATUS
352phFriNfc_Tpz_H_GetMemBytesInfo (
353    phFriNfc_NdefMap_t          *psNdefMap,
354    uint8_t                     *p_mem_info);
355
356/*!
357 * \brief \copydoc page_ovr Helper function for Topaz. This function copies and checks the CC bytes.
358 * This function checks for the lock bytes value and card state also.
359 */
360static
361NFCSTATUS
362phFriNfc_Tpz_H_CheckCCBytes (
363    phFriNfc_NdefMap_t          *psNdefMap);
364
365/*!
366 * \brief \copydoc page_ovr Helper function for Topaz. This function checks the CC bytes.
367 * If .
368 */
369static
370NFCSTATUS
371phFriNfc_Tpz_H_CheckCCBytesForWrite (
372    phFriNfc_NdefMap_t          *psNdefMap);
373
374
375/*!
376 * \brief \copydoc page_ovr Helper function for Topaz. This function copies the read bytes.
377 * This function also checks for the lock and reserved bytes and skips the bytes before copying it
378 * in the buffer.
379 */
380static
381NFCSTATUS
382phFriNfc_Tpz_H_CopyReadData (
383    phFriNfc_NdefMap_t          *psNdefMap);
384
385/*!
386 * \brief \copydoc page_ovr Helper function for Topaz. This function copies the stored read bytes.
387 * This function is used only for the offset " PH_FRINFC_NDEFMAP_SEEK_CUR ".
388 */
389static
390NFCSTATUS
391phFriNfc_Tpz_H_RemainingReadDataCopy (
392    phFriNfc_NdefMap_t          *psNdefMap);
393
394/*!
395 * \brief \copydoc page_ovr Helper function for Topaz. This function gives the exact byte address
396 * of the value field after the NDEF TYPE field
397 */
398static
399uint16_t
400phFriNfc_Tpz_H_GetNDEFValueFieldAddrForRead (
401    phFriNfc_NdefMap_t          *psNdefMap);
402
403/*!
404 * \brief \copydoc page_ovr Helper function for Topaz. This function gives the exact byte address
405 * of the value field after the NDEF TYPE field
406 */
407static
408uint16_t
409phFriNfc_Tpz_H_GetNDEFValueFieldAddrForWrite (
410    phFriNfc_NdefMap_t          *psNdefMap,
411    uint16_t                     size_to_write);
412
413/*!
414 * \brief \copydoc page_ovr Helper function for Topaz. This function gives the number of bytes to skip.
415 * This function checks the input byte address and checks if any lock or reserved bytes matches with the
416 * given address. if yes, then it will return number od bytes to skip.
417 */
418static
419uint16_t
420phFriNfc_Tpz_H_GetSkipSize (
421    phFriNfc_NdefMap_t          *psNdefMap,
422    uint16_t                    byte_adr_card);
423
424/*!
425 * \brief \copydoc page_ovr Helper function for Topaz. This function gives the actual data that can
426 * be read and written in the card.
427 * This function checks for the lock and reserved bytes and subtracts the remaining size to give the
428 * actual size.
429 */
430static
431NFCSTATUS
432phFriNfc_Tpz_H_ActualCardSize (
433    phFriNfc_NdefMap_t          *psNdefMap);
434
435/*!
436 * \brief \copydoc page_ovr Helper function for Topaz. This function processes the response for
437 * the write data
438 */
439static
440NFCSTATUS
441phFriNfc_Tpz_H_ProWrResp (
442    phFriNfc_NdefMap_t          *psNdefMap);
443
444/*!
445 * \brief \copydoc page_ovr Helper function for Topaz. This function processes the read 8 commands,
446 * that is required for writing the data
447 */
448static
449NFCSTATUS
450phFriNfc_Tpz_H_ProRdForWrResp (
451    phFriNfc_NdefMap_t          *psNdefMap);
452
453/*!
454 * \brief \copydoc page_ovr Helper function for Topaz. This function copies the user data to the
455 * write buffer and writes the data to the card. If the lock or memory blocks are in between the
456 * write data, then read the current block
457 */
458static
459NFCSTATUS
460phFriNfc_Tpz_H_CopySendWrData (
461    phFriNfc_NdefMap_t          *psNdefMap);
462
463/*!
464 * \brief \copydoc page_ovr Helper function for Topaz. This function compares the input block
465 * number with lock bytes block number and returns the p_skip_size which is the lock bytes
466 * size
467 */
468static
469uint16_t
470phFriNfc_Tpz_H_CompareLockBlocks (
471    phFriNfc_NdefMap_t          *psNdefMap,
472    uint8_t                     block_no,
473    uint16_t                    *p_skip_size);
474
475/*!
476 * \brief \copydoc page_ovr Helper function for Topaz. This function compares the input block
477 * number with reserved bytes block number and returns the p_skip_size which is the reserved bytes
478 * size
479 */
480static
481uint16_t
482phFriNfc_Tpz_H_CompareMemBlocks (
483    phFriNfc_NdefMap_t          *psNdefMap,
484    uint8_t                     block_no,
485    uint16_t                    *p_skip_size);
486
487/*!
488 * \brief \copydoc page_ovr Helper function for Topaz. This function copies the read data and update
489 * the user bytes by skipping lock or memory control areas. Also, used while updating the value field
490 * skips the initial bytes and to start at the proper value field byte offset of the block
491 */
492static
493NFCSTATUS
494phFriNfc_Tpz_H_CopyReadDataAndWrite (
495    phFriNfc_NdefMap_t          *psNdefMap);
496
497
498/*!
499 * \brief \copydoc page_ovr Helper function for Topaz. This function reads the required block for writing,
500 * as some of the bytes shall not be overwritten
501 */
502static
503NFCSTATUS
504phFriNfc_Tpz_H_RdForWrite (
505    phFriNfc_NdefMap_t          *psNdefMap);
506
507/*!
508 * \brief \copydoc page_ovr Helper function for Topaz. This function reads the length block for writing,
509 * updates the length bytes with 0
510 */
511static
512NFCSTATUS
513phFriNfc_Tpz_H_UpdateLenFieldZeroAfterRead (
514    phFriNfc_NdefMap_t          *psNdefMap);
515
516/*!
517 * \brief \copydoc page_ovr Helper function for Topaz. This function reads the length block for writing,
518 * updates the length bytes with exact bytes that was written in the card
519 */
520static
521NFCSTATUS
522phFriNfc_Tpz_H_UpdateLenFieldValuesAfterRead (
523    phFriNfc_NdefMap_t          *psNdefMap);
524
525/*!
526 * \brief \copydoc page_ovr Helper function for Topaz. This function writes the NDEF TYPE of the
527 * NDEF TLV to the specific byte address. This function is called only if the previous write is
528 * failed or there is no NDEF TLV with correct CC bytes
529 */
530static
531NFCSTATUS
532phFriNfc_Tpz_H_UpdateNdefTypeField (
533    phFriNfc_NdefMap_t          *psNdefMap);
534
535#ifdef FRINFC_READONLY_NDEF
536
537static
538NFCSTATUS
539phFriNfc_Tpz_H_ProcessReadOnly (
540    phFriNfc_NdefMap_t          *psNdefMap);
541
542static
543NFCSTATUS
544phFriNfc_Tpz_H_UpdateAndWriteLockBits (
545    phFriNfc_NdefMap_t          *psNdefMap);
546
547
548#endif /* #ifdef FRINFC_READONLY_NDEF */
549
550
551/*!
552* \brief Check whether a particular Remote Device is NDEF compliant.
553*
554* The function checks whether the peer device is NDEF compliant.
555*
556* \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t
557*                    structure describing the component context.
558*
559* \retval  NFCSTATUS_PENDING   The action has been successfully triggered.
560* \retval  Others              An error has occurred.
561*
562*/
563NFCSTATUS  phFriNfc_TopazDynamicMap_ChkNdef( phFriNfc_NdefMap_t     *NdefMap)
564{
565    NFCSTATUS   Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
566        NFCSTATUS_INVALID_PARAMETER);
567    if ( NdefMap != NULL)
568    {
569        /* Update the previous operation */
570        NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_CHECK_OPE;
571        /* Update the CR index to know from which operation completion
572        routine has to be called */
573        NdefMap->TopazContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_CHK_NDEF;
574        NdefMap->TopazContainer.Cur_RW_Index = PH_FRINFC_TOPAZ_VAL0;
575        NdefMap->TopazContainer.CurrentSeg = 0;
576        NdefMap->TopazContainer.NdefTLVByteAddress = 0;
577        NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID;
578
579        NdefMap->TopazContainer.CurrentBlock = 0;
580        NdefMap->TopazContainer.WriteSeq = 0;
581        NdefMap->TopazContainer.ExpectedSeq = 0;
582
583        (void)memset ((void *)&(NdefMap->LockTlv), 0,
584                        sizeof (phFriNfc_LockCntrlTLVCont_t));
585
586        (void)memset ((void *)&(NdefMap->MemTlv), 0,
587                    sizeof (phFriNfc_ResMemCntrlTLVCont_t));
588
589        /* Set card state */
590        NdefMap->CardType = PH_FRINFC_NDEFMAP_TOPAZ_DYNAMIC_CARD;
591
592        /* Change the state to Read */
593        NdefMap->State = PH_FRINFC_TOPAZ_STATE_READ;
594
595        NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_DYNAMIC_INIT_CHK_NDEF;
596#ifdef TOPAZ_RAW_SUPPORT
597
598        *NdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_RSEG;
599
600#else
601
602#ifdef PH_HAL4_ENABLE
603        NdefMap->Cmd.JewelCmd = phHal_eJewel_ReadSeg;
604#else
605        NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead;
606#endif
607
608#endif /* #ifdef TOPAZ_RAW_SUPPORT */
609
610        Result = phFriNfc_Tpz_H_NxpRead(NdefMap);
611
612      }
613    return Result;
614}
615
616
617/*!
618* \brief Initiates Reading of NDEF information from the Remote Device.
619*
620* The function initiates the reading of NDEF information from a Remote Device.
621* It performs a reset of the state and starts the action (state machine).
622* A periodic call of the \ref phFriNfcNdefMap_Process has to be done once the action
623* has been triggered.
624*/
625
626NFCSTATUS phFriNfc_TopazDynamicMap_RdNdef( phFriNfc_NdefMap_t           *NdefMap,
627                                        uint8_t                         *PacketData,
628                                        uint32_t                        *PacketDataLength,
629                                        uint8_t                         Offset)
630{
631    NFCSTATUS               Result =    NFCSTATUS_SUCCESS;
632
633    /* Copy user buffer to the context */
634    NdefMap->ApduBuffer = PacketData;
635    /* Copy user length to the context */
636    NdefMap->ApduBufferSize = *PacketDataLength;
637    /* Update the user memory size to a context variable */
638    NdefMap->NumOfBytesRead = PacketDataLength;
639    /* Number of bytes read from the card is zero.
640    This variable returns the number of bytes read
641    from the card. */
642    *NdefMap->NumOfBytesRead = 0;
643    /* Index to know the length read */
644    NdefMap->ApduBuffIndex = PH_FRINFC_TOPAZ_VAL0;
645    /* Store the offset in the context */
646    NdefMap->Offset = Offset;
647    /* Update the CR index to know from which operation completion
648    routine has to be called */
649    NdefMap->TopazContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_RD_NDEF;
650    NdefMap->TopazContainer.SkipLockBlkFlag = 0;
651
652    NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_READ_OPE;
653    if ((PH_FRINFC_NDEFMAP_SEEK_CUR == Offset) &&
654        (TRUE == NdefMap->TopazContainer.ReadWriteCompleteFlag))
655    {
656        Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
657                            NFCSTATUS_EOF_NDEF_CONTAINER_REACHED);
658    }
659    else if ((PH_NDEFMAP_CARD_STATE_INITIALIZED ==
660            NdefMap->CardState) ||
661            (0 == NdefMap->TopazContainer.ActualNDEFMsgSize))
662    {
663        /* Length field of NDEF TLV is 0, so read cannot proceed */
664        Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
665                            NFCSTATUS_READ_FAILED);
666    }
667    else if ((PH_FRINFC_NDEFMAP_SEEK_BEGIN == Offset) ||
668        (PH_FRINFC_NDEFMAP_READ_OPE != NdefMap->PrevOperation))
669    {
670        /* If previous operation is not read then the read shall
671        start from BEGIN */
672        NdefMap->Offset = PH_FRINFC_NDEFMAP_SEEK_BEGIN;
673        /* Initialise byte number */
674        NdefMap->TopazContainer.Cur_RW_Index = PH_FRINFC_TOPAZ_VAL0;
675
676        NdefMap->TopazContainer.RemainingReadSize = 0;
677        NdefMap->TopazContainer.ReadBufferSize = 0;
678        NdefMap->TopazContainer.ReadWriteCompleteFlag = FALSE;
679        NdefMap->TopazContainer.CurrentBlock = 0;
680        NdefMap->TopazContainer.WriteSeq = 0;
681
682        NdefMap->TopazContainer.CurrentSeg = (uint8_t)TOPAZ_SEG_FROM_BYTE_ADR (
683                        phFriNfc_Tpz_H_GetNDEFValueFieldAddrForRead (NdefMap));
684
685         /* Change the state to Read ID */
686        NdefMap->State = PH_FRINFC_TOPAZ_STATE_READID;
687        /*Change the state to Read ID*/
688        NdefMap->TopazContainer.ReadWriteCompleteFlag = 0;
689#ifdef TOPAZ_RAW_SUPPORT
690
691        NdefMap->SendRecvBuf[0] = PH_FRINFC_TOPAZ_CMD_READID;
692
693#else
694
695#ifdef PH_HAL4_ENABLE
696        NdefMap->Cmd.JewelCmd = phHal_eJewel_RID;
697#else
698        NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRid;
699#endif
700
701#endif /* #ifdef TOPAZ_RAW_SUPPORT */
702        Result =  phFriNfc_Tpz_H_NxpRead(NdefMap);
703
704    }
705    else
706    {
707         /* Change the state to Read */
708          NdefMap->State = PH_FRINFC_TOPAZ_STATE_READ;
709          Result = phFriNfc_Tpz_H_RemainingReadDataCopy (NdefMap);
710    }
711
712
713    return Result;
714}
715
716#ifdef FRINFC_READONLY_NDEF
717
718NFCSTATUS
719phFriNfc_TopazDynamicMap_ConvertToReadOnly (
720    phFriNfc_NdefMap_t     *psNdefMap)
721{
722    NFCSTATUS                   result = NFCSTATUS_SUCCESS;
723    uint8_t                     cc_read_only_byte = 0x0FU;
724
725    psNdefMap->State = PH_FRINFC_TOPAZ_STATE_READ_ONLY;
726
727    psNdefMap->TopazContainer.read_only_seq = 0;
728
729
730
731    psNdefMap->TopazContainer.CurrentBlock = 0x01U;
732    psNdefMap->TopazContainer.ByteNumber = 0x03U;
733
734#ifdef TOPAZ_RAW_SUPPORT
735    *psNdefMap->SendRecvBuf = (uint8_t)PH_FRINFC_TOPAZ_CMD_WRITE_1E;
736#else
737    psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E;
738#endif /* #ifdef TOPAZ_RAW_SUPPORT */
739
740    result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, &cc_read_only_byte,
741                                    1);
742
743    if (NFCSTATUS_PENDING == result)
744    {
745        psNdefMap->TopazContainer.read_only_seq = (uint8_t)WR_READONLY_CC;
746    }
747
748
749    return result;
750}
751
752#endif /* #ifdef FRINFC_READONLY_NDEF */
753
754/*!
755* \brief Initiates Writing of NDEF information to the Remote Device.
756*
757* The function initiates the writing of NDEF information to a Remote Device.
758* It performs a reset of the state and starts the action (state machine).
759* A periodic call of the \ref phFriNfcNdefMap_Process has to be done once the action
760* has been triggered.
761*/
762NFCSTATUS phFriNfc_TopazDynamicMap_WrNdef( phFriNfc_NdefMap_t     *NdefMap,
763                                   uint8_t                 *PacketData,
764                                   uint32_t                *PacketDataLength,
765                                   uint8_t                 Offset)
766{
767    NFCSTATUS                   Result = NFCSTATUS_SUCCESS;
768
769    /* Copy user buffer to the context */
770    NdefMap->ApduBuffer = PacketData;
771    /* Copy user length to the context */
772    NdefMap->ApduBufferSize = *PacketDataLength;
773    /* Index to know the length written */
774    NdefMap->ApduBuffIndex = 0;
775    /* Update the user memory size to a context variable */
776    NdefMap->WrNdefPacketLength = PacketDataLength;
777    /* Number of bytes written to the card is zero.
778    This variable returns the number of bytes written
779    to the card. */
780    *NdefMap->WrNdefPacketLength = 0;
781    /* Update the CR index to know from which operation completion
782    routine has to be called */
783    NdefMap->TopazContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_WR_NDEF;
784    /* Store the offset in the context */
785    NdefMap->Offset = Offset;
786
787    /* Update the previous operation to write operation */
788    NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_WRITE_OPE;
789
790    if (PH_NDEFMAP_CARD_STATE_READ_ONLY == NdefMap->CardState)
791    {
792        Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
793                            NFCSTATUS_WRITE_FAILED);
794    }
795    else if ((PH_FRINFC_NDEFMAP_SEEK_CUR == Offset) &&
796        (TRUE == NdefMap->TopazContainer.ReadWriteCompleteFlag))
797    {
798        /* Offset = Current, but the read has reached the End of Card */
799        Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
800                            NFCSTATUS_EOF_NDEF_CONTAINER_REACHED);
801    }
802    else if (0 == NdefMap->TopazContainer.NdefTLVByteAddress)
803    {
804        /* No NDEF TLV found in the card, so write not possible */
805        Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
806                            NFCSTATUS_NO_NDEF_SUPPORT);
807    }
808    else if ((PH_FRINFC_NDEFMAP_SEEK_BEGIN == Offset) ||
809        (PH_FRINFC_NDEFMAP_WRITE_OPE != NdefMap->PrevOperation))
810    {
811        NdefMap->Offset = PH_FRINFC_NDEFMAP_SEEK_BEGIN;
812        /* Initialise byte number */
813        NdefMap->TopazContainer.Cur_RW_Index = PH_FRINFC_TOPAZ_VAL0;
814        /* State has to be changed */
815        NdefMap->State = PH_FRINFC_TOPAZ_STATE_READ;
816        NdefMap->TopazContainer.ReadWriteCompleteFlag = FALSE;
817
818        NdefMap->TopazContainer.CurrentSeg = 0;
819        NdefMap->TopazContainer.CurrentBlock = 1;
820        NdefMap->TopazContainer.WriteSeq = 0;
821
822#ifdef TOPAZ_RAW_SUPPORT
823
824        *NdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ8;
825
826#else
827
828        /* Topaz command = Jewel Nxp Read */
829#ifdef PH_HAL4_ENABLE
830        NdefMap->Cmd.JewelCmd = phHal_eJewel_Read;
831#else
832        NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead;
833#endif
834
835        NdefMap->Cmd.JewelCmd = phHal_eJewel_Read8;
836
837#endif /* #ifdef TOPAZ_RAW_SUPPORT */
838        /* Call read segment */
839        Result = phFriNfc_Tpz_H_NxpRead (NdefMap);
840    }
841    else
842    {
843#if 0
844        /* This part is to handle the Current offset,
845        Current offset is not yet validated */
846        Result = phFriNfc_Tpz_H_NxpWrite(NdefMap);
847#endif /* #if 0 */
848    }
849
850    return Result;
851}
852
853
854/*!
855* \brief Completion Routine, Processing function, needed to avoid long blocking.
856* \note The lower (Overlapped HAL) layer must register a pointer to this function as a Completion
857*       Routine in order to be able to notify the component that an I/O has finished and data are
858*       ready to be processed.
859*
860*/
861
862void phFriNfc_TopazDynamicMap_Process( void       *Context,
863                               NFCSTATUS   Status)
864{
865
866    phFriNfc_NdefMap_t      *NdefMap;
867
868    NdefMap = (phFriNfc_NdefMap_t *)Context;
869
870
871    if((NFCSTATUS_SUCCESS & PHNFCSTBLOWER) == (Status & PHNFCSTBLOWER))
872    {
873        switch(NdefMap->State)
874        {
875            case PH_FRINFC_TOPAZ_STATE_READ:
876            {
877                Status = phFriNfc_Tpz_H_ProReadResp (NdefMap);
878                break;
879            }
880
881            case PH_FRINFC_TOPAZ_STATE_WRITE:
882            {
883                Status =  phFriNfc_Tpz_H_ProWrResp (NdefMap);
884                break;
885            }
886
887            case PH_FRINFC_TOPAZ_STATE_RD_FOR_WR_NDEF:
888            {
889                Status =  phFriNfc_Tpz_H_ProRdForWrResp (NdefMap);
890                break;
891            }
892
893            case PH_FRINFC_TOPAZ_STATE_READID:
894            {
895                Status = phFriNfc_Tpz_H_ChkReadID(NdefMap);
896                break;
897            }
898
899#ifdef FRINFC_READONLY_NDEF
900            case PH_FRINFC_TOPAZ_STATE_READ_ONLY:
901            {
902                Status = phFriNfc_Tpz_H_ProcessReadOnly (NdefMap);
903                break;
904            }
905#endif /* #ifdef FRINFC_READONLY_NDEF */
906
907            default:
908            {
909                Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
910                                    NFCSTATUS_INVALID_DEVICE_REQUEST);
911                break;
912            }
913        }
914    }
915
916    /* Call for the Completion Routine*/
917    if(Status != NFCSTATUS_PENDING)
918    {
919        phFriNfc_Tpz_H_Complete(NdefMap, Status);
920    }
921}
922
923#ifdef FRINFC_READONLY_NDEF
924
925static
926NFCSTATUS
927phFriNfc_Tpz_H_UpdateAndWriteLockBits (
928    phFriNfc_NdefMap_t          *psNdefMap)
929{
930    NFCSTATUS                       result = NFCSTATUS_SUCCESS;
931    phFriNfc_TopazCont_t            *ps_tpz_info = NULL;
932    phFriNfc_LockCntrlTLVCont_t     *ps_locktlv_info = NULL;
933    uint8_t                         remaining_lock_bits = 0;
934    uint8_t                         byte_index = 0;
935    uint8_t                         lock_bytes_value[TOPAZ_BYTES_PER_BLOCK] = {0};
936    uint8_t                         lock_byte_index = 0;
937    uint8_t                         no_of_bits_left_in_block = 0;
938
939    ps_tpz_info = &(psNdefMap->TopazContainer);
940    ps_locktlv_info = &(psNdefMap->LockTlv);
941
942    (void)memcpy ((void *)lock_bytes_value, (void *)psNdefMap->SendRecvBuf,
943                    TOPAZ_BYTES_PER_BLOCK);
944
945    if (ps_tpz_info->CurrentBlock == ps_locktlv_info->BlkNum)
946    {
947        /* Get the lock bits that has to locked */
948        remaining_lock_bits = ps_locktlv_info->LockTlvBuff[1];
949        byte_index = (uint8_t)ps_locktlv_info->ByteNum;
950    }
951    else
952    {
953        /* This condition applies only for the lock bits not ending with
954        " ps_locktlv_info->BlkNum ".
955        Calculate the remaining lock bits */
956        remaining_lock_bits = (uint8_t)(ps_locktlv_info->LockTlvBuff[1] -
957                    ps_tpz_info->lock_bytes_written);
958    }
959
960    no_of_bits_left_in_block = (uint8_t)((TOPAZ_BYTES_PER_BLOCK - byte_index) *
961                                TOPAZ_BYTE_SIZE_IN_BITS);
962
963    if (no_of_bits_left_in_block >= remaining_lock_bits)
964    {
965        /* Entire lock bits can be written */
966        uint8_t                 mod_value = 0;
967
968        mod_value = (uint8_t)(remaining_lock_bits % TOPAZ_BYTES_PER_BLOCK);
969
970        if (mod_value)
971        {
972            /* The lock bits ends in between of a byte */
973            /* lock bits to write is greater than 8 bits */
974            if (mod_value > TOPAZ_BYTE_SIZE_IN_BITS)
975            {
976                while (lock_byte_index <
977                    (TOPAZ_CONVERT_BITS_TO_BYTES(remaining_lock_bits) - 1))
978                {
979                    /* Set 1b to all bits left in the block */
980                    lock_bytes_value[byte_index] = 0xFF;
981                    lock_byte_index = (uint8_t)(lock_byte_index + 1);
982                    byte_index = (uint8_t)(byte_index + 1);
983                }
984                /* Last byte of the lock bits shall be filled partially,
985                    Set only the remaining lock bits and dont change
986                    the other bit value */
987                lock_bytes_value[byte_index] = 0;
988                lock_bytes_value[byte_index] = (uint8_t)
989                        SET_BITS8 (lock_bytes_value[byte_index], 0,
990                                    mod_value, 1);
991            }
992            else
993            {
994                /* lock bits to write is less than 8 bits, so
995                    there is only one byte to write.
996                    Set only the remaining lock bits and dont change
997                    the other bit value */
998                lock_bytes_value[0] = (uint8_t)
999                        SET_BITS8 (lock_bytes_value[0], 0,
1000                                    mod_value, 1);
1001            }
1002        } /* if (mod_value) */
1003        else
1004        {
1005            /* The lock bits exactly ends at a byte
1006            MOD operation is 00, that means entire byte value shall be 0xFF, means
1007            every bit shall be to 1 */
1008
1009            while (lock_byte_index < TOPAZ_CONVERT_BITS_TO_BYTES(remaining_lock_bits))
1010            {
1011                /* Set 1b to all bits left in the block */
1012                lock_bytes_value[byte_index] = 0xFF;
1013                lock_byte_index = (uint8_t)(lock_byte_index + 1);
1014                byte_index = (uint8_t)(byte_index + 1);
1015            }
1016        } /* else of if (mod_value) */
1017        ps_tpz_info->lock_bytes_written = remaining_lock_bits;
1018    }
1019    else /* if (no_of_bits_left_in_block >= remaining_lock_bits) */
1020    {
1021        /* Partial lock bits can be written. use next read to write
1022            the remaining lock bits  */
1023        while (lock_byte_index <  (no_of_bits_left_in_block /
1024                            TOPAZ_BYTES_PER_BLOCK))
1025        {
1026            /* Set 1b to all bits left in the block */
1027            lock_bytes_value[byte_index] = 0xFF;
1028            lock_byte_index = (uint8_t)(lock_byte_index + 1);
1029            byte_index = (uint8_t)(byte_index + 1);
1030        }
1031        ps_tpz_info->lock_bytes_written = (uint8_t)(no_of_bits_left_in_block /
1032                            TOPAZ_BYTES_PER_BLOCK);
1033    } /* else of if (no_of_bits_left_in_block >= remaining_lock_bits) */
1034
1035#ifdef TOPAZ_RAW_SUPPORT
1036    *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_E8;
1037#else
1038    psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write8E;
1039#endif /* #ifdef TOPAZ_RAW_SUPPORT */
1040
1041    result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, lock_bytes_value,
1042                                    sizeof (lock_bytes_value));
1043    return result;
1044}
1045
1046static
1047NFCSTATUS
1048phFriNfc_Tpz_H_ProcessReadOnly (
1049    phFriNfc_NdefMap_t          *psNdefMap)
1050{
1051    NFCSTATUS                           result = NFCSTATUS_SUCCESS;
1052    phFriNfc_Tpz_RO_Seq_t               e_readonly_seq = RD_LOCK_BYTES;
1053    phFriNfc_TopazCont_t                *ps_tpz_info = NULL;
1054    phFriNfc_LockCntrlTLVCont_t         *ps_locktlv_info = NULL;
1055    static uint8_t                      static_lock_bytes[2] = {0};
1056
1057    ps_tpz_info = &(psNdefMap->TopazContainer);
1058    ps_locktlv_info = &(psNdefMap->LockTlv);
1059    e_readonly_seq = (phFriNfc_Tpz_RO_Seq_t)psNdefMap->TopazContainer.read_only_seq;
1060
1061    switch (e_readonly_seq)
1062    {
1063        case WR_READONLY_CC:
1064        {
1065            if (TOPAZ_WRITE_1_RESPONSE == *psNdefMap->SendRecvLength)
1066            {
1067                psNdefMap->TopazContainer.CurrentBlock = (uint8_t)
1068                                psNdefMap->LockTlv.BlkNum;
1069
1070                e_readonly_seq = RD_LOCK_BYTES;
1071#ifdef TOPAZ_RAW_SUPPORT
1072
1073                *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ8;
1074
1075#else
1076
1077        /* Topaz command = Jewel Nxp Read */
1078#ifdef PH_HAL4_ENABLE
1079                psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read;
1080#else
1081                psNdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead;
1082#endif
1083
1084                psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read8;
1085
1086#endif /* #ifdef TOPAZ_RAW_SUPPORT */
1087                /* Call read segment */
1088                result = phFriNfc_Tpz_H_NxpRead (psNdefMap);
1089            }
1090            else
1091            {
1092                result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1093                                    NFCSTATUS_INVALID_RECEIVE_LENGTH);
1094            }
1095            break;
1096        }
1097
1098        case RD_LOCK_BYTES:
1099        {
1100            if (TOPAZ_READ_8_RESPONSE == *psNdefMap->SendRecvLength)
1101            {
1102                result = phFriNfc_Tpz_H_UpdateAndWriteLockBits (psNdefMap);
1103
1104                if (NFCSTATUS_PENDING == result)
1105                {
1106                    e_readonly_seq = WR_LOCK_BYTES;
1107                }
1108            }
1109            else
1110            {
1111                result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1112                                    NFCSTATUS_INVALID_RECEIVE_LENGTH);
1113            }
1114            break;
1115        }
1116
1117        case WR_LOCK_BYTES:
1118        {
1119            if (TOPAZ_WRITE_8_RESPONSE == *psNdefMap->SendRecvLength)
1120            {
1121                ps_tpz_info->CurrentBlock = (uint8_t)
1122                                        (ps_tpz_info->CurrentBlock + 1);
1123                if (ps_locktlv_info->LockTlvBuff[1] -
1124                    ps_tpz_info->lock_bytes_written)
1125                {
1126#ifdef TOPAZ_RAW_SUPPORT
1127
1128                    *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ8;
1129
1130#else
1131
1132                    /* Topaz command = Jewel Nxp Read */
1133#ifdef PH_HAL4_ENABLE
1134                    psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read;
1135#else
1136                    psNdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead;
1137#endif
1138
1139                    psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read8;
1140
1141#endif /* #ifdef TOPAZ_RAW_SUPPORT */
1142                    /* Call read segment */
1143                    result = phFriNfc_Tpz_H_NxpRead (psNdefMap);
1144                    e_readonly_seq = RD_LOCK_BYTES;
1145                }
1146                else
1147                {
1148                    ps_tpz_info->CurrentBlock = (uint8_t)
1149                                        DYN_STATIC_LOCK_BLOCK_NUM;
1150                    ps_tpz_info->ByteNumber = (uint8_t)
1151                                        DYN_STATIC_LOCK0_BYTE_NUM;
1152#ifdef TOPAZ_RAW_SUPPORT
1153
1154                    *psNdefMap->SendRecvBuf = (uint8_t)PH_FRINFC_TOPAZ_CMD_READ8;
1155
1156#else
1157
1158                    /* Topaz command = Jewel Nxp Read */
1159#ifdef PH_HAL4_ENABLE
1160                    psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read;
1161#else
1162                    psNdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead;
1163#endif
1164
1165                    psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read8;
1166
1167#endif /* #ifdef TOPAZ_RAW_SUPPORT */
1168                    /* Call read segment */
1169                    result = phFriNfc_Tpz_H_NxpRead (psNdefMap);
1170                    e_readonly_seq = RD_STATIC_LOCK_BYTE0;
1171
1172                }
1173            }
1174            else
1175            {
1176                result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1177                                    NFCSTATUS_INVALID_RECEIVE_LENGTH);
1178            }
1179            break;
1180        }
1181
1182        case RD_STATIC_LOCK_BYTE0:
1183        {
1184            if (TOPAZ_READ_8_RESPONSE == *psNdefMap->SendRecvLength)
1185            {
1186                uint8_t                 lock_byte_value = 0;
1187
1188                (void)memcpy ((void *)static_lock_bytes,
1189                            (void *)(psNdefMap->SendRecvBuf +
1190                                ps_tpz_info->ByteNumber),
1191                            sizeof (static_lock_bytes));
1192
1193
1194                lock_byte_value = (uint8_t)(static_lock_bytes[0] |
1195                                    DYN_STATIC_LOCK0_BYTE_VALUE);
1196
1197#ifdef TOPAZ_RAW_SUPPORT
1198                    *psNdefMap->SendRecvBuf = (uint8_t)PH_FRINFC_TOPAZ_CMD_WRITE_1E;
1199#else
1200                    psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E;
1201#endif /* #ifdef TOPAZ_RAW_SUPPORT */
1202
1203                result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, &lock_byte_value,
1204                                                    1);
1205
1206                    if (NFCSTATUS_PENDING == result)
1207                    {
1208                    e_readonly_seq = (uint8_t)WR_STATIC_LOCK_BYTE0;
1209                    }
1210                }
1211            else
1212            {
1213                result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1214                                    NFCSTATUS_INVALID_RECEIVE_LENGTH);
1215            }
1216            break;
1217        }
1218
1219        case WR_STATIC_LOCK_BYTE0:
1220        {
1221            if (TOPAZ_WRITE_1_RESPONSE == *psNdefMap->SendRecvLength)
1222            {
1223                uint8_t                 lock_byte_value =
1224                                        (static_lock_bytes[1] |
1225                                        DYN_STATIC_LOCK1_BYTE_VALUE);
1226
1227                ps_tpz_info->CurrentBlock = (uint8_t)
1228                                    DYN_STATIC_LOCK_BLOCK_NUM;
1229                ps_tpz_info->ByteNumber = (uint8_t)
1230                                    DYN_STATIC_LOCK1_BYTE_NUM;
1231#ifdef TOPAZ_RAW_SUPPORT
1232                *psNdefMap->SendRecvBuf = (uint8_t)PH_FRINFC_TOPAZ_CMD_WRITE_1E;
1233#else
1234                psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E;
1235#endif /* #ifdef TOPAZ_RAW_SUPPORT */
1236
1237                result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, &lock_byte_value,
1238                                                    1);
1239
1240                if (NFCSTATUS_PENDING == result)
1241                {
1242                    e_readonly_seq = (uint8_t)WR_STATIC_LOCK_BYTE1;
1243                }
1244            }
1245            else
1246            {
1247                result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1248                                    NFCSTATUS_INVALID_RECEIVE_LENGTH);
1249            }
1250            break;
1251        }
1252
1253        case WR_STATIC_LOCK_BYTE1:
1254        {
1255            if (TOPAZ_WRITE_1_RESPONSE == *psNdefMap->SendRecvLength)
1256            {
1257                /* READ ONLY successful */
1258            }
1259            else
1260            {
1261                result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1262                                    NFCSTATUS_INVALID_RECEIVE_LENGTH);
1263            }
1264            break;
1265        }
1266
1267        default:
1268        {
1269            result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1270                                    NFCSTATUS_INVALID_RECEIVE_LENGTH);
1271            break;
1272        }
1273    }
1274
1275    psNdefMap->TopazContainer.read_only_seq = (uint8_t)e_readonly_seq;
1276    return result;
1277}
1278
1279#endif /* #ifdef FRINFC_READONLY_NDEF */
1280
1281static
1282NFCSTATUS
1283phFriNfc_Tpz_H_ProWrResp (
1284    phFriNfc_NdefMap_t          *psNdefMap)
1285{
1286    NFCSTATUS                           result = NFCSTATUS_SUCCESS;
1287    phFriNfc_TopazCont_t                *ps_tpz_info = NULL;
1288    phFriNfc_Tpz_WrSeq_t                write_seq;
1289    uint8_t                             write_buf[] = {0x00};
1290    uint8_t                             write_index = 0;
1291    uint16_t                            write_len = 0;
1292    uint16_t                            len_byte_addr = 0;
1293
1294    ps_tpz_info = &(psNdefMap->TopazContainer);
1295    write_seq = (phFriNfc_Tpz_WrSeq_t)(ps_tpz_info->WriteSeq);
1296    write_len = (uint16_t)((psNdefMap->ApduBufferSize < ps_tpz_info->NDEFRWSize) ?
1297                psNdefMap->ApduBufferSize : ps_tpz_info->NDEFRWSize);
1298
1299    switch (write_seq)
1300    {
1301        case WR_NDEF_T_TLV:
1302        {
1303            /* TYPE field of the NDEF TLV write is complete */
1304            if (TOPAZ_WRITE_8_RESPONSE == *psNdefMap->SendRecvLength)
1305            {
1306                psNdefMap->State = (uint8_t)
1307                                    PH_FRINFC_TOPAZ_STATE_WRITE;
1308
1309                /* Now, Write 0 to the magic number byte */
1310                ps_tpz_info->WriteSeq = (uint8_t)WR_NMN_0;
1311                write_seq = WR_NMN_0;
1312                ps_tpz_info->CurrentBlock = 1;
1313                ps_tpz_info->ByteNumber = 0;
1314
1315#ifdef TOPAZ_RAW_SUPPORT
1316                *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_1E;
1317#else
1318                psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E;
1319#endif /* #ifdef TOPAZ_RAW_SUPPORT */
1320                result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, write_buf,
1321                                                sizeof (write_buf));
1322            }
1323            else
1324            {
1325                result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1326                                    NFCSTATUS_INVALID_RECEIVE_LENGTH);
1327            }
1328            break;
1329        }
1330
1331        case WR_NMN_0:
1332        {
1333            /* Magic number set to 0 write is complete */
1334            if (TOPAZ_WRITE_1_RESPONSE == *psNdefMap->SendRecvLength)
1335            {
1336                ps_tpz_info->WriteSeq = (uint8_t)(write_seq + 1);
1337                write_seq = (phFriNfc_Tpz_WrSeq_t)(write_seq + 1);
1338                /* Now the sequence = WR_LEN_1_0, so Length block is read,
1339                    and only length bytes are made 0, before writing data to 0
1340                */
1341                result = phFriNfc_Tpz_H_RdForWrite (psNdefMap);
1342            }
1343            else
1344            {
1345                result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1346                                    NFCSTATUS_INVALID_RECEIVE_LENGTH);
1347            }
1348            break;
1349        }
1350
1351        case WR_LEN_1_0:
1352        {
1353            /* Length field is updated with the value 0 */
1354            if (TOPAZ_WRITE_8_RESPONSE != *psNdefMap->SendRecvLength)
1355            {
1356                result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1357                                    NFCSTATUS_INVALID_RECEIVE_LENGTH);
1358            }
1359            else if (write_len >= 0xFF)
1360            {
1361                ps_tpz_info->ByteNumber = 0;
1362
1363                ps_tpz_info->CurrentBlock = (uint8_t)
1364                                    TOPAZ_INCREMENT_SKIP_STATIC_BLOCK (
1365                                    ps_tpz_info->CurrentBlock);
1366
1367                ps_tpz_info->WriteSeq = (uint8_t)(write_seq + 1);
1368                write_seq = (phFriNfc_Tpz_WrSeq_t)(write_seq + 1);
1369                /* Now the sequence = WR_LEN_1_1, so Length block is read,
1370                    and only length bytes are made 0, before writing data to 0
1371                */
1372                result = phFriNfc_Tpz_H_RdForWrite (psNdefMap);
1373            }
1374            else
1375            {
1376                /* NDEF data length < 0xFF */
1377                len_byte_addr = phFriNfc_Tpz_H_GetNDEFValueFieldAddrForWrite
1378                                                (psNdefMap, write_len);
1379                ps_tpz_info->CurrentBlock = (uint8_t)
1380                        TOPAZ_BLK_FROM_BYTE_ADR (len_byte_addr);
1381                ps_tpz_info->ByteNumber = (uint8_t)
1382                        TOPAZ_BYTE_OFFSET_FROM_BYTE_ADR (len_byte_addr);
1383
1384
1385                ps_tpz_info->WriteSeq = (uint8_t)WR_DATA;
1386                write_seq = WR_DATA;
1387
1388                if (0 != ps_tpz_info->ByteNumber)
1389                {
1390                    /* If data starts in between the block then read
1391                        the data */
1392                    result = phFriNfc_Tpz_H_RdForWrite (psNdefMap);
1393                }
1394                else
1395                {
1396                    /* Data starts at the beginning of the block, so start
1397                        writing the user data */
1398                    result = phFriNfc_Tpz_H_CopySendWrData (psNdefMap);
1399                }
1400            }
1401            break;
1402        }
1403
1404        case WR_LEN_2_0:
1405        case WR_LEN_2_VALUE:
1406        {
1407            /* 2nd length field is updated with the value 0 or the correct
1408                written value */
1409            if (TOPAZ_WRITE_8_RESPONSE != *psNdefMap->SendRecvLength)
1410            {
1411                result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1412                                    NFCSTATUS_INVALID_RECEIVE_LENGTH);
1413            }
1414            else
1415            {
1416                ps_tpz_info->ByteNumber = 0;
1417                ps_tpz_info->CurrentBlock = (uint8_t)
1418                                    TOPAZ_INCREMENT_SKIP_STATIC_BLOCK (
1419                                    ps_tpz_info->CurrentBlock);
1420                ps_tpz_info->WriteSeq = (uint8_t)(write_seq + 1);
1421                write_seq = (phFriNfc_Tpz_WrSeq_t)(write_seq + 1);
1422                /* If length byte starts in between the block then read
1423                    the length block */
1424                result = phFriNfc_Tpz_H_RdForWrite (psNdefMap);
1425            }
1426            break;
1427        }
1428
1429        case WR_LEN_3_0:
1430        {
1431            /* 3rd length field is updated with the value 0 */
1432            if (TOPAZ_WRITE_8_RESPONSE != *psNdefMap->SendRecvLength)
1433            {
1434                result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1435                                    NFCSTATUS_INVALID_RECEIVE_LENGTH);
1436            }
1437            else
1438            {
1439                len_byte_addr = phFriNfc_Tpz_H_GetNDEFValueFieldAddrForWrite
1440                                                (psNdefMap, write_len);
1441                ps_tpz_info->CurrentBlock = (uint8_t)
1442                        TOPAZ_BLK_FROM_BYTE_ADR (len_byte_addr);
1443                ps_tpz_info->ByteNumber = (uint8_t)
1444                        TOPAZ_BYTE_OFFSET_FROM_BYTE_ADR (len_byte_addr);
1445
1446                ps_tpz_info->WriteSeq = (uint8_t)(write_seq + 1);
1447                write_seq = (phFriNfc_Tpz_WrSeq_t)(write_seq + 1);
1448
1449                if (0 != ps_tpz_info->ByteNumber)
1450                {
1451                    /* If data starts in between the block then read
1452                        the data */
1453                    result = phFriNfc_Tpz_H_RdForWrite (psNdefMap);
1454                }
1455                else
1456                {
1457                    /* Data starts at the beginning of the block, so start
1458                        writing the user data */
1459                    result = phFriNfc_Tpz_H_CopySendWrData (psNdefMap);
1460                }
1461            }
1462            break;
1463        }
1464
1465        case WR_DATA:
1466        {
1467            /* Data is written from the input buffer */
1468            if (TOPAZ_WRITE_8_RESPONSE != *psNdefMap->SendRecvLength)
1469            {
1470                result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1471                                    NFCSTATUS_INVALID_RECEIVE_LENGTH);
1472            }
1473            else if (write_len == psNdefMap->ApduBuffIndex)
1474            {
1475                /* Data to be written is completely written to the card */
1476                *psNdefMap->WrNdefPacketLength = psNdefMap->ApduBuffIndex;
1477                ps_tpz_info->WriteSeq = (uint8_t)WR_LEN_1_VALUE;
1478                write_seq = WR_LEN_1_VALUE;
1479                /* To write the first length byte, it has to be read and then
1480                    the length has to be updated */
1481                result = phFriNfc_Tpz_H_RdForWrite (psNdefMap);
1482            }
1483            else
1484            {
1485                ps_tpz_info->ByteNumber = 0;
1486                /* Go to the next block */
1487                ps_tpz_info->CurrentBlock = (uint8_t)
1488                                    TOPAZ_INCREMENT_SKIP_STATIC_BLOCK (
1489                                    ps_tpz_info->CurrentBlock);
1490                /* Copy and write the user data */
1491                result = phFriNfc_Tpz_H_CopySendWrData (psNdefMap);
1492            }
1493            break;
1494        }
1495
1496        case WR_DATA_READ_REQD:
1497        {
1498            /* This sequence is executed, if the first read has some
1499                lock or reserved blocks bytes and the lock or reserved
1500                blocks are extended to the next block  */
1501            if (TOPAZ_WRITE_8_RESPONSE != *psNdefMap->SendRecvLength)
1502            {
1503                result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1504                                    NFCSTATUS_INVALID_RECEIVE_LENGTH);
1505            }
1506            else
1507            {
1508                ps_tpz_info->ByteNumber = 0;
1509                /* Go to the next block */
1510                ps_tpz_info->CurrentBlock = (uint8_t)
1511                                    TOPAZ_INCREMENT_SKIP_STATIC_BLOCK (
1512                                    ps_tpz_info->CurrentBlock);
1513                /* Write is complete for one block, now because lock bytes are
1514                    shifted to next blocks, the next block is read and update
1515                    the written data by skipping the lock or reserved memory bytes */
1516                result = phFriNfc_Tpz_H_RdForWrite (psNdefMap);
1517            }
1518            break;
1519        }
1520
1521        case WR_LEN_3_VALUE:
1522        {
1523            /* 3rd LENGTH field byte is updated with correct written value */
1524            if (TOPAZ_WRITE_8_RESPONSE != *psNdefMap->SendRecvLength)
1525            {
1526                result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1527                                    NFCSTATUS_INVALID_RECEIVE_LENGTH);
1528            }
1529            else
1530            {
1531#ifdef TOPAZ_RAW_SUPPORT
1532                *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_1E;
1533#else
1534                psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E;
1535#endif /* #ifdef TOPAZ_RAW_SUPPORT */
1536
1537                psNdefMap->State = (uint8_t)PH_FRINFC_TOPAZ_STATE_WRITE;
1538
1539                write_buf[write_index] = PH_FRINFC_TOPAZ_CC_BYTE0;
1540                write_index = (uint8_t)(write_index + 1);
1541
1542                ps_tpz_info->ByteNumber = 0;
1543                ps_tpz_info->CurrentBlock = 1;
1544
1545                ps_tpz_info->WriteSeq = (uint8_t)WR_NMN_E1;
1546                write_seq = WR_NMN_E1;
1547
1548                /* Length byte write is complete, so now update the magic
1549                    number byte with value 0xE1 */
1550                result = phFriNfc_Tpz_H_NxpWrite(psNdefMap, write_buf,
1551                                                write_index);
1552            }
1553            break;
1554        }
1555
1556        case WR_LEN_1_VALUE:
1557        {
1558            /* 1st LENGTH field byte is updated */
1559            if (TOPAZ_WRITE_8_RESPONSE != *psNdefMap->SendRecvLength)
1560            {
1561                result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1562                                    NFCSTATUS_INVALID_RECEIVE_LENGTH);
1563            }
1564            else if (write_len < 0xFF)
1565            {
1566                /* Total length to write is less than 0xFF, so LENGTH field has
1567                    only one byte, then update the magic number byte with
1568                    value 0xE1 */
1569#ifdef TOPAZ_RAW_SUPPORT
1570                *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_1E;
1571#else
1572                psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E;
1573#endif /* #ifdef TOPAZ_RAW_SUPPORT */
1574                psNdefMap->State = (uint8_t)PH_FRINFC_TOPAZ_STATE_WRITE;
1575
1576                write_buf[write_index] = PH_FRINFC_TOPAZ_CC_BYTE0;
1577                write_index = (uint8_t)(write_index + 1);
1578
1579                ps_tpz_info->ByteNumber = 0;
1580                ps_tpz_info->CurrentBlock = 1;
1581
1582                ps_tpz_info->WriteSeq = (uint8_t)WR_NMN_E1;
1583                write_seq = WR_NMN_E1;
1584                result = phFriNfc_Tpz_H_NxpWrite(psNdefMap, write_buf,
1585                                                write_index);
1586            }
1587            else
1588            {
1589                /* 2nd byte of the LENGTH field has to be updated so,
1590                    read the block, before updating it */
1591                ps_tpz_info->ByteNumber = 0;
1592                ps_tpz_info->CurrentBlock = (uint8_t)
1593                                    TOPAZ_INCREMENT_SKIP_STATIC_BLOCK (
1594                                    ps_tpz_info->CurrentBlock);
1595                ps_tpz_info->WriteSeq = (uint8_t)WR_LEN_2_VALUE;
1596                write_seq = WR_LEN_2_VALUE;
1597                result = phFriNfc_Tpz_H_RdForWrite (psNdefMap);
1598            }
1599            break;
1600        }
1601
1602        case WR_NMN_E1:
1603        {
1604            /* Magic number is written, so update the actual ndef length.  */
1605            if (TOPAZ_WRITE_1_RESPONSE == *psNdefMap->SendRecvLength)
1606            {
1607                *psNdefMap->WrNdefPacketLength = (uint32_t)
1608                                                psNdefMap->ApduBuffIndex;
1609                ps_tpz_info->ActualNDEFMsgSize = (uint16_t)
1610                                                psNdefMap->ApduBuffIndex;
1611            }
1612            else
1613            {
1614                result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1615                                    NFCSTATUS_INVALID_RECEIVE_LENGTH);
1616            }
1617            break;
1618        }
1619
1620        default:
1621        {
1622            break;
1623        }
1624    }
1625
1626    return result;
1627}
1628
1629static
1630NFCSTATUS
1631phFriNfc_Tpz_H_UpdateNdefTypeField (
1632    phFriNfc_NdefMap_t          *psNdefMap)
1633{
1634    NFCSTATUS                           result = NFCSTATUS_SUCCESS;
1635    phFriNfc_TopazCont_t                *ps_tpz_info = NULL;
1636    uint8_t                             write_buf[TOPAZ_WRITE_8_DATA_LENGTH];
1637
1638    ps_tpz_info = &(psNdefMap->TopazContainer);
1639
1640    (void)memcpy ((void *)write_buf, (void *)
1641                psNdefMap->SendRecvBuf, TOPAZ_WRITE_8_DATA_LENGTH);
1642
1643    /* Update the TYPE field of the NDEF TLV */
1644    write_buf[ps_tpz_info->ByteNumber] = PH_FRINFC_TOPAZ_NDEF_T;
1645
1646    psNdefMap->State = (uint8_t)PH_FRINFC_TOPAZ_STATE_WRITE;
1647
1648#ifdef TOPAZ_RAW_SUPPORT
1649    *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_E8;
1650#else
1651    psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write8E;
1652#endif /* #ifdef TOPAZ_RAW_SUPPORT */
1653    result = phFriNfc_Tpz_H_NxpWrite(psNdefMap, write_buf,
1654                                    sizeof (write_buf));
1655
1656    return result;
1657}
1658
1659static
1660NFCSTATUS
1661phFriNfc_Tpz_H_ProRdForWrResp (
1662    phFriNfc_NdefMap_t          *psNdefMap)
1663{
1664    /* This function is used during the write operation */
1665    NFCSTATUS                           result = NFCSTATUS_SUCCESS;
1666    phFriNfc_TopazCont_t                *ps_tpz_info = NULL;
1667
1668    ps_tpz_info = &(psNdefMap->TopazContainer);
1669
1670    psNdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE;
1671
1672    if (TOPAZ_READ_8_RESPONSE == *psNdefMap->SendRecvLength)
1673    {
1674        switch ((phFriNfc_Tpz_WrSeq_t)ps_tpz_info->WriteSeq)
1675        {
1676            case WR_NDEF_T_TLV:
1677            {
1678                /* Read bytes are for updating the TYPE field of the NDEF TLV */
1679                result = phFriNfc_Tpz_H_UpdateNdefTypeField (psNdefMap);
1680                break;
1681            }
1682
1683            case WR_LEN_1_0:
1684            case WR_LEN_2_0:
1685            case WR_LEN_3_0:
1686            {
1687                /* Read bytes are for updating the LENGTH field to 0 of the NDEF TLV and
1688                also to update the data from the user buffer */
1689                result = phFriNfc_Tpz_H_UpdateLenFieldZeroAfterRead (psNdefMap);
1690                break;
1691            }
1692
1693            case WR_DATA:
1694            case WR_DATA_READ_REQD:
1695            {
1696                /* Read bytes are for skipping the lock and reserved bytes */
1697                result = phFriNfc_Tpz_H_CopyReadDataAndWrite (psNdefMap);
1698                break;
1699            }
1700
1701            case WR_LEN_1_VALUE:
1702            case WR_LEN_2_VALUE:
1703            case WR_LEN_3_VALUE:
1704            {
1705                /* Read bytes are for updating the LENGTH field to the correct values
1706                    of the NDEF TLV */
1707                result = phFriNfc_Tpz_H_UpdateLenFieldValuesAfterRead (psNdefMap);
1708                break;
1709            }
1710
1711            default:
1712            {
1713                /* Code must not come come here */
1714                break;
1715            }
1716        }
1717    }
1718    else
1719    {
1720        /* Error in the length, wither the HW has sent wrong response length or
1721            the response length byte is corrupted */
1722        result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1723                            NFCSTATUS_INVALID_RECEIVE_LENGTH);
1724    }
1725
1726
1727    return result;
1728}
1729
1730static
1731NFCSTATUS
1732phFriNfc_Tpz_H_ChkReadID(
1733    phFriNfc_NdefMap_t      *psNdefMap)
1734{
1735    NFCSTATUS   result = NFCSTATUS_SUCCESS;
1736    int         compare_result = 0;
1737    uint8_t     recv_index = 0;
1738
1739
1740    if (PH_FRINFC_TOPAZ_VAL6 == *psNdefMap->SendRecvLength)
1741    {
1742        if (((psNdefMap->SendRecvBuf[recv_index] &
1743            PH_FRINFC_TOPAZ_HEADROM0_CHK) == PH_FRINFC_TOPAZ_DYNAMIC_HEADROM0_VAL))
1744        {
1745            /* Copy UID to the context*/
1746            compare_result = phOsalNfc_MemCompare (
1747                                psNdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid,
1748                                &psNdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2],
1749                                TOPAZ_UID_LENGTH_FOR_READ_WRITE);
1750            if (0 == compare_result)
1751            {
1752                /* State has to be changed */
1753                psNdefMap->State = PH_FRINFC_TOPAZ_STATE_READ;
1754
1755                /* Topaz command = READSEG */
1756#ifdef TOPAZ_RAW_SUPPORT
1757
1758                *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_RSEG;
1759
1760#else
1761
1762#ifdef PH_HAL4_ENABLE
1763                psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read;
1764#else
1765                psNdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead;
1766#endif
1767                psNdefMap->Cmd.JewelCmd = phHal_eJewel_ReadSeg;
1768
1769#endif /* #ifdef TOPAZ_RAW_SUPPORT */
1770                /* Read bytes from the card */
1771                result = phFriNfc_Tpz_H_NxpRead (psNdefMap);
1772            }
1773            else
1774            {
1775                result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1776                                    NFCSTATUS_NO_NDEF_SUPPORT);
1777
1778            }
1779        }
1780    }
1781    else
1782    {
1783        result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1784                            NFCSTATUS_INVALID_RECEIVE_LENGTH);
1785    }
1786
1787    return result;
1788}
1789
1790#define TOPAZ_READ_ID_ZERO_LENGTH                   (0x06U)
1791static
1792NFCSTATUS
1793phFriNfc_Tpz_H_NxpRead (
1794    phFriNfc_NdefMap_t          *psNdefMap)
1795{
1796    NFCSTATUS           result = NFCSTATUS_SUCCESS;
1797    uint8_t             send_index = 0;
1798#ifdef TOPAZ_RAW_SUPPORT
1799    uint8_t             read_append[] = { 0x00, 0x00, 0x00, 0x00,
1800                                        0x00, 0x00, 0x00, 0x00};
1801#endif /* #ifdef TOPAZ_RAW_SUPPORT */
1802
1803    /* set the data for additional data exchange*/
1804    psNdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = PH_FRINFC_TOPAZ_VAL0;
1805    psNdefMap->psDepAdditionalInfo.DepFlags.NADPresent = PH_FRINFC_TOPAZ_VAL0;
1806    psNdefMap->psDepAdditionalInfo.NAD = PH_FRINFC_TOPAZ_VAL0;
1807
1808    psNdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_TopazDynamicMap_Process;
1809    psNdefMap->MapCompletionInfo.Context = psNdefMap;
1810
1811    *psNdefMap->SendRecvLength = psNdefMap->TempReceiveLength;
1812
1813    /* Depending on the jewel command, the send length is decided */
1814#ifdef TOPAZ_RAW_SUPPORT
1815
1816    psNdefMap->Cmd.JewelCmd = phHal_eJewel_Raw;
1817    /* " send_index " is incremented because already received buffer is filled with
1818        TOPAZ command */
1819    send_index = (uint8_t)(send_index + 1);
1820
1821    switch (*psNdefMap->SendRecvBuf)
1822#else
1823    switch(psNdefMap->Cmd.JewelCmd)
1824#endif /* #ifdef TOPAZ_RAW_SUPPORT */
1825    {
1826#ifdef TOPAZ_RAW_SUPPORT
1827
1828        case PH_FRINFC_TOPAZ_CMD_READID:
1829        {
1830            (void)memcpy ((void *)(psNdefMap->SendRecvBuf + send_index),
1831                        (void *)read_append, TOPAZ_READ_ID_ZERO_LENGTH);
1832            send_index = (uint8_t)(send_index + TOPAZ_READ_ID_ZERO_LENGTH);
1833            break;
1834        }
1835
1836        case PH_FRINFC_TOPAZ_CMD_READ8:
1837        {
1838            psNdefMap->SendRecvBuf[send_index] =
1839                                    psNdefMap->TopazContainer.CurrentBlock;
1840            send_index = (uint8_t)(send_index + 1);
1841            break;
1842        }
1843
1844        case PH_FRINFC_TOPAZ_CMD_RSEG:
1845        {
1846            psNdefMap->SendRecvBuf[send_index] = (uint8_t)
1847                                            (psNdefMap->TopazContainer.CurrentSeg
1848                                             << NIBBLE_SIZE);
1849            send_index = (uint8_t)(send_index + 1);
1850            break;
1851        }
1852
1853#else /* #ifdef TOPAZ_RAW_SUPPORT */
1854
1855#ifdef PH_HAL4_ENABLE
1856        case phHal_eJewel_RID:
1857        case phHal_eJewel_ReadAll:
1858#else
1859        case phHal_eJewelCmdListJewelRid:
1860        case phHal_eJewelCmdListJewelReadAll:
1861#endif
1862        {
1863            /* For READ ID and READ ALL, send length is 0 */
1864            psNdefMap->SendLength = PH_FRINFC_TOPAZ_VAL0;
1865            break;
1866        }
1867
1868#ifdef PH_HAL4_ENABLE
1869        case phHal_eJewel_Read:
1870#else
1871        case phHal_eJewelCmdListJewelRead:
1872#endif
1873        {
1874            /* Need to check the User data size request*/
1875
1876            psNdefMap->SendLength = PH_FRINFC_TOPAZ_VAL3;
1877            break;
1878        }
1879
1880        case phHal_eJewel_ReadSeg:
1881        {
1882            psNdefMap->SendRecvBuf[send_index] = (uint8_t)
1883                                            (psNdefMap->TopazContainer.CurrentSeg
1884                                             << NIBBLE_SIZE);
1885            send_index = (uint8_t)(send_index + 1);
1886            psNdefMap->SendLength = send_index;
1887            break;
1888        }
1889
1890        case phHal_eJewel_Read8:
1891        {
1892            psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read4;
1893            psNdefMap->SendRecvBuf[send_index] = psNdefMap->TopazContainer.CurrentBlock;
1894            send_index = (uint8_t)(send_index + 1);
1895            psNdefMap->SendLength = send_index;
1896            break;
1897        }
1898
1899#endif /* #ifdef TOPAZ_RAW_SUPPORT */
1900
1901        default:
1902        {
1903            result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1904                                NFCSTATUS_INVALID_DEVICE_REQUEST);
1905            break;
1906        }
1907    }
1908    if(result == NFCSTATUS_SUCCESS)
1909    {
1910#ifdef TOPAZ_RAW_SUPPORT
1911
1912        if (PH_FRINFC_TOPAZ_CMD_READID != *psNdefMap->SendRecvBuf)
1913        {
1914            (void)memcpy ((void *)(psNdefMap->SendRecvBuf + send_index),
1915                            (void *)read_append, sizeof (read_append));
1916            send_index = (uint8_t)(send_index + sizeof (read_append));
1917
1918            (void)memcpy ((void *)(psNdefMap->SendRecvBuf + send_index),
1919                        (void *)psNdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid,
1920                        TOPAZ_UID_LENGTH_FOR_READ_WRITE);
1921            send_index = (uint8_t)(send_index +
1922                        TOPAZ_UID_LENGTH_FOR_READ_WRITE);
1923        }
1924
1925        psNdefMap->SendLength = send_index;
1926
1927#endif /* #ifdef TOPAZ_RAW_SUPPORT */
1928        /* Call the Overlapped HAL Transceive function */
1929        result = phFriNfc_OvrHal_Transceive(    psNdefMap->LowerDevice,
1930                                                &psNdefMap->MapCompletionInfo,
1931                                                psNdefMap->psRemoteDevInfo,
1932                                                psNdefMap->Cmd,
1933                                                &psNdefMap->psDepAdditionalInfo,
1934                                                psNdefMap->SendRecvBuf,
1935                                                psNdefMap->SendLength,
1936                                                psNdefMap->SendRecvBuf,
1937                                                psNdefMap->SendRecvLength);
1938    }
1939    return result;
1940}
1941
1942
1943static
1944NFCSTATUS
1945phFriNfc_Tpz_H_NxpWrite(
1946    phFriNfc_NdefMap_t          *psNdefMap,
1947    uint8_t                     *p_write_data,
1948    uint8_t                     wr_data_len)
1949{
1950    NFCSTATUS                   result = NFCSTATUS_SUCCESS;
1951    phFriNfc_TopazCont_t        *ps_tpz_info = NULL;
1952    uint8_t                     send_index = 0;
1953
1954    ps_tpz_info = &(psNdefMap->TopazContainer);
1955
1956    /* set the data for additional data exchange*/
1957    psNdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = PH_FRINFC_TOPAZ_VAL0;
1958    psNdefMap->psDepAdditionalInfo.DepFlags.NADPresent = PH_FRINFC_TOPAZ_VAL0;
1959    psNdefMap->psDepAdditionalInfo.NAD = PH_FRINFC_TOPAZ_VAL0;
1960
1961    psNdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_TopazDynamicMap_Process;
1962    psNdefMap->MapCompletionInfo.Context = psNdefMap;
1963
1964    *psNdefMap->SendRecvLength = psNdefMap->TempReceiveLength;
1965
1966#ifdef TOPAZ_RAW_SUPPORT
1967    /* " send_index " is incremented because already received buffer is filled with
1968        TOPAZ command */
1969    send_index = (uint8_t)(send_index + 1);
1970    psNdefMap->Cmd.JewelCmd = phHal_eJewel_Raw;
1971
1972    switch (*psNdefMap->SendRecvBuf)
1973
1974#else /* #ifdef TOPAZ_RAW_SUPPORT */
1975
1976    switch (psNdefMap->Cmd.JewelCmd)
1977
1978#endif /* #ifdef TOPAZ_RAW_SUPPORT */
1979    {
1980#ifdef TOPAZ_RAW_SUPPORT
1981
1982        case PH_FRINFC_TOPAZ_CMD_WRITE_1E:
1983        {
1984            psNdefMap->SendRecvBuf[send_index] = (uint8_t)((ps_tpz_info->CurrentBlock
1985                                                << (NIBBLE_SIZE - 1)) |
1986                                                ps_tpz_info->ByteNumber);
1987            send_index = (uint8_t)(send_index + 1);
1988            break;
1989        }
1990
1991        case PH_FRINFC_TOPAZ_CMD_WRITE_E8:
1992        {
1993            psNdefMap->SendRecvBuf[send_index] = ps_tpz_info->CurrentBlock;
1994            send_index = (uint8_t)(send_index + 1);
1995            break;
1996        }
1997
1998#else /* #ifdef TOPAZ_RAW_SUPPORT */
1999
2000        case phHal_eJewel_Write1E:
2001        {
2002            psNdefMap->SendRecvBuf[send_index] = (uint8_t)((ps_tpz_info->CurrentBlock
2003                                                << (NIBBLE_SIZE - 1)) |
2004                                                ps_tpz_info->ByteNumber);
2005            send_index = (uint8_t)(send_index + 1);
2006
2007
2008            break;
2009        }
2010
2011        case phHal_eJewel_Write8E:
2012        {
2013            psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write4E;
2014            psNdefMap->SendRecvBuf[send_index] = ps_tpz_info->CurrentBlock;
2015            send_index = (uint8_t)(send_index + 1);
2016            break;
2017        }
2018
2019#endif /* #ifdef TOPAZ_RAW_SUPPORT */
2020
2021        default:
2022        {
2023            result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
2024                                NFCSTATUS_INVALID_DEVICE_REQUEST);
2025            break;
2026        }
2027    }
2028
2029
2030    if (NFCSTATUS_SUCCESS == result)
2031    {
2032        (void)memcpy ((void *)(psNdefMap->SendRecvBuf + send_index),
2033                    (void *)p_write_data, wr_data_len);
2034
2035        send_index = (uint8_t)(send_index + wr_data_len);
2036
2037#ifdef TOPAZ_RAW_SUPPORT
2038
2039        (void)memcpy ((void *)(psNdefMap->SendRecvBuf + send_index),
2040                    (void *)psNdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid,
2041                    TOPAZ_UID_LENGTH_FOR_READ_WRITE);
2042        send_index = (uint8_t)(send_index + TOPAZ_UID_LENGTH_FOR_READ_WRITE);
2043
2044#endif /* #ifdef TOPAZ_RAW_SUPPORT */
2045
2046        psNdefMap->SendLength = send_index;
2047
2048        /* Call the Overlapped HAL Transceive function */
2049        result = phFriNfc_OvrHal_Transceive(    psNdefMap->LowerDevice,
2050                                                &psNdefMap->MapCompletionInfo,
2051                                                psNdefMap->psRemoteDevInfo,
2052                                                psNdefMap->Cmd,
2053                                                &psNdefMap->psDepAdditionalInfo,
2054                                                psNdefMap->SendRecvBuf,
2055                                                psNdefMap->SendLength,
2056                                                psNdefMap->SendRecvBuf,
2057                                                psNdefMap->SendRecvLength);
2058    }
2059    return result;
2060}
2061
2062static
2063NFCSTATUS
2064phFriNfc_Tpz_H_ProReadResp(
2065    phFriNfc_NdefMap_t          *psNdefMap)
2066{
2067    NFCSTATUS                   result = NFCSTATUS_SUCCESS;
2068    phFriNfc_TopazCont_t        *ps_tpz_info = NULL;
2069    uint8_t                     write_buffer[] = {0x00};
2070
2071    ps_tpz_info = &(psNdefMap->TopazContainer);
2072
2073    switch (psNdefMap->PrevOperation)
2074    {
2075        case  PH_FRINFC_NDEFMAP_CHECK_OPE:
2076        {
2077            if (PH_FRINFC_TOPAZ_DYNAMIC_READSEG_RESP ==
2078                *psNdefMap->SendRecvLength)
2079            {
2080                if (0 == ps_tpz_info->CurrentSeg)
2081                {
2082                    result = phFriNfc_Tpz_H_CheckCCBytes (psNdefMap);
2083                }
2084
2085                if (NFCSTATUS_SUCCESS == result)
2086                {
2087                    result = phFriNfc_Tpz_H_ParseTLVs (psNdefMap);
2088                }
2089            }
2090            else
2091            {
2092                result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
2093                                    NFCSTATUS_INVALID_RECEIVE_LENGTH);
2094            }
2095            break;
2096        }
2097
2098        case  PH_FRINFC_NDEFMAP_READ_OPE:
2099        {
2100            if (PH_FRINFC_TOPAZ_DYNAMIC_READSEG_RESP ==
2101                *psNdefMap->SendRecvLength)
2102            {
2103                /* call the data bytes to internal buffer*/
2104                result = phFriNfc_Tpz_H_CopyReadData (psNdefMap);
2105            }
2106            else
2107            {
2108                result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
2109                                    NFCSTATUS_INVALID_RECEIVE_LENGTH);
2110            }
2111            break;
2112        }
2113
2114        case  PH_FRINFC_NDEFMAP_WRITE_OPE:
2115        {
2116            /* read the bytes for cheking the CC bytes and lock bit status*/
2117            if(TOPAZ_READ_8_RESPONSE == *psNdefMap->SendRecvLength)
2118            {
2119                (void)memcpy ((void *)ps_tpz_info->CCByteBuf,
2120                            (void *)(psNdefMap->SendRecvBuf),
2121                            TOPAZ_CC_BYTES_LENGTH);
2122
2123                result = phFriNfc_Tpz_H_CheckCCBytesForWrite (psNdefMap);
2124                if (NFCSTATUS_SUCCESS == result)
2125                {
2126                    if ((0x00 == *ps_tpz_info->CCByteBuf) ||
2127                        (NDEF_T_TLV == ps_tpz_info->ExpectedSeq))
2128                    {
2129                        /* This statement is for getting the new
2130                            NDEF TLV byte address, because 1st CC byte is
2131                            corrupted or no NDEF TLV in the card
2132
2133                            If the 1st CC byte (NDEF magic number) in the
2134                            card is 0, means that previous write has failed,
2135                            so to write the exact file
2136                            OR
2137                            The NDEF TLV is not present in the entire card, and
2138                            the sequence is NDEF_T_TLV (this means, that lock and
2139                            memory control TLV is found in the card)
2140                        */
2141                        psNdefMap->State = (uint8_t)
2142                                        PH_FRINFC_TOPAZ_STATE_RD_FOR_WR_NDEF;
2143                        ps_tpz_info->WriteSeq = (uint8_t)WR_NDEF_T_TLV;
2144
2145                        ps_tpz_info->CurrentBlock = (uint8_t)
2146                                    TOPAZ_BLK_FROM_BYTE_ADR (
2147                                        ps_tpz_info->NdefTLVByteAddress);
2148
2149                        ps_tpz_info->ByteNumber = (uint8_t)
2150                                    TOPAZ_BYTE_OFFSET_FROM_BYTE_ADR (
2151                                        ps_tpz_info->NdefTLVByteAddress);
2152
2153#ifdef TOPAZ_RAW_SUPPORT
2154                        *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ8;
2155#else
2156                        psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read8;
2157#endif /* #ifdef TOPAZ_RAW_SUPPORT */
2158
2159                        result = phFriNfc_Tpz_H_NxpRead (psNdefMap);
2160                    }
2161                    else
2162                    {
2163                        ps_tpz_info->WriteSeq = (uint8_t)WR_NMN_0;
2164                        ps_tpz_info->CurrentBlock = 1;
2165                        ps_tpz_info->ByteNumber = 0;
2166                        psNdefMap->State = (uint8_t)
2167                                            PH_FRINFC_TOPAZ_STATE_WRITE;
2168#ifdef TOPAZ_RAW_SUPPORT
2169                        *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_1E;
2170#else
2171                        psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E;
2172#endif /* #ifdef TOPAZ_RAW_SUPPORT */
2173
2174                        /* Call read 8 */
2175                        result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, write_buffer,
2176                                                    sizeof (write_buffer));
2177                    }
2178
2179                }
2180            }
2181            else
2182            {
2183                result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
2184                                    NFCSTATUS_INVALID_RECEIVE_LENGTH);
2185            }
2186            break;
2187        }
2188
2189        default:
2190        {
2191            result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
2192                                NFCSTATUS_INVALID_DEVICE_REQUEST);
2193            break;
2194        }
2195    }
2196
2197    return result;
2198}
2199
2200
2201
2202static void phFriNfc_Tpz_H_Complete(phFriNfc_NdefMap_t  *NdefMap,
2203                                    NFCSTATUS           Status)
2204{
2205    /* set the state back to the Reset_Init state*/
2206    NdefMap->State =  PH_FRINFC_NDEFMAP_STATE_RESET_INIT;
2207
2208    /* set the completion routine*/
2209    NdefMap->CompletionRoutine[NdefMap->TopazContainer.CRIndex].
2210        CompletionRoutine(NdefMap->CompletionRoutine->Context, Status);
2211}
2212
2213static
2214NFCSTATUS
2215phFriNfc_Tpz_H_ChkLockBits(
2216    phFriNfc_NdefMap_t  *psNdefMap)
2217{
2218    NFCSTATUS           result = NFCSTATUS_SUCCESS;
2219#ifdef ENABLE_LOCK_BITS_CHECK
2220    uint8_t             *p_recv_buf = psNdefMap->SendRecvBuf;
2221#endif /* #ifdef ENABLE_LOCK_BITS_CHECK */
2222    psNdefMap->CardState = PH_NDEFMAP_CARD_STATE_INITIALIZED;
2223
2224#ifdef ENABLE_LOCK_BITS_CHECK
2225
2226    /* Set the card state */
2227    psNdefMap->CardState =  (uint8_t)
2228        (((p_recv_buf[PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_0] ==
2229            PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_0) &&
2230            ((p_recv_buf[PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_1] ==
2231            PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_1)) &&
2232            ((p_recv_buf[PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_2] ==
2233            PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_2TO7)) &&
2234            ((p_recv_buf[PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_3] ==
2235            PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_2TO7)) &&
2236            ((p_recv_buf[PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_4] ==
2237            PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_2TO7)) &&
2238            ((p_recv_buf[PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_5] ==
2239            PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_2TO7)) &&
2240            ((p_recv_buf[PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_6] ==
2241            PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_2TO7))) &&
2242            ((p_recv_buf[PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_7] ==
2243            PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_2TO7)) ?
2244                PH_NDEFMAP_CARD_STATE_INITIALIZED :
2245                PH_NDEFMAP_CARD_STATE_READ_ONLY);
2246
2247#endif /* #ifdef ENABLE_LOCK_BITS_CHECK */
2248
2249    /* Set the card state from CC bytes */
2250    if (PH_NDEFMAP_CARD_STATE_INITIALIZED == psNdefMap->CardState)
2251    {
2252        switch ((psNdefMap->TopazContainer.CCByteBuf[3] & 0xFF))
2253        {
2254            case PH_FRINFC_TOPAZ_CC_READWRITE:
2255            {
2256                psNdefMap->CardState = PH_NDEFMAP_CARD_STATE_INITIALIZED;
2257                break;
2258            }
2259
2260            case PH_FRINFC_TOPAZ_CC_READONLY:
2261            {
2262                psNdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_ONLY;
2263                break;
2264            }
2265
2266            default:
2267            {
2268                psNdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID;
2269                result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
2270                                    NFCSTATUS_NO_NDEF_SUPPORT);
2271                break;
2272            }
2273        }
2274    }
2275
2276    return result;
2277}
2278
2279static
2280NFCSTATUS
2281phFriNfc_Tpz_H_CheckCCBytes (
2282    phFriNfc_NdefMap_t          *psNdefMap)
2283{
2284    NFCSTATUS                       result = NFCSTATUS_SUCCESS;
2285    phFriNfc_TopazCont_t            *ps_tpz_info = &(psNdefMap->TopazContainer);
2286    uint8_t                         *p_recv_buf = psNdefMap->SendRecvBuf;
2287    uint16_t                        parse_index = 0;
2288
2289    parse_index = (uint16_t)(parse_index + TOPAZ_UID_BYTES_LENGTH);
2290
2291    (void)memcpy ((void *)ps_tpz_info->CCByteBuf,
2292                (void *)(p_recv_buf + parse_index),
2293                TOPAZ_CC_BYTES_LENGTH);
2294
2295    p_recv_buf = ps_tpz_info->CCByteBuf;
2296    parse_index = 0;
2297
2298#ifdef TOPAZ_MAGIC_NO_CHK_ENABLE
2299    /* 1st CC byte value = 0 or 0xE1 */
2300    if ((PH_FRINFC_TOPAZ_CC_BYTE0 == p_recv_buf[parse_index])
2301#ifdef TOPAZ_MAGIC_NO_0_CHK_ENABLE
2302        || (0 == p_recv_buf[parse_index])
2303#endif /* #if TOPAZ_MAGIC_NO_0_CHK_ENABLE */
2304        )
2305#endif /* #ifdef TOPAZ_MAGIC_NO_CHK_ENABLE */
2306    {
2307        parse_index = (uint16_t)(parse_index + 1);
2308        /* 2nd CC byte value = 0x10 */
2309        result = phFriNfc_Tpz_H_ChkSpcVer (psNdefMap, p_recv_buf[parse_index]);
2310    }
2311#ifdef TOPAZ_MAGIC_NO_CHK_ENABLE
2312    else
2313    {
2314        result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
2315                            NFCSTATUS_NO_NDEF_SUPPORT);
2316    }
2317#endif /* #ifdef TOPAZ_MAGIC_NO_CHK_ENABLE */
2318
2319    if (NFCSTATUS_SUCCESS == result)
2320    {
2321        parse_index = (uint16_t)(parse_index + 1);
2322        /* 3rd CC byte value = 0x3F for 512 card */
2323        if (PH_FRINFC_TOPAZ_DYNAMIC_CC_BYTE2_MMSIZE == p_recv_buf[parse_index])
2324        {
2325            /* Card size calculated as ((3rd CC byte * 8) - 4 CC bytes) */
2326            psNdefMap->CardMemSize = (uint16_t)((p_recv_buf[parse_index] *
2327                                    TOPAZ_BYTES_PER_BLOCK) -
2328                                    TOPAZ_CC_BYTES_LENGTH);
2329            ps_tpz_info->RemainingSize = (uint16_t)(psNdefMap->CardMemSize +
2330                                        TOPAZ_UID_BYTES_LENGTH +
2331                                        TOPAZ_CC_BYTES_LENGTH);
2332            result = phFriNfc_Tpz_H_ChkLockBits (psNdefMap);
2333        }
2334        else
2335        {
2336            result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
2337                                NFCSTATUS_NO_NDEF_SUPPORT);
2338        }
2339    }
2340
2341    if (NFCSTATUS_SUCCESS != result)
2342    {
2343        psNdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID;
2344    }
2345
2346    return result;
2347}
2348
2349static
2350NFCSTATUS
2351phFriNfc_Tpz_H_CheckCCBytesForWrite (
2352    phFriNfc_NdefMap_t          *psNdefMap)
2353{
2354    NFCSTATUS                           result = NFCSTATUS_SUCCESS;
2355    phFriNfc_TopazCont_t                *ps_tpz_info = NULL;
2356    uint8_t                             check_cc_rw[] = {TOPAZ_SPEC_VERSION,
2357                                        PH_FRINFC_TOPAZ_DYNAMIC_CC_BYTE2_MMSIZE,
2358                                        PH_FRINFC_TOPAZ_CC_READWRITE};
2359    uint8_t                             check_index = 0;
2360
2361    ps_tpz_info = &(psNdefMap->TopazContainer);
2362
2363#ifdef TOPAZ_MAGIC_NO_CHK_ENABLE
2364    if (
2365        (PH_FRINFC_TOPAZ_CC_BYTE0 == ps_tpz_info->CCByteBuf[check_index])
2366#if TOPAZ_MAGIC_NO_0_CHK_ENABLE
2367        || (0 == ps_tpz_info->CCByteBuf[check_index])
2368#endif /* #if TOPAZ_MAGIC_NO_0_CHK_ENABLE */
2369        )
2370#endif /* #ifdef TOPAZ_MAGIC_NO_CHK_ENABLE */
2371    {
2372        check_index = (uint8_t)(check_index + 1);
2373
2374        if ((!TOPAZ_COMPARE_VERSION(check_cc_rw[0], ps_tpz_info->CCByteBuf[1])) ||
2375            (check_cc_rw[1] != ps_tpz_info->CCByteBuf[2]) ||
2376            (check_cc_rw[2] != ps_tpz_info->CCByteBuf[3]))
2377        {
2378            result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
2379                                NFCSTATUS_NO_NDEF_SUPPORT);
2380        }
2381    }
2382#ifdef TOPAZ_MAGIC_NO_CHK_ENABLE
2383    else
2384    {
2385        result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
2386                            NFCSTATUS_NO_NDEF_SUPPORT);
2387    }
2388#endif /* #ifdef TOPAZ_MAGIC_NO_CHK_ENABLE */
2389    return result;
2390}
2391
2392static
2393uint16_t
2394phFriNfc_Tpz_H_GetNDEFValueFieldAddrForRead (
2395    phFriNfc_NdefMap_t          *psNdefMap)
2396{
2397    phFriNfc_TopazCont_t            *ps_tpz_info = &(psNdefMap->TopazContainer);
2398    uint16_t                        skip_size = 0;
2399    uint16_t                        byte_addr = 0;
2400    uint8_t                         exit_index = 0;
2401
2402    byte_addr = ps_tpz_info->NdefTLVByteAddress;
2403
2404    while (exit_index < ((ps_tpz_info->ActualNDEFMsgSize >= 0xFF) ? 3 : 1))
2405    {
2406        byte_addr = (uint16_t)(byte_addr + 1);
2407        if (TOPAZ_STATIC_LOCK_RES_START == byte_addr)
2408        {
2409            byte_addr = (uint16_t)(byte_addr + TOPAZ_STATIC_LOCK_RES_BYTES);
2410        }
2411        skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, byte_addr);
2412
2413        byte_addr = (uint16_t)(byte_addr + skip_size);
2414        exit_index = (uint8_t)(exit_index + 1);
2415    }
2416
2417    byte_addr = (uint16_t)(byte_addr + 1);
2418    if (TOPAZ_STATIC_LOCK_RES_START == byte_addr)
2419    {
2420        byte_addr = (uint16_t)(byte_addr + TOPAZ_STATIC_LOCK_RES_BYTES);
2421    }
2422    skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, byte_addr);
2423
2424    byte_addr = (uint16_t)(byte_addr + skip_size);
2425
2426    return byte_addr;
2427}
2428
2429static
2430uint16_t
2431phFriNfc_Tpz_H_GetNDEFValueFieldAddrForWrite (
2432    phFriNfc_NdefMap_t          *psNdefMap,
2433    uint16_t                    size_to_write)
2434{
2435    phFriNfc_TopazCont_t            *ps_tpz_info = &(psNdefMap->TopazContainer);
2436    uint16_t                        skip_size = 0;
2437    uint16_t                        byte_addr = 0;
2438    uint8_t                         exit_index = 0;
2439
2440    byte_addr = ps_tpz_info->NdefTLVByteAddress;
2441
2442    while (exit_index < ((size_to_write >= 0xFF) ? 3 : 1))
2443    {
2444        byte_addr = (uint16_t)(byte_addr + 1);
2445        if (TOPAZ_STATIC_LOCK_RES_START == byte_addr)
2446        {
2447            byte_addr = (uint16_t)(byte_addr + TOPAZ_STATIC_LOCK_RES_BYTES);
2448        }
2449        skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, byte_addr);
2450
2451        byte_addr = (uint16_t)(byte_addr + skip_size);
2452        exit_index = (uint8_t)(exit_index + 1);
2453    }
2454
2455    byte_addr = (uint16_t)(byte_addr + 1);
2456    if (TOPAZ_STATIC_LOCK_RES_START == byte_addr)
2457    {
2458        byte_addr = (uint16_t)(byte_addr + TOPAZ_STATIC_LOCK_RES_BYTES);
2459    }
2460    skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, byte_addr);
2461
2462    byte_addr = (uint16_t)(byte_addr + skip_size);
2463
2464    return byte_addr;
2465}
2466
2467
2468static
2469NFCSTATUS
2470phFriNfc_Tpz_H_RemainingReadDataCopy (
2471    phFriNfc_NdefMap_t          *psNdefMap)
2472{
2473    NFCSTATUS                       result = NFCSTATUS_SUCCESS;
2474    phFriNfc_TopazCont_t            *ps_tpz_info = &(psNdefMap->TopazContainer);
2475    uint8_t                         copy_temp_buf[PH_FRINFC_NDEFMAP_TOPAZ_MAX_SIZE];
2476    uint16_t                        copy_length = 0;
2477    uint16_t                        read_copy_length = 0;
2478
2479
2480    if (0 != ps_tpz_info->ReadBufferSize)
2481    {
2482        /* Data is already copied, so give it from the stored buffer */
2483        if ((psNdefMap->ApduBufferSize - psNdefMap->ApduBuffIndex) >=
2484            ps_tpz_info->ReadBufferSize)
2485        {
2486            read_copy_length = ps_tpz_info->ReadBufferSize;
2487            (void)memcpy ((void *)(psNdefMap->ApduBuffer + psNdefMap->ApduBuffIndex),
2488                    (void *)ps_tpz_info->ReadBuffer, ps_tpz_info->ReadBufferSize);
2489        }
2490        else
2491        {
2492            read_copy_length = (uint16_t)(psNdefMap->ApduBufferSize -
2493                                psNdefMap->ApduBuffIndex);
2494
2495            copy_length = (uint16_t)(ps_tpz_info->ReadBufferSize -
2496                            read_copy_length);
2497
2498            /* Copy data to user buffer */
2499            (void)memcpy ((void *)(psNdefMap->ApduBuffer + psNdefMap->ApduBuffIndex),
2500                    (void *)ps_tpz_info->ReadBuffer, read_copy_length);
2501
2502            /* Copy data from " ReadBuffer " to temporary buffer */
2503            (void)memcpy ((void *)copy_temp_buf,
2504                    (void *)(ps_tpz_info->ReadBuffer + read_copy_length),
2505                    copy_length);
2506
2507            /* Copy data from temporary buffer to " ReadBuffer " */
2508            (void)memcpy ((void *)ps_tpz_info->ReadBuffer,
2509                    (void *)copy_temp_buf, copy_length);
2510
2511        }
2512
2513        psNdefMap->ApduBuffIndex = (uint16_t)(psNdefMap->ApduBuffIndex +
2514                                    read_copy_length);
2515        ps_tpz_info->ReadBufferSize = (uint8_t)
2516                            (ps_tpz_info->ReadBufferSize -
2517                            read_copy_length);
2518        ps_tpz_info->RemainingReadSize = (uint16_t)(
2519                            ps_tpz_info->RemainingReadSize - read_copy_length);
2520    }
2521
2522    if (0 == ps_tpz_info->RemainingReadSize)
2523    {
2524        /* No data to read, so return */
2525        *psNdefMap->NumOfBytesRead = psNdefMap->ApduBuffIndex;
2526        ps_tpz_info->ReadBufferSize = 0;
2527        ps_tpz_info->ReadWriteCompleteFlag = TRUE;
2528    }
2529    else if (psNdefMap->ApduBuffIndex == psNdefMap->ApduBufferSize)
2530    {
2531        /* User data length is read completely */
2532        *psNdefMap->NumOfBytesRead = psNdefMap->ApduBuffIndex;
2533    }
2534    else
2535    {
2536        /* Stored data is not enough, so continue reading the next segment */
2537        ps_tpz_info->CurrentSeg = (uint8_t)
2538                            (ps_tpz_info->CurrentSeg + 1);
2539#ifdef TOPAZ_RAW_SUPPORT
2540
2541        *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_RSEG;
2542
2543#else
2544
2545        psNdefMap->Cmd.JewelCmd = phHal_eJewel_ReadSeg;
2546
2547#endif /* #ifdef TOPAZ_RAW_SUPPORT */
2548        result = phFriNfc_Tpz_H_NxpRead (psNdefMap);
2549    }
2550
2551    return result;
2552}
2553
2554static
2555NFCSTATUS
2556phFriNfc_Tpz_H_CopyReadData (
2557    phFriNfc_NdefMap_t          *psNdefMap)
2558{
2559    NFCSTATUS                       result = NFCSTATUS_SUCCESS;
2560    phFriNfc_TopazCont_t            *ps_tpz_info = &(psNdefMap->TopazContainer);
2561    phFriNfc_LockCntrlTLVCont_t     *ps_locktlv_info = NULL;
2562    phFriNfc_ResMemCntrlTLVCont_t   *ps_memtlv_info = NULL;
2563    uint16_t                        copy_index = 0;
2564    uint16_t                        copy_length = 0;
2565    uint16_t                        recv_length = 0;
2566    static uint16_t                 skip_size = 0;
2567    /* byte address read */
2568    uint16_t                        copy_till_address = 0;
2569    uint16_t                        exact_copy_length = 0;
2570    uint16_t                        actual_ndef_length = 0;
2571
2572
2573    recv_length = *(psNdefMap->SendRecvLength);
2574
2575    actual_ndef_length = ps_tpz_info->ActualNDEFMsgSize;
2576    if (PH_FRINFC_NDEFMAP_SEEK_CUR == psNdefMap->Offset)
2577    {
2578        actual_ndef_length = (uint16_t)(
2579                            ps_tpz_info->RemainingReadSize +
2580                            psNdefMap->ApduBuffIndex);
2581    }
2582
2583    exact_copy_length = (uint16_t)((psNdefMap->ApduBufferSize >
2584                            actual_ndef_length) ? actual_ndef_length :
2585                            psNdefMap->ApduBufferSize);
2586
2587    if (0 == ps_tpz_info->CurrentSeg)
2588    {
2589        /* Skip copying the UID bytes, CC bytes, and lock and reserved memory bytes
2590             */
2591        recv_length = (*(psNdefMap->SendRecvLength) - TOPAZ_STATIC_LOCK_RES_BYTES);
2592    }
2593
2594    if (TOPAZ_SEG_FROM_BYTE_ADR (
2595        phFriNfc_Tpz_H_GetNDEFValueFieldAddrForRead (psNdefMap)) ==
2596        ps_tpz_info->CurrentSeg)
2597    {
2598        copy_index = (uint16_t)(copy_index + (
2599                    phFriNfc_Tpz_H_GetNDEFValueFieldAddrForRead (
2600                        psNdefMap) % TOPAZ_SEGMENT_READ_LENGTH));
2601        skip_size = 0;
2602    }
2603
2604    if (0 != skip_size)
2605    {
2606        copy_index = (copy_index + skip_size);
2607        skip_size = 0;
2608    }
2609
2610    while (copy_index < recv_length)
2611    {
2612        copy_length = (uint16_t)(recv_length - copy_index);
2613        copy_till_address = 0;
2614        /* IF MORE THAN ONE TLV EXISTS THEN ADD A WHILE LOOP HERE, AND PLACE THE
2615            IF STATEMENT INSIDE THE WHILE LOOP. ALSO,
2616            ps_locktlv_info = &(psNdefMap->LockTlv) change this to
2617            ps_locktlv_info = &(psNdefMap->LockTlv[index])
2618            */
2619        ps_locktlv_info = &(psNdefMap->LockTlv);
2620        if (
2621            /* Check the lock bytes belong to this segment */
2622            (ps_tpz_info->CurrentSeg ==
2623            (ps_locktlv_info->ByteAddr / TOPAZ_SEGMENT_READ_LENGTH)) &&
2624            /* Now to check if the copy_index has surpassed the lock byte address */
2625            (TOPAZ_BYTE_ADR_FROM_SEG(ps_tpz_info->CurrentSeg, copy_index)
2626            <= ps_locktlv_info->ByteAddr)
2627            )
2628        {
2629            if ((ps_locktlv_info->ByteAddr < TOPAZ_STATIC_LOCK_RES_START) ||
2630                (ps_locktlv_info->ByteAddr >= (TOPAZ_STATIC_LOCK_RES_END + 8)))
2631            {
2632                copy_till_address = ps_locktlv_info->ByteAddr;
2633            }
2634            skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap,
2635                                                        ps_locktlv_info->ByteAddr);
2636        }
2637
2638        /* IF MORE THAN ONE TLV EXISTS THEN ADD A WHILE LOOP HERE, AND PLACE THE
2639            IF STATEMENT INSIDE THE WHILE LOOP. ALSO,
2640            ps_memtlv_info = &(psNdefMap->MemTlv) change this to
2641            ps_memtlv_info = &(psNdefMap->MemTlv[index])
2642            */
2643        ps_memtlv_info = &(psNdefMap->MemTlv);
2644        if (
2645            /* Check the reserved bytes belong to this segment */
2646            (ps_tpz_info->CurrentSeg ==
2647            (ps_memtlv_info->ByteAddr / TOPAZ_SEGMENT_READ_LENGTH)) &&
2648            /* Now to check if the copy_index has surpassed the reserved byte address */
2649            (TOPAZ_BYTE_ADR_FROM_SEG(ps_tpz_info->CurrentSeg, copy_index)
2650            <= ps_memtlv_info->ByteAddr)
2651            )
2652        {
2653            if ((ps_memtlv_info->ByteAddr < TOPAZ_STATIC_LOCK_RES_START) ||
2654                (ps_memtlv_info->ByteAddr >= (TOPAZ_STATIC_LOCK_RES_END + 8)))
2655            {
2656                copy_till_address = (uint16_t)
2657                            (((ps_memtlv_info->ByteAddr < copy_till_address) ||
2658                                (0 == copy_till_address))?
2659                            ps_memtlv_info->ByteAddr : copy_till_address);
2660            }
2661
2662            if (copy_till_address == ps_memtlv_info->ByteAddr)
2663            {
2664                skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap,
2665                                                            ps_memtlv_info->ByteAddr);
2666            }
2667        }
2668
2669
2670        copy_length = (uint16_t) ((copy_till_address == 0) ? copy_length :
2671                    ((copy_till_address % TOPAZ_SEGMENT_READ_LENGTH) -
2672                    copy_index));
2673
2674        /* After lock bytes, there are immediate reserved bytes, so " copy_length "
2675            can be 0 */
2676        if (0 != copy_length)
2677        {
2678            /* If complete user buffer is not filled and the
2679                read data is greater than the user data buffer, then get the
2680                remaining size that should be copied.
2681                The below " if " statement is used for the above scenario */
2682            if ((copy_length > (uint16_t)
2683                (exact_copy_length - psNdefMap->ApduBuffIndex)) &&
2684                (exact_copy_length != psNdefMap->ApduBuffIndex))
2685            {
2686                copy_length = (uint16_t)(exact_copy_length -
2687                                        psNdefMap->ApduBuffIndex);
2688            }
2689
2690            if (exact_copy_length != psNdefMap->ApduBuffIndex)
2691            {
2692                (void)memcpy ((void *)(psNdefMap->ApduBuffer +
2693                        psNdefMap->ApduBuffIndex),
2694                        (void *)(psNdefMap->SendRecvBuf + copy_index),
2695                        copy_length);
2696#if 0
2697                if (((copy_till_address == 0) ? copy_length :
2698                    ((copy_till_address % TOPAZ_SEGMENT_READ_LENGTH) -
2699                    copy_index)) > (uint16_t)
2700                    (exact_copy_length - psNdefMap->ApduBuffIndex))
2701                {
2702                    /* Copy remaining buffer in the static memory */
2703                    (void)memcpy ((void *)(ps_tpz_info->ReadBuffer +
2704                            ps_tpz_info->ReadBufferSize),
2705                            (void *)(psNdefMap->SendRecvBuf + copy_index),
2706                            (((copy_till_address % TOPAZ_SEGMENT_READ_LENGTH) -
2707                            copy_index) - copy_length));
2708
2709                    ps_tpz_info->ReadBufferSize = (uint16_t)(((copy_till_address %
2710                                                    TOPAZ_SEGMENT_READ_LENGTH) -
2711                                                    copy_index) - copy_length);
2712
2713                    /* Copy the data in the user buffer */
2714                    copy_index = (uint16_t)(copy_index +
2715                                ((copy_till_address % TOPAZ_SEGMENT_READ_LENGTH) -
2716                                copy_index));
2717                }
2718                else
2719#endif /* #if 0 */
2720                {
2721                    /* Copy the data in the user buffer */
2722                    copy_index = (uint16_t)(copy_index + copy_length);
2723                }
2724
2725                psNdefMap->ApduBuffIndex = (uint16_t)(psNdefMap->ApduBuffIndex +
2726                                            copy_length);
2727
2728
2729            }
2730            else
2731            {
2732                copy_length = (uint16_t) ((copy_till_address == 0) ? copy_length :
2733                            ((copy_till_address % TOPAZ_SEGMENT_READ_LENGTH) -
2734                            copy_index));
2735
2736                /* Actual NDEF message size is greater than the last index copied in
2737                    the user buffer */
2738                if (actual_ndef_length > (psNdefMap->ApduBuffIndex +
2739                    ps_tpz_info->ReadBufferSize))
2740                {
2741                    /* The statement is correct, check the remaining length */
2742                    copy_length = ((copy_length > (actual_ndef_length -
2743                                psNdefMap->ApduBuffIndex)) ?
2744                                (actual_ndef_length -
2745                                psNdefMap->ApduBuffIndex) :
2746                                copy_length);
2747
2748                    /* Copy remaining buffer in the static memory */
2749                    (void)memcpy ((void *)(ps_tpz_info->ReadBuffer +
2750                                ps_tpz_info->ReadBufferSize),
2751                                (void *)(psNdefMap->SendRecvBuf + copy_index),
2752                                copy_length);
2753
2754                    ps_tpz_info->ReadBufferSize = (uint8_t)(
2755                                                    ps_tpz_info->ReadBufferSize +
2756                                                    copy_length);
2757                }
2758
2759                /* Copy the data in the user buffer */
2760                copy_index = (uint16_t)(copy_index + copy_length);
2761            }
2762        }
2763
2764        if (copy_index != copy_till_address)
2765        {
2766            skip_size = 0;
2767        }
2768
2769        if ((copy_index + skip_size) <= recv_length)
2770        {
2771            copy_index = (uint16_t)(copy_index + skip_size);
2772            skip_size = 0;
2773        }
2774        else
2775        {
2776            skip_size = (uint16_t)((skip_size > 0) ?
2777                                    (recv_length - copy_index) : 0);
2778            copy_index = (uint16_t)recv_length;
2779        }
2780    }
2781
2782    if (exact_copy_length != psNdefMap->ApduBuffIndex)
2783    {
2784        ps_tpz_info->CurrentSeg = (uint8_t)
2785                            (ps_tpz_info->CurrentSeg + 1);
2786#ifdef TOPAZ_RAW_SUPPORT
2787
2788        *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_RSEG;
2789
2790#else
2791
2792        psNdefMap->Cmd.JewelCmd = phHal_eJewel_ReadSeg;
2793
2794#endif /* #ifdef TOPAZ_RAW_SUPPORT */
2795        result = phFriNfc_Tpz_H_NxpRead (psNdefMap);
2796    }
2797    else
2798    {
2799        *psNdefMap->NumOfBytesRead = psNdefMap->ApduBuffIndex;
2800        if (psNdefMap->ApduBuffIndex == actual_ndef_length)
2801        {
2802            ps_tpz_info->ReadBufferSize = 0;
2803            ps_tpz_info->ReadWriteCompleteFlag = TRUE;
2804        }
2805        else
2806        {
2807            ps_tpz_info->RemainingReadSize = (actual_ndef_length -
2808                                        psNdefMap->ApduBuffIndex);
2809        }
2810    }
2811    return result;
2812}
2813
2814
2815static
2816NFCSTATUS
2817phFriNfc_Tpz_H_ParseTLVs (
2818    phFriNfc_NdefMap_t          *psNdefMap)
2819{
2820    NFCSTATUS                   result = NFCSTATUS_SUCCESS;
2821    phFriNfc_TopazCont_t        *ps_tpz_info = &(psNdefMap->TopazContainer);
2822    uint8_t                     *p_recv_buf = NULL;
2823    uint16_t                    recv_length = 0;
2824    uint16_t                    parse_index = 0;
2825    phFriNfc_Tpz_ParseSeq_t     expected_seq = (phFriNfc_Tpz_ParseSeq_t)
2826                                ps_tpz_info->ExpectedSeq;
2827    uint16_t                    byte_addr = 0;
2828    /* This variable is kept static because if the size to skip LOCK or RESERVED
2829    bytes extends to next read then it shall be stored and used to skip the next
2830    read the bytes
2831    */
2832    static uint16_t             skip_size = 0;
2833    /* This variable is kept static because if the bytes extends from the read segment,
2834        then the index shall be stored
2835    This is to store index copied from the
2836    1. lock memory VALUE field bytes in the LOCK and MEMORY CONTROL TLV.
2837    2. Also, LENGTH field of the NDEF TLV */
2838    static uint8_t              lock_mem_ndef_index = 0;
2839    /* This variable is kept static because if the bytes extends from the read segment,
2840        then it has to stored
2841    This is to store the
2842    1. lock memory VALUE field bytes in the LOCK and MEMORY CONTROL TLV.
2843    2. Also, LENGTH field of the NDEF TLV */
2844    static uint8_t              lock_mem_buf[TOPAZ_MEM_LOCK_TLV_LENGTH] = {0};
2845    /* This is used in case if there is no MAGIC NUMBER found
2846                        OR
2847        TYPE field is not found after reading entire card */
2848    static uint16_t             ndef_tlv_byte_addr = 0;
2849
2850    p_recv_buf = psNdefMap->SendRecvBuf;
2851    recv_length = *psNdefMap->SendRecvLength;
2852
2853    if (0 == ps_tpz_info->CurrentSeg)
2854    {
2855        /* First read, so reset all the static variables */
2856        lock_mem_ndef_index = 0;
2857        skip_size = 0;
2858        ndef_tlv_byte_addr = 0;
2859
2860        /* Skip copying the UID bytes and CC bytes, which is first 12 bytes */
2861        parse_index = (uint16_t)(TOPAZ_UID_BYTES_LENGTH +
2862                                TOPAZ_CC_BYTES_LENGTH);
2863        /* Delete the lock and reserved memory bytes
2864            (which are the last 24 bytes in the card) */
2865        recv_length = (uint16_t)(*(psNdefMap->SendRecvLength) -
2866                                TOPAZ_STATIC_LOCK_RES_BYTES);
2867    }
2868
2869    while ((parse_index < recv_length) && (NFCSTATUS_SUCCESS == result) &&
2870        (NDEF_V_TLV != expected_seq))
2871    {
2872        if (0 == skip_size)
2873        {
2874            /* Macro used to get the exact byte address of the card.
2875                This is done by using the current segment and the parse index */
2876            byte_addr = TOPAZ_BYTE_ADR_FROM_SEG (ps_tpz_info->CurrentSeg, parse_index);
2877            /* Skip size is to skip the lock or memory reserved bytes  */
2878            skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, byte_addr);
2879        }
2880
2881        if (0 != skip_size)
2882        {
2883            if ((recv_length - parse_index) >= skip_size)
2884            {
2885                parse_index = (uint16_t)(parse_index + skip_size);
2886                skip_size = 0;
2887            }
2888            else
2889            {
2890                parse_index = (uint16_t)(parse_index + (recv_length -
2891                                parse_index));
2892                skip_size = (uint16_t)(skip_size - (recv_length -
2893                                parse_index));
2894            }
2895        }
2896        else
2897        {
2898            switch (expected_seq)
2899            {
2900                case LOCK_T_TLV:
2901                {
2902                    /* Parse the bytes till TYPE field of LOCK TLV is found, Once the
2903                        TYPE field is found then change the sequence to LOCK_L_TLV */
2904                    result = phFriNfc_Tpz_H_ParseLockTLVType (psNdefMap, p_recv_buf,
2905                                            &parse_index, recv_length, &expected_seq);
2906
2907                    break;
2908                }
2909
2910                case LOCK_L_TLV:
2911                {
2912                    /* Parse the length field of LOCK TLV. Length field value of the
2913                        LOCK TLV is always 3 */
2914                    if (TOPAZ_MEM_LOCK_TLV_LENGTH != p_recv_buf[parse_index])
2915                    {
2916                        result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
2917                                            NFCSTATUS_NO_NDEF_SUPPORT);
2918                    }
2919                    else
2920                    {
2921                        parse_index = (uint16_t)(parse_index + 1);
2922                        expected_seq = LOCK_V_TLV;
2923                    }
2924                    break;
2925                }
2926
2927                case LOCK_V_TLV:
2928                {
2929                    /* Parse the VALUE field of the LOCK TLV */
2930                    lock_mem_buf[lock_mem_ndef_index] = p_recv_buf[parse_index];
2931                    parse_index = (uint16_t)(parse_index + 1);
2932                    lock_mem_ndef_index = (uint8_t)(lock_mem_ndef_index + 1);
2933
2934
2935                    /* All the 3 bytes are copied in the local buffer */
2936                    if (TOPAZ_MEM_LOCK_TLV_LENGTH == lock_mem_ndef_index)
2937                    {
2938#ifdef FRINFC_READONLY_NDEF
2939                        (void)memcpy ((void *)psNdefMap->LockTlv.LockTlvBuff,
2940                                (void *)lock_mem_buf, sizeof (lock_mem_buf));
2941#endif /* #ifdef FRINFC_READONLY_NDEF */
2942                        /* Calculate the byte address and size of the lock bytes */
2943                        result = phFriNfc_Tpz_H_GetLockBytesInfo (psNdefMap, lock_mem_buf);
2944                        lock_mem_ndef_index = 0;
2945                        expected_seq = MEM_T_TLV;
2946                    }
2947                    break;
2948                }
2949
2950                case MEM_T_TLV:
2951                {
2952                    /* Parse the bytes till TYPE field of MEMORY TLV is found, Once the
2953                        TYPE field is found then change the sequence to MEM_L_TLV */
2954                    result = phFriNfc_Tpz_H_ParseMemTLVType (psNdefMap, p_recv_buf,
2955                                            &parse_index, recv_length, &expected_seq);
2956                    break;
2957                }
2958
2959                case MEM_L_TLV:
2960                {
2961                    /* Parse the length field of MEMORY TLV. Length field value of the
2962                        MEMORY TLV is always 3 */
2963                    if (TOPAZ_MEM_LOCK_TLV_LENGTH != p_recv_buf[parse_index])
2964                    {
2965                        result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
2966                                            NFCSTATUS_NO_NDEF_SUPPORT);
2967                    }
2968                    else
2969                    {
2970                        parse_index = (uint16_t)(parse_index + 1);
2971                        expected_seq = MEM_V_TLV;
2972                    }
2973
2974                    break;
2975                }
2976
2977                case MEM_V_TLV:
2978                {
2979                    /* Parse the VALUE field of the MEMORY TLV */
2980                    lock_mem_buf[lock_mem_ndef_index] = p_recv_buf[parse_index];
2981                    parse_index = (uint16_t)(parse_index + 1);
2982                    lock_mem_ndef_index = (uint8_t)(lock_mem_ndef_index + 1);
2983
2984                    /* All the 3 bytes are copied in the local buffer */
2985                    if (TOPAZ_MEM_LOCK_TLV_LENGTH == lock_mem_ndef_index)
2986                    {
2987                        /* Calculate the byte address and size of the lock bytes */
2988                        ndef_tlv_byte_addr = TOPAZ_BYTE_ADR_FROM_SEG (
2989                                            ps_tpz_info->CurrentSeg , parse_index);
2990                        result = phFriNfc_Tpz_H_GetMemBytesInfo (psNdefMap, lock_mem_buf);
2991                        lock_mem_ndef_index = 0;
2992                        expected_seq = NDEF_T_TLV;
2993                    }
2994
2995                    break;
2996                }
2997
2998                case NDEF_T_TLV:
2999                {
3000                    /* Parse the bytes till TYPE field of NDEF TLV is found, Once the
3001                        TYPE field is found then change the sequence to NDEF_L_TLV */
3002                    result = phFriNfc_Tpz_H_ParseNdefTLVType (psNdefMap, p_recv_buf,
3003                                            &parse_index, recv_length, &expected_seq);
3004
3005                    break;
3006                }
3007
3008                case NDEF_L_TLV:
3009                {
3010                    /* Length field of the NDEF TLV */
3011                    if (0 == lock_mem_ndef_index)
3012                    {
3013                        /* This is the 1st time, the loop has entered this case,
3014                            means that the NDEF byte address has to be updated */
3015                        ps_tpz_info->NdefTLVByteAddress = (uint16_t)
3016                                TOPAZ_BYTE_ADR_FROM_SEG (ps_tpz_info->CurrentSeg,
3017                                (parse_index - 1));
3018                    }
3019
3020                    if (0 != lock_mem_ndef_index)
3021                    {
3022                        /* There is already index has been updated, update remaining
3023                            buffer */
3024                        lock_mem_buf[lock_mem_ndef_index] = p_recv_buf[parse_index];
3025                        parse_index = (uint16_t)(parse_index + 1);
3026                        lock_mem_ndef_index = (uint8_t)(lock_mem_ndef_index + 1);
3027
3028                        if (TOPAZ_MEM_LOCK_TLV_LENGTH == lock_mem_ndef_index)
3029                        {
3030                            lock_mem_ndef_index = 0;
3031                            ps_tpz_info->ActualNDEFMsgSize = (uint16_t)((lock_mem_buf[1] <<
3032                                        TOPAZ_BYTE_SHIFT) | lock_mem_buf[2]);
3033                            expected_seq = NDEF_V_TLV;
3034                        }
3035                    }
3036                    /* Check for remaining size in the card and the actual ndef length */
3037                    else if (p_recv_buf[parse_index] <=
3038                            (ps_tpz_info->RemainingSize - (parse_index + 1)))
3039                    {
3040                        /* This check is added to see that length field in the TLV is
3041                            greater than the 1 byte */
3042                        if (0xFF == p_recv_buf[parse_index])
3043                        {
3044                            lock_mem_buf[lock_mem_ndef_index] =
3045                                                    p_recv_buf[parse_index];
3046                            lock_mem_ndef_index = (uint8_t)(lock_mem_ndef_index + 1);
3047                        }
3048                        else
3049                        {
3050                            /* Length field of the TLV is ONE byte, so update the
3051                            actual ndef size */
3052                            lock_mem_ndef_index = 0;
3053                            ps_tpz_info->ActualNDEFMsgSize = (uint16_t)
3054                                                        p_recv_buf[parse_index];
3055
3056                            expected_seq = NDEF_V_TLV;
3057                        }
3058                        parse_index = (uint16_t)(parse_index + 1);
3059                    }
3060                    else
3061                    {
3062                        /* Wrong length, remaining size in the card is lesser than the actual
3063                            ndef message length */
3064                        lock_mem_ndef_index = 0;
3065                        result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
3066                                            NFCSTATUS_NO_NDEF_SUPPORT);
3067                    }
3068                    break;
3069                }
3070
3071                default:
3072                {
3073                    break;
3074                }
3075            }/* end of switch (expected_seq) */
3076        } /* end of if (0 != skip_size) */
3077    } /* while ((parse_index < recv_length) && (NFCSTATUS_SUCCESS != result) &&
3078        (NDEF_V_TLV != expected_seq)) */
3079
3080    ps_tpz_info->ExpectedSeq = (uint8_t)expected_seq;
3081
3082    if (0 == ps_tpz_info->CurrentSeg)
3083    {
3084        /* First segment has the STATIC lock and reserved bytes, so delete it from
3085            the remaining size */
3086        ps_tpz_info->RemainingSize = (uint16_t)(ps_tpz_info->RemainingSize -
3087                                    (parse_index + TOPAZ_STATIC_LOCK_RES_BYTES));
3088
3089    }
3090    else
3091    {
3092        ps_tpz_info->RemainingSize = (uint16_t)(ps_tpz_info->RemainingSize -
3093                                    parse_index);
3094    }
3095
3096    if ((NDEF_V_TLV == expected_seq) && (NFCSTATUS_SUCCESS == result))
3097    {
3098        /* NDEF TLV found */
3099        result = phFriNfc_Tpz_H_ActualCardSize (psNdefMap);
3100
3101        if ((PH_NDEFMAP_CARD_STATE_READ_ONLY != psNdefMap->CardState) &&
3102            (0 != ps_tpz_info->ActualNDEFMsgSize))
3103        {
3104            /* Check if the card state is READ ONLY or the actual NDEF size is 0
3105                if actual NDEF size is 0, then card state is INITIALISED
3106            */
3107            psNdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_WRITE;
3108        }
3109    }
3110
3111    if ((NFCSTATUS_SUCCESS == result) && (NDEF_V_TLV != expected_seq))
3112    {
3113        ps_tpz_info->CurrentSeg = (uint8_t)(ps_tpz_info->CurrentSeg + 1);
3114        if (TOPAZ_TOTAL_SEG_TO_READ == ps_tpz_info->CurrentSeg)
3115        {
3116            /* Max segment to read reached, so no more read can be done */
3117            result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
3118                                NFCSTATUS_NO_NDEF_SUPPORT);
3119        }
3120        else
3121        {
3122#ifdef TOPAZ_RAW_SUPPORT
3123
3124            *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_RSEG;
3125
3126#else
3127
3128            psNdefMap->Cmd.JewelCmd = phHal_eJewel_ReadSeg;
3129
3130#endif /* #ifdef TOPAZ_RAW_SUPPORT */
3131            result = phFriNfc_Tpz_H_NxpRead(psNdefMap);
3132        }
3133    }
3134
3135    if ((NFCSTATUS_SUCCESS != result) && (NFCSTATUS_PENDING != result))
3136    {
3137        /* Error scenario */
3138        ps_tpz_info->NdefTLVByteAddress = 0;
3139        ps_tpz_info->ActualNDEFMsgSize = 0;
3140    }
3141
3142    if (NFCSTATUS_PENDING != result)
3143    {
3144        /* Exit scenario */
3145        if ((0x00 == *ps_tpz_info->CCByteBuf) ||
3146            ((NDEF_T_TLV == expected_seq) &&
3147            (TOPAZ_TOTAL_SEG_TO_READ == ps_tpz_info->CurrentSeg)))
3148        {
3149            /* This statement is for getting the new
3150                NDEF TLV byte address, because 1st CC byte is corrupted or
3151                no NDEF TLV in the card
3152
3153                If the 1st CC byte (NDEF magic number) in the card is 0, means
3154                that previous write has failed, so to write the exact TLV,
3155                calculate the byte number
3156                                            OR
3157                The NDEF TLV is not present in the entire card, and the sequence is
3158                NDEF_T_TLV (this means, that lock and memory control TLV is found
3159                in the card)
3160                */
3161            uint16_t             size_to_skip = 0;
3162            ps_tpz_info->ActualNDEFMsgSize = 0;
3163
3164            if (0 != ndef_tlv_byte_addr)
3165            {
3166                /* ndef_tlv_byte_addr is updated, only after complete parsing the
3167                    memory control TLV so the value shall not be 0 */
3168                do
3169                {
3170                    /* This loop is added to make sure the lock and reserved bytes are not
3171                    overwritten */
3172                    size_to_skip = 0;
3173                    size_to_skip = phFriNfc_Tpz_H_GetSkipSize (psNdefMap,
3174                                                            ndef_tlv_byte_addr);
3175
3176                    ndef_tlv_byte_addr = (uint16_t)(ndef_tlv_byte_addr +
3177                                            size_to_skip);
3178                }while (0 != size_to_skip);
3179
3180                /* Update the TLV byte address */
3181                ps_tpz_info->NdefTLVByteAddress = ndef_tlv_byte_addr;
3182
3183                /* Update the remaining size */
3184                ps_tpz_info->RemainingSize = (uint16_t)(psNdefMap->CardMemSize +
3185                                        TOPAZ_UID_BYTES_LENGTH +
3186                                        TOPAZ_CC_BYTES_LENGTH);
3187
3188                ps_tpz_info->RemainingSize = (uint16_t)
3189                                            (ps_tpz_info->RemainingSize -
3190                                            (ndef_tlv_byte_addr +
3191                                            TOPAZ_STATIC_LOCK_RES_BYTES));
3192                (void)phFriNfc_Tpz_H_ActualCardSize (psNdefMap);
3193
3194                /* Length byte is subtracted here to get the actual NDEF
3195                    read and write size */
3196                ps_tpz_info->NDEFRWSize = (uint16_t)
3197                                        (ps_tpz_info->NDEFRWSize - 2);
3198                ndef_tlv_byte_addr = 0;
3199                result = NFCSTATUS_SUCCESS;
3200            }
3201        }
3202    }
3203
3204    return result;
3205}
3206
3207static
3208NFCSTATUS
3209phFriNfc_Tpz_H_CopyReadDataAndWrite (
3210    phFriNfc_NdefMap_t          *psNdefMap)
3211{
3212    NFCSTATUS                           result = NFCSTATUS_SUCCESS;
3213    phFriNfc_TopazCont_t                *ps_tpz_info = NULL;
3214    uint8_t                             write_buf[TOPAZ_WRITE_8_DATA_LENGTH];
3215    uint16_t                            write_index = 0;
3216    uint16_t                            write_len = 0;
3217    uint16_t                            byte_addr = 0;
3218    static uint16_t                     skip_size = 0;
3219
3220    ps_tpz_info = &(psNdefMap->TopazContainer);
3221
3222    write_len = (uint16_t)((psNdefMap->ApduBufferSize < ps_tpz_info->NDEFRWSize) ?
3223                        psNdefMap->ApduBufferSize : ps_tpz_info->NDEFRWSize);
3224
3225    (void)memcpy ((void *)write_buf, (void *)psNdefMap->SendRecvBuf,
3226                    TOPAZ_WRITE_8_DATA_LENGTH);
3227
3228    if (ps_tpz_info->CurrentBlock == TOPAZ_BLK_FROM_BYTE_ADR (
3229        phFriNfc_Tpz_H_GetNDEFValueFieldAddrForWrite (psNdefMap, write_len)))
3230    {
3231        skip_size = 0;
3232    }
3233
3234    /* Byte Number != 0 menas that the VALUE field of the TLV is in between the
3235        block, so the first few bytes shall be copied and then user data has to
3236        be copied
3237        */
3238    if (0 != ps_tpz_info->ByteNumber)
3239    {
3240        write_index = (uint16_t)(write_index + ps_tpz_info->ByteNumber);
3241    }
3242
3243
3244    if (0 != skip_size)
3245    {
3246        write_index = (uint16_t)(write_index + skip_size);
3247    }
3248
3249    while ((write_index < TOPAZ_WRITE_8_DATA_LENGTH) &&
3250        (write_len != psNdefMap->ApduBuffIndex))
3251    {
3252        skip_size = 0;
3253        byte_addr = TOPAZ_BYTE_ADR_FROM_BLK (ps_tpz_info->CurrentBlock,
3254                                            ps_tpz_info->ByteNumber);
3255        skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, byte_addr);
3256
3257        if (0 == skip_size)
3258        {
3259            write_buf[write_index] =
3260                        psNdefMap->ApduBuffer[psNdefMap->ApduBuffIndex];
3261
3262            write_index = (uint16_t)(write_index + 1);
3263            psNdefMap->ApduBuffIndex = (uint16_t)
3264                                        (psNdefMap->ApduBuffIndex + 1);
3265            ps_tpz_info->ByteNumber = (uint8_t)
3266                                        (ps_tpz_info->ByteNumber + 1);
3267        }
3268        else
3269        {
3270
3271            if (skip_size >= (TOPAZ_WRITE_8_DATA_LENGTH - write_index))
3272            {
3273                skip_size = (uint16_t)(skip_size - (TOPAZ_WRITE_8_DATA_LENGTH
3274                            - write_index));
3275                write_index = (uint16_t)TOPAZ_WRITE_8_DATA_LENGTH;
3276            }
3277            else
3278            {
3279                ps_tpz_info->ByteNumber = (uint8_t)
3280                            (ps_tpz_info->ByteNumber + skip_size);
3281                write_index = (uint16_t)(write_index + skip_size);
3282                skip_size = 0;
3283            }
3284        }
3285    }
3286
3287    if (psNdefMap->ApduBuffIndex == write_len)
3288    {
3289        ps_tpz_info->WriteSeq = (uint8_t)WR_DATA;
3290    }
3291    else
3292    {
3293        if (0 != skip_size)
3294        {
3295            ps_tpz_info->WriteSeq = (uint8_t)WR_DATA_READ_REQD;
3296
3297        }
3298        else
3299        {
3300            ps_tpz_info->WriteSeq = (uint8_t)WR_DATA;
3301        }
3302    }
3303
3304#ifdef TOPAZ_RAW_SUPPORT
3305    *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_E8;
3306#else
3307    psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write8E;
3308#endif /* #ifdef TOPAZ_RAW_SUPPORT */
3309    result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, write_buf,
3310                                            sizeof (write_buf));
3311
3312    return result;
3313
3314}
3315
3316static
3317NFCSTATUS
3318phFriNfc_Tpz_H_UpdateLenFieldValuesAfterRead (
3319    phFriNfc_NdefMap_t          *psNdefMap)
3320{
3321    /* This function is called, only when the LENGTH field has to be updated
3322        with the correct value */
3323    NFCSTATUS                           result = NFCSTATUS_SUCCESS;
3324    phFriNfc_TopazCont_t                *ps_tpz_info = NULL;
3325    uint16_t                            write_len = 0;
3326    uint16_t                            write_index = 0;
3327    uint16_t                            byte_addr = 0;
3328    phFriNfc_Tpz_WrSeq_t                write_seq;
3329    /* This variable is kept static because if the size to skip LOCK or RESERVED
3330    bytes extends to next read then it shall be stored and used to skip the next
3331    read the bytes
3332    */
3333    static uint16_t                     skip_size = 0;
3334    uint8_t                             write_buf[TOPAZ_WRITE_8_DATA_LENGTH];
3335    uint8_t                             exit_while = FALSE;
3336
3337    ps_tpz_info = &(psNdefMap->TopazContainer);
3338    write_len = (uint16_t)((psNdefMap->ApduBufferSize < ps_tpz_info->NDEFRWSize) ?
3339                psNdefMap->ApduBufferSize : ps_tpz_info->NDEFRWSize);
3340
3341    psNdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE;
3342
3343    (void)memcpy ((void *)write_buf, (void *)psNdefMap->SendRecvBuf,
3344                    TOPAZ_WRITE_8_DATA_LENGTH);
3345
3346    write_seq = (phFriNfc_Tpz_WrSeq_t)ps_tpz_info->WriteSeq;
3347
3348    if (WR_LEN_1_VALUE == write_seq)
3349    {
3350        /* First LENGTH field is geting updated, so the skip size
3351            reset is done */
3352        skip_size = 0;
3353    }
3354
3355    if (0 != ps_tpz_info->ByteNumber)
3356    {
3357        /* Byte Number is not 0, means that some data shall not be overwriteen till
3358            that position in the block */
3359        write_index = (uint16_t)(write_index + ps_tpz_info->ByteNumber);
3360    }
3361
3362    if (0 != skip_size)
3363    {
3364        /* This is possible after updating the FIRST length field
3365            skip size is skipped because of the pending LOCK or
3366            RESERVED bytes
3367        */
3368        write_index = (uint16_t)(write_index + skip_size);
3369    }
3370
3371    while ((write_index < TOPAZ_WRITE_8_DATA_LENGTH) &&
3372        (FALSE == exit_while))
3373    {
3374        skip_size = 0;
3375        /* Get the exact byte address from the block number and
3376            byte number */
3377        byte_addr = TOPAZ_BYTE_ADR_FROM_BLK (ps_tpz_info->CurrentBlock,
3378                                            ps_tpz_info->ByteNumber);
3379        /* Get the skip size */
3380        skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, byte_addr);
3381
3382        if (0 == skip_size)
3383        {
3384            switch (write_seq)
3385            {
3386                case WR_LEN_1_VALUE:
3387                {
3388                    /* First sequenc is always to update 1st LENGTH field of the TLV */
3389                    if (write_len < 0xFF)
3390                    {
3391                        /* This means the LENGTH field is only one BYTE */
3392                        write_buf[write_index] = (uint8_t)
3393                                        psNdefMap->ApduBuffIndex;
3394                        /* Exit the loop */
3395                        exit_while = TRUE;
3396                    }
3397                    else
3398                    {
3399                        /* Update the 1st LENGTH field */
3400                        write_buf[write_index] = (uint8_t)0xFF;
3401                    }
3402                    break;
3403                }
3404
3405                case WR_LEN_2_VALUE:
3406                {
3407                    /* Update the 2nd LENGTH field */
3408                    write_buf[write_index] = (uint8_t)
3409                                (psNdefMap->ApduBuffIndex >> BYTE_SIZE);
3410                    break;
3411                }
3412
3413                case WR_LEN_3_VALUE:
3414                {
3415                    /* Update the 3rd LENGTH field */
3416                    write_buf[write_index] = (uint8_t)
3417                                (psNdefMap->ApduBuffIndex &
3418                                TOPAZ_BYTE_LENGTH_MASK);
3419                    /* Exit the loop */
3420                    exit_while = TRUE;
3421                    break;
3422                }
3423
3424                default:
3425                {
3426                    /* Invalid case */
3427                    break;
3428                }
3429            }
3430            write_index = (uint16_t)(write_index + 1);
3431            if (
3432                /* As the write is done for 8 bytes, the write index cant
3433                    go for more than or equal to 8 bytes, if it reaches 8 bytes
3434                    then sequence shall not be incrmented */
3435                (TOPAZ_WRITE_8_DATA_LENGTH != write_index) &&
3436                /* If the last length field byte is updated then the
3437                    write sequence shall not be incremented */
3438                (WR_LEN_3_VALUE != write_seq) &&
3439                /* Check added if the write length is less than 0xFF.
3440                    If length is less than 0xFF, then write sequence
3441                    shall not be incremented */
3442                (write_len >= 0xFF)
3443                )
3444            {
3445                /* Sequence is incremented to the next level */
3446                write_seq = (phFriNfc_Tpz_WrSeq_t)(write_seq + 1);
3447            }
3448            /* Byte number is incremented */
3449            ps_tpz_info->ByteNumber = (uint8_t)
3450                            (ps_tpz_info->ByteNumber + 1);
3451        }
3452        else
3453        {
3454
3455            if (skip_size >= (TOPAZ_WRITE_8_DATA_LENGTH - write_index))
3456            {
3457                skip_size = (uint16_t)(skip_size - (TOPAZ_WRITE_8_DATA_LENGTH
3458                            - write_index));
3459                write_index = (uint16_t)TOPAZ_WRITE_8_DATA_LENGTH;
3460            }
3461            else
3462            {
3463                ps_tpz_info->ByteNumber = (uint8_t)
3464                            (ps_tpz_info->ByteNumber + skip_size);
3465                write_index = (uint16_t)(write_index + skip_size);
3466                skip_size = 0;
3467            }
3468
3469        }
3470    }
3471
3472    ps_tpz_info->WriteSeq = (uint8_t)write_seq;
3473
3474#ifdef TOPAZ_RAW_SUPPORT
3475    *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_E8;
3476#else
3477    psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write8E;
3478#endif /* #ifdef TOPAZ_RAW_SUPPORT */
3479
3480    result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, write_buf,
3481                                            sizeof (write_buf));
3482    return result;
3483}
3484
3485
3486
3487static
3488NFCSTATUS
3489phFriNfc_Tpz_H_UpdateLenFieldZeroAfterRead (
3490    phFriNfc_NdefMap_t          *psNdefMap)
3491{
3492    /* This function is called, only when the LENGTH field has to be updated
3493        with the 0 */
3494    NFCSTATUS                           result = NFCSTATUS_SUCCESS;
3495    phFriNfc_TopazCont_t                *ps_tpz_info = NULL;
3496    uint16_t                            write_len = 0;
3497    uint16_t                            write_index = 0;
3498    uint16_t                            prev_apdu_index = 0;
3499    uint16_t                            byte_addr = 0;
3500    phFriNfc_Tpz_WrSeq_t                write_seq;
3501    /* This variable is kept static because if the size to skip LOCK or RESERVED
3502        bytes extends to next read then it shall be stored and used to skip the next
3503        read bytes
3504    */
3505    static uint16_t                     skip_size = 0;
3506    uint8_t                             write_buf[TOPAZ_WRITE_8_DATA_LENGTH];
3507
3508    ps_tpz_info = &(psNdefMap->TopazContainer);
3509    write_len = (uint16_t)((psNdefMap->ApduBufferSize < ps_tpz_info->NDEFRWSize) ?
3510                psNdefMap->ApduBufferSize : ps_tpz_info->NDEFRWSize);
3511
3512    psNdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE;
3513
3514    (void)memcpy ((void *)write_buf, (void *)psNdefMap->SendRecvBuf,
3515                    TOPAZ_WRITE_8_DATA_LENGTH);
3516
3517    prev_apdu_index = psNdefMap->ApduBuffIndex;
3518    write_seq = (phFriNfc_Tpz_WrSeq_t)ps_tpz_info->WriteSeq;
3519
3520    if (WR_LEN_1_0 == write_seq)
3521    {
3522         /* First LENGTH field is geting updated, so the skip size
3523            reset is done */
3524        skip_size = 0;
3525    }
3526
3527    if (0 != ps_tpz_info->ByteNumber)
3528    {
3529        /* Byte Number is not 0, means that some data shall not be overwriteen till
3530            that position in the block */
3531        write_index = (uint16_t)(write_index + ps_tpz_info->ByteNumber);
3532        ps_tpz_info->ByteNumber = 0;
3533    }
3534
3535    if (0 != skip_size)
3536    {
3537        /* This is possible after updating the FIRST length field
3538            skip size is skipped because of the pending LOCK or
3539            RESERVED bytes
3540        */
3541        write_index = (uint16_t)(write_index + skip_size);
3542    }
3543
3544    while ((write_index < TOPAZ_WRITE_8_DATA_LENGTH) &&
3545        (write_len != psNdefMap->ApduBuffIndex))
3546    {
3547        skip_size = 0;
3548        byte_addr = TOPAZ_BYTE_ADR_FROM_BLK (ps_tpz_info->CurrentBlock,
3549                                            ps_tpz_info->ByteNumber);
3550        skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, byte_addr);
3551
3552        if (0 == skip_size)
3553        {
3554            switch (write_seq)
3555            {
3556                case WR_LEN_1_0:
3557                {
3558                    /* First sequence is always to update 1st LENGTH field
3559                        of the TLV */
3560                    write_buf[write_index] = 0x00;
3561                    write_index = (uint16_t)(write_index + 1);
3562                    if (write_len < 0xFF)
3563                    {
3564                        /* LENGTH field is only 1 byte, so update change the sequence to
3565                            update user data */
3566                        write_seq = WR_DATA;
3567                    }
3568                    else
3569                    {
3570                        /* Go to the next LENGTH field to update */
3571                        write_seq = (phFriNfc_Tpz_WrSeq_t)((TOPAZ_WRITE_8_DATA_LENGTH !=
3572                                    write_index) ?
3573                                    (write_seq + 1) : write_seq);
3574                    }
3575                    break;
3576                }
3577
3578                case WR_LEN_2_0:
3579                case WR_LEN_3_0:
3580                {
3581                    /* Update 2nd and 3rd LEGNTH field */
3582                    write_buf[write_index] = 0x00;
3583                    write_index = (uint16_t)(write_index + 1);
3584                    write_seq = (phFriNfc_Tpz_WrSeq_t)((TOPAZ_WRITE_8_DATA_LENGTH !=
3585                                write_index) ?
3586                                (write_seq + 1) : write_seq);
3587                    break;
3588                }
3589
3590                case WR_DATA:
3591                default:
3592                {
3593                    /* Update the buffer by the user data */
3594                    write_buf[write_index] =
3595                            psNdefMap->ApduBuffer[psNdefMap->ApduBuffIndex];
3596
3597                    write_index = (uint16_t)(write_index + 1);
3598                    psNdefMap->ApduBuffIndex = (uint16_t)
3599                                        (psNdefMap->ApduBuffIndex + 1);
3600                    break;
3601                }
3602
3603            }
3604
3605            ps_tpz_info->ByteNumber = (uint8_t)
3606                            (ps_tpz_info->ByteNumber + 1);
3607        }
3608        else
3609        {
3610            /* LOCK and MEMORY bytes are found */
3611            if (skip_size >= (TOPAZ_WRITE_8_DATA_LENGTH - write_index))
3612            {
3613                /* skip size has exceeded the block number, so calculate the
3614                remaining skip size  */
3615                skip_size = (uint16_t)(skip_size - (TOPAZ_WRITE_8_DATA_LENGTH
3616                            - write_index));
3617                write_index = (uint16_t)TOPAZ_WRITE_8_DATA_LENGTH;
3618            }
3619            else
3620            {
3621                /* skip the LOCK and MEMORY bytes size */
3622                ps_tpz_info->ByteNumber = (uint8_t)
3623                            (ps_tpz_info->ByteNumber + skip_size);
3624                write_index = (uint16_t)(write_index + skip_size);
3625                skip_size = 0;
3626            }
3627        }
3628    }
3629
3630    if (psNdefMap->ApduBuffIndex == write_len)
3631    {
3632        /* User data has been completely copied and it is ready to write, so
3633            change the sequence */
3634        ps_tpz_info->WriteSeq = (uint8_t)WR_DATA;
3635    }
3636    else if ((WR_DATA == write_seq) && (prev_apdu_index ==
3637        psNdefMap->ApduBuffIndex))
3638    {
3639        /* The user data has not been written, only the LENGTH field is
3640            updated */
3641        ps_tpz_info->WriteSeq = (uint8_t)((write_len < 0xFF) ?
3642                                WR_LEN_1_0 : WR_LEN_3_0);
3643    }
3644    else
3645    {
3646        /*  Update the sequence in the context */
3647        ps_tpz_info->WriteSeq = (uint8_t)write_seq;
3648    }
3649
3650    ps_tpz_info->ByteNumber = 0;
3651
3652#ifdef TOPAZ_RAW_SUPPORT
3653    *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_E8;
3654#else
3655    psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write8E;
3656#endif /* #ifdef TOPAZ_RAW_SUPPORT */
3657
3658    result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, write_buf,
3659                                            sizeof (write_buf));
3660    return result;
3661}
3662
3663static
3664NFCSTATUS
3665phFriNfc_Tpz_H_RdForWrite (
3666    phFriNfc_NdefMap_t          *psNdefMap)
3667{
3668    NFCSTATUS                           result = NFCSTATUS_SUCCESS;
3669    phFriNfc_TopazCont_t                *ps_tpz_info = NULL;
3670    phFriNfc_Tpz_WrSeq_t                write_seq;
3671    uint16_t                            byte_addr = 0;
3672    uint8_t                             exit_while = FALSE;
3673    uint16_t                            skip_size = 0;
3674
3675    ps_tpz_info = &(psNdefMap->TopazContainer);
3676    write_seq = (phFriNfc_Tpz_WrSeq_t)(ps_tpz_info->WriteSeq);
3677
3678#ifdef TOPAZ_RAW_SUPPORT
3679
3680    *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ8;
3681
3682#else
3683
3684    psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read8;
3685
3686#endif /* #ifdef TOPAZ_RAW_SUPPORT */
3687
3688    psNdefMap->State = PH_FRINFC_TOPAZ_STATE_RD_FOR_WR_NDEF;
3689
3690    switch (write_seq)
3691    {
3692        case WR_LEN_1_0:
3693        case WR_LEN_1_VALUE:
3694        {
3695            byte_addr = (ps_tpz_info->NdefTLVByteAddress + 1);
3696
3697            /* This loop is to skip the lock amd reserved bytes */
3698            while (FALSE == exit_while)
3699            {
3700                if (TOPAZ_STATIC_LOCK_FIRST_BLOCK_NO ==
3701                    TOPAZ_BLK_FROM_BYTE_ADR (byte_addr))
3702                {
3703                    byte_addr = (uint16_t)(byte_addr +
3704                                TOPAZ_STATIC_LOCK_RES_BYTES);
3705                }
3706                skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap,
3707                                                            byte_addr);
3708                if (0 != skip_size)
3709                {
3710                    byte_addr = (uint16_t)(byte_addr + skip_size);
3711
3712
3713                }
3714                else
3715                {
3716                    exit_while = TRUE;
3717                }
3718            }
3719            break;
3720        }
3721
3722        case WR_LEN_2_0:
3723        case WR_LEN_3_0:
3724        case WR_LEN_2_VALUE:
3725        case WR_LEN_3_VALUE:
3726        {
3727            byte_addr = (uint16_t)TOPAZ_BYTE_ADR_FROM_BLK (ps_tpz_info->CurrentBlock,
3728                                                    ps_tpz_info->ByteNumber);
3729            /* This loop is for to skip the lock amd reserved bytes */
3730            while (FALSE == exit_while)
3731            {
3732                skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap,
3733                                                            byte_addr);
3734                if (0 != skip_size)
3735                {
3736                    byte_addr = (uint16_t)(byte_addr + skip_size);
3737                }
3738                else
3739                {
3740                    exit_while = TRUE;
3741                }
3742            }
3743            break;
3744        }
3745
3746        case WR_DATA_READ_REQD:
3747        {
3748            /* Lock or reserved bytes found bytes */
3749            byte_addr = (uint16_t)TOPAZ_BYTE_ADR_FROM_BLK (ps_tpz_info->CurrentBlock,
3750                                                    ps_tpz_info->ByteNumber);
3751            break;
3752        }
3753
3754        default:
3755        {
3756            break;
3757        }
3758    }
3759
3760    ps_tpz_info->CurrentBlock = (uint8_t)
3761                        TOPAZ_BLK_FROM_BYTE_ADR (byte_addr);
3762    ps_tpz_info->ByteNumber = (uint8_t)
3763                        TOPAZ_BYTE_OFFSET_FROM_BYTE_ADR (byte_addr);
3764
3765    result = phFriNfc_Tpz_H_NxpRead (psNdefMap);
3766
3767    return result;
3768}
3769
3770static
3771uint16_t
3772phFriNfc_Tpz_H_CompareLockBlocks (
3773    phFriNfc_NdefMap_t          *psNdefMap,
3774    uint8_t                     block_no,
3775    uint16_t                    *p_skip_size)
3776{
3777    uint16_t                            return_addr = 0;
3778    phFriNfc_LockCntrlTLVCont_t         *ps_locktlv_info = NULL;
3779
3780    ps_locktlv_info = &(psNdefMap->LockTlv);
3781
3782    if (block_no == ps_locktlv_info->BlkNum)
3783    {
3784        /* ps_tpz_info->ByteNumber = (uint8_t)ps_locktlv_info->ByteNum; */
3785        *p_skip_size = ps_locktlv_info->Size;
3786        return_addr = ps_locktlv_info->ByteAddr;
3787    }
3788
3789    return return_addr;
3790}
3791
3792static
3793uint16_t
3794phFriNfc_Tpz_H_CompareMemBlocks (
3795    phFriNfc_NdefMap_t          *psNdefMap,
3796    uint8_t                     block_no,
3797    uint16_t                    *p_skip_size)
3798{
3799    uint16_t                            return_addr = 0;
3800    phFriNfc_ResMemCntrlTLVCont_t       *ps_memtlv_info = NULL;
3801
3802    ps_memtlv_info = &(psNdefMap->MemTlv);
3803
3804    if (block_no == ps_memtlv_info->BlkNum)
3805    {
3806        /* ps_tpz_info->ByteNumber = (uint8_t)ps_memtlv_info->ByteNum; */
3807        *p_skip_size = ps_memtlv_info->Size;
3808        return_addr = ps_memtlv_info->ByteAddr;
3809    }
3810
3811    return return_addr;
3812}
3813
3814
3815static
3816NFCSTATUS
3817phFriNfc_Tpz_H_CopySendWrData (
3818    phFriNfc_NdefMap_t          *psNdefMap)
3819{
3820    NFCSTATUS                           result = NFCSTATUS_SUCCESS;
3821    phFriNfc_TopazCont_t                *ps_tpz_info = NULL;
3822    uint8_t                             write_buf[TOPAZ_WRITE_8_DATA_LENGTH];
3823    uint16_t                            write_len;
3824    uint8_t                             copy_length;
3825    uint16_t                            skip_size = 0;
3826
3827    ps_tpz_info = &(psNdefMap->TopazContainer);
3828    write_len = (uint16_t)((psNdefMap->ApduBufferSize < ps_tpz_info->NDEFRWSize) ?
3829                psNdefMap->ApduBufferSize : ps_tpz_info->NDEFRWSize);
3830
3831    if (0 != phFriNfc_Tpz_H_CompareLockBlocks (psNdefMap,
3832                ps_tpz_info->CurrentBlock, &skip_size))
3833    {
3834        ps_tpz_info->WriteSeq = (uint8_t)WR_DATA_READ_REQD;
3835        ps_tpz_info->ByteNumber = 0;
3836        result = phFriNfc_Tpz_H_RdForWrite (psNdefMap);
3837    }
3838    else if (0 != phFriNfc_Tpz_H_CompareMemBlocks (psNdefMap,
3839                ps_tpz_info->CurrentBlock, &skip_size))
3840    {
3841        ps_tpz_info->WriteSeq = (uint8_t)WR_DATA_READ_REQD;
3842        ps_tpz_info->ByteNumber = 0;
3843        result = phFriNfc_Tpz_H_RdForWrite (psNdefMap);
3844    }
3845    else
3846    {
3847#ifdef TOPAZ_RAW_SUPPORT
3848        *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_E8;
3849#else
3850        psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write8E;
3851#endif /* #ifdef TOPAZ_RAW_SUPPORT */
3852        psNdefMap->State = (uint8_t)PH_FRINFC_TOPAZ_STATE_WRITE;
3853
3854        if ((write_len - psNdefMap->ApduBuffIndex) >= (uint16_t)TOPAZ_WRITE_8_DATA_LENGTH)
3855        {
3856            copy_length = (uint8_t)TOPAZ_WRITE_8_DATA_LENGTH;
3857            (void)memcpy ((void *)write_buf,
3858                    (void *)(psNdefMap->ApduBuffer + psNdefMap->ApduBuffIndex),
3859                    copy_length);
3860
3861            psNdefMap->ApduBuffIndex = (uint16_t)(psNdefMap->ApduBuffIndex +
3862                                        copy_length);
3863        }
3864        else
3865        {
3866            copy_length = (uint8_t)(write_len - psNdefMap->ApduBuffIndex);
3867
3868            (void)memcpy ((void *)write_buf,
3869                    (void *)(psNdefMap->ApduBuffer + psNdefMap->ApduBuffIndex),
3870                    TOPAZ_WRITE_8_DATA_LENGTH);
3871
3872            psNdefMap->ApduBuffIndex = (uint16_t)(psNdefMap->ApduBuffIndex +
3873                                        copy_length);
3874
3875            (void)memset ((void *)(write_buf + copy_length), 0x00,
3876                        (TOPAZ_WRITE_8_DATA_LENGTH - copy_length));
3877        }
3878
3879#ifdef TOPAZ_RAW_SUPPORT
3880        *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_E8;
3881#else
3882        psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write8E;
3883#endif /* #ifdef TOPAZ_RAW_SUPPORT */
3884
3885        result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, write_buf,
3886                                            sizeof (write_buf));
3887    }
3888
3889
3890    return result;
3891}
3892
3893
3894static
3895NFCSTATUS
3896phFriNfc_Tpz_H_ActualCardSize (
3897    phFriNfc_NdefMap_t          *psNdefMap)
3898{
3899    NFCSTATUS                           result = NFCSTATUS_SUCCESS;
3900    phFriNfc_TopazCont_t                *ps_tpz_info = NULL;
3901    phFriNfc_LockCntrlTLVCont_t         *ps_locktlv_info = NULL;
3902    phFriNfc_ResMemCntrlTLVCont_t       *ps_memtlv_info = NULL;
3903    uint16_t                            ndef_value_byte_addr = 0;
3904    uint16_t                            ndef_read_write_size = 0;
3905
3906    ps_tpz_info = &(psNdefMap->TopazContainer);
3907    if (ps_tpz_info->ActualNDEFMsgSize > ps_tpz_info->RemainingSize)
3908    {
3909        ps_tpz_info->ActualNDEFMsgSize = 0;
3910        result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
3911                            NFCSTATUS_NO_NDEF_SUPPORT);
3912    }
3913    else
3914    {
3915        ndef_read_write_size = ps_tpz_info->RemainingSize;
3916        ndef_value_byte_addr = phFriNfc_Tpz_H_GetNDEFValueFieldAddrForRead
3917                                (psNdefMap);
3918
3919        ps_locktlv_info = &(psNdefMap->LockTlv);
3920        if (ps_locktlv_info->ByteAddr > ndef_value_byte_addr)
3921        {
3922            ndef_read_write_size = (ndef_read_write_size -
3923                                    ps_locktlv_info->Size);
3924        }
3925
3926        ps_memtlv_info = &(psNdefMap->MemTlv);
3927        if (ps_memtlv_info->ByteAddr > ndef_value_byte_addr)
3928        {
3929            ndef_read_write_size = (ndef_read_write_size -
3930                                    ps_memtlv_info->Size);
3931        }
3932
3933        if (ps_tpz_info->ActualNDEFMsgSize > ndef_read_write_size)
3934        {
3935            ps_tpz_info->ActualNDEFMsgSize = 0;
3936            result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
3937                                NFCSTATUS_NO_NDEF_SUPPORT);
3938        }
3939        else
3940        {
3941            ps_tpz_info->NDEFRWSize = (uint16_t)
3942                            ((ps_tpz_info->ActualNDEFMsgSize < 0xFF) ?
3943                            (ndef_read_write_size - 2) :
3944                            ndef_read_write_size);
3945        }
3946    }
3947
3948    return result;
3949}
3950
3951static
3952NFCSTATUS
3953phFriNfc_Tpz_H_ParseLockTLVType (
3954    phFriNfc_NdefMap_t          *psNdefMap,
3955    uint8_t                     *p_parse_data,
3956    uint16_t                    *p_parse_index,
3957    uint16_t                    total_len_to_parse,
3958    phFriNfc_Tpz_ParseSeq_t     *seq_to_execute)
3959{
3960    NFCSTATUS                   result = NFCSTATUS_SUCCESS;
3961    uint16_t                    parse_index = *p_parse_index;
3962    phFriNfc_Tpz_ParseSeq_t     expected_seq = *seq_to_execute;
3963
3964    PHNFC_UNUSED_VARIABLE(psNdefMap);
3965    PHNFC_UNUSED_VARIABLE(total_len_to_parse);
3966
3967    switch (p_parse_data[parse_index])
3968    {
3969        case PH_FRINFC_TOPAZ_LOCK_CTRL_T:
3970        {
3971            expected_seq = LOCK_L_TLV;
3972            parse_index = (parse_index + 1);
3973            break;
3974        }
3975
3976        case PH_FRINFC_TOPAZ_NULL_T:
3977        {
3978            expected_seq = LOCK_T_TLV;
3979            parse_index = (parse_index + 1);
3980            break;
3981        }
3982
3983        default:
3984        {
3985            result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
3986                                NFCSTATUS_NO_NDEF_SUPPORT);
3987            break;
3988        }
3989    }
3990
3991
3992    *seq_to_execute = expected_seq;
3993    *p_parse_index = parse_index;
3994    return result;
3995}
3996
3997static
3998NFCSTATUS
3999phFriNfc_Tpz_H_ParseMemTLVType (
4000    phFriNfc_NdefMap_t          *psNdefMap,
4001    uint8_t                     *p_parse_data,
4002    uint16_t                    *p_parse_index,
4003    uint16_t                    total_len_to_parse,
4004    phFriNfc_Tpz_ParseSeq_t     *seq_to_execute)
4005{
4006    NFCSTATUS                   result = NFCSTATUS_SUCCESS;
4007    uint16_t                    parse_index = *p_parse_index;
4008    phFriNfc_Tpz_ParseSeq_t     expected_seq = *seq_to_execute;
4009
4010    PHNFC_UNUSED_VARIABLE(psNdefMap);
4011    PHNFC_UNUSED_VARIABLE(total_len_to_parse);
4012
4013    switch (p_parse_data[parse_index])
4014    {
4015        case PH_FRINFC_TOPAZ_LOCK_CTRL_T:
4016        {
4017            expected_seq = LOCK_L_TLV;
4018            parse_index = (parse_index + 1);
4019            break;
4020        }
4021
4022        case PH_FRINFC_TOPAZ_NULL_T:
4023        {
4024            expected_seq = MEM_T_TLV;
4025            parse_index = (parse_index + 1);
4026            break;
4027        }
4028
4029        case PH_FRINFC_TOPAZ_MEM_CTRL_T:
4030        {
4031            expected_seq = MEM_L_TLV;
4032            parse_index = (parse_index + 1);
4033            break;
4034        }
4035
4036        default:
4037        {
4038            result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
4039                                NFCSTATUS_NO_NDEF_SUPPORT);
4040            break;
4041        }
4042    }
4043
4044    *seq_to_execute = expected_seq;
4045    *p_parse_index = parse_index;
4046    return result;
4047}
4048
4049static
4050NFCSTATUS
4051phFriNfc_Tpz_H_ParseNdefTLVType (
4052    phFriNfc_NdefMap_t          *psNdefMap,
4053    uint8_t                     *p_parse_data,
4054    uint16_t                    *p_parse_index,
4055    uint16_t                    total_len_to_parse,
4056    phFriNfc_Tpz_ParseSeq_t     *seq_to_execute)
4057{
4058    NFCSTATUS                   result = NFCSTATUS_SUCCESS;
4059    uint16_t                    parse_index = *p_parse_index;
4060    phFriNfc_Tpz_ParseSeq_t     expected_seq = *seq_to_execute;
4061
4062    PHNFC_UNUSED_VARIABLE(psNdefMap);
4063    PHNFC_UNUSED_VARIABLE(total_len_to_parse);
4064
4065    switch (p_parse_data[parse_index])
4066    {
4067        case PH_FRINFC_TOPAZ_MEM_CTRL_T:
4068        {
4069            /* TYPE field of Memory control TLV is found.
4070                This means that more than one memory control
4071                TLV exists */
4072            expected_seq = MEM_L_TLV;
4073            parse_index = (parse_index + 1);
4074            break;
4075        }
4076
4077        case PH_FRINFC_TOPAZ_NULL_T:
4078        {
4079            /* Skip the NULL TLV */
4080            expected_seq = NDEF_T_TLV;
4081            parse_index = (parse_index + 1);
4082            break;
4083        }
4084
4085        case PH_FRINFC_TOPAZ_NDEF_T:
4086        {
4087            /* TYPE field of NDEF TLV found, so next expected
4088                sequence is LENGTH field */
4089            expected_seq = NDEF_L_TLV;
4090            parse_index = (parse_index + 1);
4091            break;
4092        }
4093
4094        default:
4095        {
4096            /* Reset the sequence */
4097            expected_seq = LOCK_T_TLV;
4098            result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
4099                                NFCSTATUS_NO_NDEF_SUPPORT);
4100            break;
4101        }
4102    }
4103
4104    *seq_to_execute = expected_seq;
4105    *p_parse_index = parse_index;
4106    return result;
4107}
4108
4109static
4110uint16_t
4111phFriNfc_Tpz_H_GetSkipSize (
4112    phFriNfc_NdefMap_t          *psNdefMap,
4113    uint16_t                    byte_adr_card)
4114{
4115    uint16_t                        return_size = 0;
4116    phFriNfc_LockCntrlTLVCont_t     *ps_locktlv_info = NULL;
4117    phFriNfc_ResMemCntrlTLVCont_t   *ps_memtlv_info = NULL;
4118
4119    ps_locktlv_info = &(psNdefMap->LockTlv);
4120    ps_memtlv_info = &(psNdefMap->MemTlv);
4121
4122    /* If there are more than one LOCK CONTROL TLV, then
4123    ADD A LOOP HERE OF THE NUMBER OF TLVs FOUND */
4124    if (byte_adr_card == ps_locktlv_info->ByteAddr)
4125    {
4126        return_size = ps_locktlv_info->Size;
4127    }
4128
4129    /* If there are more than one MEMORY CONTROL TLV, then
4130        ADD A LOOP HERE OF THE NUMBER OF TLVs FOUND */
4131    if (byte_adr_card == ps_memtlv_info->ByteAddr)
4132    {
4133        return_size = ps_memtlv_info->Size;
4134    }
4135    return return_size;
4136}
4137
4138static
4139NFCSTATUS
4140phFriNfc_Tpz_H_GetLockBytesInfo (
4141    phFriNfc_NdefMap_t          *psNdefMap,
4142    uint8_t                     *p_lock_info)
4143{
4144    NFCSTATUS                       result = NFCSTATUS_SUCCESS;
4145    phFriNfc_LockCntrlTLVCont_t     *ps_locktlv_info = NULL;
4146    uint8_t                         page_address = 0;
4147    uint8_t                         bytes_offset = 0;
4148    uint8_t                         lock_index = 0;
4149
4150    ps_locktlv_info = &(psNdefMap->LockTlv);
4151
4152    page_address = (uint8_t)(p_lock_info[lock_index] >> NIBBLE_SIZE);
4153    bytes_offset = (uint8_t)(p_lock_info[lock_index] & TOPAZ_NIBBLE_MASK);
4154
4155    lock_index = (lock_index + 1);
4156    ps_locktlv_info->Size = (uint16_t)
4157                            (((p_lock_info[lock_index] % TOPAZ_BYTE_SIZE_IN_BITS) > 0)?
4158                            ((p_lock_info[lock_index] / TOPAZ_BYTE_SIZE_IN_BITS) + 1) :
4159                            (p_lock_info[lock_index] / TOPAZ_BYTE_SIZE_IN_BITS));
4160
4161    lock_index = (lock_index + 1);
4162    ps_locktlv_info->BytesPerPage =
4163                            (p_lock_info[lock_index] & TOPAZ_NIBBLE_MASK);
4164    ps_locktlv_info->BytesLockedPerLockBit =
4165                            (p_lock_info[lock_index] >> NIBBLE_SIZE);
4166
4167    /* Apply the formula to calculate byte address
4168        ByteAddr = PageAddr*2^BytesPerPage + ByteOffset
4169    */
4170    ps_locktlv_info->ByteAddr = (uint16_t)((page_address
4171                                * (1 << ps_locktlv_info->BytesPerPage))
4172                                + bytes_offset);
4173
4174
4175    if (
4176        /* Out of bound memory check */
4177        ((ps_locktlv_info->ByteAddr + ps_locktlv_info->Size) >
4178        (uint16_t)(psNdefMap->TopazContainer.CCByteBuf[2] *
4179        TOPAZ_BYTES_PER_BLOCK)) ||
4180
4181        /* Check the static lock and reserved areas memory blocks */
4182        ((ps_locktlv_info->ByteAddr >= TOPAZ_STATIC_LOCK_RES_START) &&
4183        (ps_locktlv_info->ByteAddr < TOPAZ_STATIC_LOCK_RES_END)) ||
4184        (((ps_locktlv_info->ByteAddr + ps_locktlv_info->Size - 1) >=
4185        TOPAZ_STATIC_LOCK_RES_START) &&
4186        ((ps_locktlv_info->ByteAddr + ps_locktlv_info->Size - 1) <
4187        TOPAZ_STATIC_LOCK_RES_END))
4188        )
4189    {
4190        ps_locktlv_info->ByteAddr = 0;
4191        result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
4192                            NFCSTATUS_NO_NDEF_SUPPORT);
4193    }
4194    else
4195    {
4196        ps_locktlv_info->BlkNum = (ps_locktlv_info->ByteAddr /
4197                                    TOPAZ_BYTES_PER_BLOCK);
4198        ps_locktlv_info->ByteNum = (ps_locktlv_info->ByteAddr %
4199                                    TOPAZ_BYTES_PER_BLOCK);
4200    }
4201
4202    return result;
4203}
4204
4205static
4206NFCSTATUS
4207phFriNfc_Tpz_H_GetMemBytesInfo (
4208    phFriNfc_NdefMap_t          *psNdefMap,
4209    uint8_t                     *p_mem_info)
4210{
4211    NFCSTATUS                       result = NFCSTATUS_SUCCESS;
4212    phFriNfc_ResMemCntrlTLVCont_t   *ps_memtlv_info = NULL;
4213    phFriNfc_LockCntrlTLVCont_t     *ps_locktlv_info = NULL;
4214    uint8_t                         page_address = 0;
4215    uint8_t                         bytes_offset = 0;
4216    uint8_t                         mem_index = 0;
4217
4218    ps_memtlv_info = &(psNdefMap->MemTlv);
4219    ps_locktlv_info = &(psNdefMap->LockTlv);
4220    page_address = (uint8_t)(p_mem_info[mem_index] >> NIBBLE_SIZE);
4221    bytes_offset = (uint8_t)(p_mem_info[mem_index] & TOPAZ_NIBBLE_MASK);
4222
4223    mem_index = (mem_index + 1);
4224    ps_memtlv_info->Size = (uint16_t)p_mem_info[mem_index];
4225
4226    mem_index = (mem_index + 1);
4227    ps_memtlv_info->BytesPerPage =
4228                            (p_mem_info[mem_index] & TOPAZ_NIBBLE_MASK);
4229
4230    /* Apply the formula to calculate byte address
4231        ByteAddr = PageAddr * 2^BytesPerPage + ByteOffset
4232    */
4233    ps_memtlv_info->ByteAddr = (uint16_t)((page_address
4234                            * (1 << ps_memtlv_info->BytesPerPage))
4235                            + bytes_offset);
4236
4237
4238    if (
4239        /* Check if the lock and memory bytes are overlapped */
4240        ((ps_memtlv_info->ByteAddr >= ps_locktlv_info->ByteAddr) &&
4241        (ps_memtlv_info->ByteAddr <=
4242        (ps_locktlv_info->ByteAddr + ps_locktlv_info->Size - 1))) ||
4243
4244        (((ps_memtlv_info->ByteAddr + ps_memtlv_info->Size - 1) >=
4245        ps_locktlv_info->ByteAddr) &&
4246        ((ps_memtlv_info->ByteAddr + ps_memtlv_info->Size - 1) <=
4247        (ps_locktlv_info->ByteAddr + ps_locktlv_info->Size - 1))) ||
4248
4249        /* Check the static lock and reserved areas memory blocks */
4250        ((ps_memtlv_info->ByteAddr >= TOPAZ_STATIC_LOCK_RES_START) &&
4251        (ps_memtlv_info->ByteAddr < TOPAZ_STATIC_LOCK_RES_END)) ||
4252        (((ps_memtlv_info->ByteAddr + ps_memtlv_info->Size - 1) >=
4253        TOPAZ_STATIC_LOCK_RES_START) &&
4254        ((ps_memtlv_info->ByteAddr + ps_memtlv_info->Size - 1) <
4255        TOPAZ_STATIC_LOCK_RES_END)) ||
4256
4257        /* Check if the memory address is out bound */
4258        ((ps_locktlv_info->ByteAddr + ps_locktlv_info->Size) >
4259        (uint16_t)(psNdefMap->TopazContainer.CCByteBuf[2] *
4260        TOPAZ_BYTES_PER_BLOCK))
4261        )
4262    {
4263        ps_memtlv_info->ByteAddr = 0;
4264        result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
4265                            NFCSTATUS_NO_NDEF_SUPPORT);
4266    }
4267    else
4268    {
4269        ps_memtlv_info->BlkNum = (ps_memtlv_info->ByteAddr /
4270                                    TOPAZ_BYTES_PER_BLOCK);
4271        ps_memtlv_info->ByteNum = (ps_memtlv_info->ByteAddr %
4272                                    TOPAZ_BYTES_PER_BLOCK);
4273    }
4274
4275    return result;
4276}
4277
4278#ifdef UNIT_TEST
4279#include <phUnitTestNfc_TopazDynamic_static.c>
4280#endif
4281
4282#endif  /*#if !(defined(PH_FRINFC_MAP_TOPAZ_DISABLED ) || defined (PH_FRINFC_MAP_TOPAZ_DYNAMIC_DISABLED ))*/
4283
4284
4285
4286