phFriNfc_TopazMap.c revision 80ee29b88ec489e2bbf6ae446692229d36755429
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_TopazMap.c
19* \brief NFC Ndef Mapping For Remote Devices.
20*
21* Project: NFC-FRI
22*
23* $Date: Wed May 12 10:21:17 2010 $
24* $Author: ing02260 $
25* $Revision: 1.21 $
26* $Aliases: NFC_FRI1.1_WK1019_SDK,NFC_FRI1.1_WK1023_R35_1 $
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#ifndef PH_FRINFC_MAP_TOPAZ_DISABLED
38/*! \ingroup grp_file_attributes
39*  \name NDEF Mapping
40*
41* File: \ref phFriNfcNdefMap.c
42*
43*/
44/*@{*/
45#define PHFRINFCTOPAZMAP_FILEREVISION "$Revision: 1.21 $"
46#define PHFRINFCTOPAZMAP_FILEALIASES  "$Aliases: NFC_FRI1.1_WK1019_SDK,NFC_FRI1.1_WK1023_R35_1 $"
47/*@}*/
48/****************** Start of macros ********************/
49/* Below MACRO is used for the WRITE error scenario,
50    in case PN544 returns error for any WRITE, then
51    read the written block and byte number, to check the data
52    written to the card is correct or not
53*/
54/* #define TOPAZ_RF_ERROR_WORKAROUND */
55
56#ifdef FRINFC_READONLY_NDEF
57
58    #define CC_BLOCK_NUMBER                                         (0x01U)
59    #define CC_RWA_BYTE_NUMBER                                      (0x03U)
60    #define CC_READ_ONLY_VALUE                                      (0x0FU)
61
62#endif /* #ifdef FRINFC_READONLY_NDEF */
63
64#ifdef TOPAZ_RF_ERROR_WORKAROUND
65
66    /* Below MACROs are added for the error returned from HAL, if the
67        below error has occured during the WRITE, then read the error
68        returned blocks to confirm */
69    #define FRINFC_RF_TIMEOUT_89                                    (0x89U)
70    #define FRINFC_RF_TIMEOUT_90                                    (0x90U)
71
72    /* State specific to read after the RF ERROR for the WRITE */
73    #define PH_FRINFC_TOPAZ_STATE_RF_ERROR_READ                     (0x0FU)
74
75#endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */
76
77/****************** End of macros ********************/
78
79/*!
80* \name Topaz Mapping - Helper Functions
81*
82*/
83/*@{*/
84
85/*!
86* \brief \copydoc page_ovr Helper function for Topaz. This function shall read 8 bytes
87*  from the card.
88*/
89static NFCSTATUS phFriNfc_Tpz_H_RdBytes(phFriNfc_NdefMap_t *NdefMap,
90                                        uint16_t             BlockNo,
91                                        uint16_t             ByteNo);
92
93/*!
94* \brief \copydoc page_ovr Helper function for Topaz. This function shall process
95* read id command
96*/
97static NFCSTATUS phFriNfc_Tpz_H_ProReadID(phFriNfc_NdefMap_t *NdefMap);
98
99/*!
100* \brief \copydoc page_ovr Helper function for Topaz. This function shall process
101* read all command
102*/
103static NFCSTATUS phFriNfc_Tpz_H_ProReadAll(phFriNfc_NdefMap_t *NdefMap);
104
105/*!
106* \brief \copydoc page_ovr Helper function for Topaz. This function depends on
107* function called by the user
108*/
109static NFCSTATUS phFriNfc_Tpz_H_CallNxtOp(phFriNfc_NdefMap_t *NdefMap);
110
111/*!
112* \brief \copydoc page_ovr Helper function for Topaz. This function checks the CC
113* bytes
114*/
115static NFCSTATUS phFriNfc_Tpz_H_ChkCCBytes(phFriNfc_NdefMap_t *NdefMap);
116
117/*!
118* \brief \copydoc page_ovr Helper function for Topaz. This function finds
119* NDEF TLV
120*/
121static NFCSTATUS phFriNfc_Tpz_H_findNDEFTLV(phFriNfc_NdefMap_t *NdefMap);
122
123/*!
124* \brief \copydoc page_ovr Helper function for Topaz. This function writes a
125* byte into the card
126*/
127static NFCSTATUS phFriNfc_Tpz_H_WrAByte(phFriNfc_NdefMap_t *NdefMap,
128                                        uint16_t             BlockNo,
129                                        uint16_t             ByteNo,
130                                        uint8_t              ByteVal
131                                        );
132
133/*!
134* \brief \copydoc page_ovr Helper function for Topaz. This function shall process the
135* NMN write
136*/
137static NFCSTATUS phFriNfc_Tpz_H_ProWrNMN(phFriNfc_NdefMap_t *NdefMap);
138
139/*!
140* \brief \copydoc page_ovr Helper function for Topaz. This function writes the length field of
141* the NDEF TLV
142*/
143static NFCSTATUS phFriNfc_Tpz_H_ProWrTLV(phFriNfc_NdefMap_t *NdefMap);
144
145/*!
146* \brief \copydoc page_ovr Helper function for Topaz. This function updates length field
147* of the NDEF TLV after complete write.
148*/
149static NFCSTATUS phFriNfc_Tpz_H_WrLByte(phFriNfc_NdefMap_t  *NdefMap);
150
151/*!
152* \brief \copydoc page_ovr Helper function for Topaz. This function copies the card data
153*  to the user buffer
154*/
155static NFCSTATUS phFriNfc_Tpz_H_CpDataToUsrBuf( phFriNfc_NdefMap_t  *NdefMap);
156
157/*!
158* \brief \copydoc page_ovr Helper function for Topaz. This function shall process the
159* written data
160*/
161static NFCSTATUS phFriNfc_Tpz_H_ProWrUsrData( phFriNfc_NdefMap_t  *NdefMap);
162
163/*!
164* \brief \copydoc page_ovr Helper function for Topaz. This function checks the block
165* number is correct or not
166*/
167static void phFriNfc_Tpz_H_BlkChk(phFriNfc_NdefMap_t  *NdefMap);
168
169/*!
170* \brief \copydoc page_ovr Helper function for Topaz. This function writes the 0th
171* byte of block 1 has Zero
172*/
173static NFCSTATUS phFriNfc_Tpz_H_WrByte0ValE1(phFriNfc_NdefMap_t   *NdefMap);
174
175/*!
176* \brief \copydoc page_ovr Helper function for Topaz. This function calls the
177* completion routine
178*/
179static void phFriNfc_Tpz_H_Complete(phFriNfc_NdefMap_t  *NdefMap,
180                                    NFCSTATUS           Status);
181
182/*!
183* \brief \copydoc page_ovr Helper function for Topaz check ndef. This function checks
184* the CC byte in check ndef function
185*/
186static NFCSTATUS phFriNfc_Tpz_H_ChkCCinChkNdef(phFriNfc_NdefMap_t  *NdefMap);
187
188/*!
189* \brief \copydoc page_ovr Helper function for Topaz check ndef. This function checks
190* the lock bits and set a card state
191*/
192static void phFriNfc_Tpz_H_ChkLockBits(phFriNfc_NdefMap_t  *NdefMap);
193
194/*!
195* \brief \copydoc page_ovr Helper function for Topaz. This function writes CC bytes or
196* type of the TLV
197*/
198static NFCSTATUS phFriNfc_Tpz_H_WrCCorTLV(phFriNfc_NdefMap_t  *NdefMap);
199
200#ifdef TOPAZ_RF_ERROR_WORKAROUND
201
202/*!
203* \brief \copydoc page_ovr Helper function for Topaz. This function checks the written
204* value after the
205*/
206static
207NFCSTATUS
208phFriNfc_Tpz_H_CheckWrittenData (
209    phFriNfc_NdefMap_t          *psNdefMap,
210    uint8_t                     state_rf_error);
211
212#endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */
213
214/*!
215* \brief \copydoc page_ovr Helper function for Topaz. This function checks the written
216* CC bytes are correct
217*/
218static NFCSTATUS phFriNfc_Tpz_H_ProCCTLV(phFriNfc_NdefMap_t  *NdefMap);
219/*@}*/
220void phFriNfc_TopazMap_H_Reset(phFriNfc_NdefMap_t        *NdefMap)
221{
222    /* Initialising the Topaz structure variable */
223    NdefMap->TopazContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_INVALID_OPE;
224    NdefMap->TopazContainer.CurrentBlock = PH_FRINFC_TOPAZ_VAL1;
225    NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL0;
226    NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_VAL0;
227    (void)memset(NdefMap->TopazContainer.ReadBuffer, PH_FRINFC_TOPAZ_VAL0,
228                sizeof(NdefMap->TopazContainer.ReadBuffer));
229    NdefMap->TopazContainer.ReadWriteCompleteFlag = PH_FRINFC_TOPAZ_FLAG0;
230    NdefMap->TopazContainer.RemainingSize = PH_FRINFC_TOPAZ_VAL0;
231    (void)memset(NdefMap->TopazContainer.UID, PH_FRINFC_TOPAZ_VAL0,
232                sizeof(NdefMap->TopazContainer.UID));
233    NdefMap->TopazContainer.Cur_RW_Index=0;
234    NdefMap->TopazContainer.ByteRWFrmCard =0;
235}
236
237/*!
238* \brief Check whether a particular Remote Device is NDEF compliant.
239*
240* The function checks whether the peer device is NDEF compliant.
241*
242* \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t
243*                    structure describing the component context.
244*
245* \retval  NFCSTATUS_PENDING   The action has been successfully triggered.
246* \retval  Others              An error has occurred.
247*
248*/
249
250NFCSTATUS phFriNfc_TopazMap_ChkNdef( phFriNfc_NdefMap_t     *NdefMap)
251{
252    NFCSTATUS   Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
253        NFCSTATUS_INVALID_PARAMETER);
254    if ( NdefMap != NULL)
255    {
256        /* Update the previous operation */
257        NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_CHECK_OPE;
258        /* Update the CR index to know from which operation completion
259        routine has to be called */
260        NdefMap->TopazContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_CHK_NDEF;
261        NdefMap->TopazContainer.CurrentBlock = PH_FRINFC_TOPAZ_VAL1;
262        NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL0;
263
264        /* Set card state */
265        NdefMap->CardType = PH_FRINFC_NDEFMAP_TOPAZ_CARD;
266
267        /* Change the state to Check Ndef Compliant */
268        NdefMap->State = PH_FRINFC_TOPAZ_STATE_READID;
269        NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_CHECK_OPE;
270
271#ifdef TOPAZ_RAW_SUPPORT
272        NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw;
273        NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READID;
274#else
275#ifdef PH_HAL4_ENABLE
276        NdefMap->Cmd.JewelCmd = phHal_eJewel_RID;
277#else
278        NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRid;
279#endif
280#endif /* #ifdef TOPAZ_RAW_SUPPORT */
281
282        Result = phFriNfc_Tpz_H_RdBytes(NdefMap, NdefMap->TopazContainer.CurrentBlock,
283            NdefMap->TopazContainer.ByteNumber);
284    }
285    return Result;
286}
287
288#ifdef FRINFC_READONLY_NDEF
289
290NFCSTATUS
291phFriNfc_TopazMap_ConvertToReadOnly (
292    phFriNfc_NdefMap_t          *NdefMap)
293{
294    NFCSTATUS               result = NFCSTATUS_SUCCESS;
295
296    result = phFriNfc_Tpz_H_WrAByte (NdefMap, CC_BLOCK_NUMBER,
297                                    CC_RWA_BYTE_NUMBER, CC_READ_ONLY_VALUE);
298
299    if (NFCSTATUS_PENDING == PHNFCSTATUS(result))
300    {
301        NdefMap->State = PH_FRINFC_TOPAZ_STATE_READ_ONLY;
302    }
303    return result;
304}
305
306#endif /* #ifdef FRINFC_READONLY_NDEF */
307
308/*!
309* \brief Initiates Reading of NDEF information from the Remote Device.
310*
311* The function initiates the reading of NDEF information from a Remote Device.
312* It performs a reset of the state and starts the action (state machine).
313* A periodic call of the \ref phFriNfcNdefMap_Process has to be done once the action
314* has been triggered.
315*/
316NFCSTATUS phFriNfc_TopazMap_RdNdef( phFriNfc_NdefMap_t                  *NdefMap,
317                                        uint8_t                         *PacketData,
318                                        uint32_t                        *PacketDataLength,
319                                        uint8_t                         Offset)
320{
321    NFCSTATUS               Result =    NFCSTATUS_SUCCESS;
322
323    /* Copy user buffer to the context */
324    NdefMap->ApduBuffer = PacketData;
325    /* Copy user length to the context */
326    NdefMap->ApduBufferSize = *PacketDataLength;
327    /* Update the user memory size to a context variable */
328    NdefMap->NumOfBytesRead = PacketDataLength;
329    /* Number of bytes read from the card is zero.
330    This variable returns the number of bytes read
331    from the card. */
332    *NdefMap->NumOfBytesRead = PH_FRINFC_TOPAZ_VAL0;
333    /* Index to know the length read */
334    NdefMap->ApduBuffIndex = PH_FRINFC_TOPAZ_VAL0;
335    /* Store the offset in the context */
336    NdefMap->Offset = Offset;
337    /* Update the CR index to know from which operation completion
338    routine has to be called */
339    NdefMap->TopazContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_RD_NDEF;
340
341    if( (Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN) || ( NdefMap->PrevOperation ==
342        PH_FRINFC_NDEFMAP_WRITE_OPE))
343    {
344        /* If previous operation is not read then the read shall
345        start from BEGIN */
346        NdefMap->Offset = PH_FRINFC_NDEFMAP_SEEK_BEGIN;
347        /* Initialise current block and byte number */
348        NdefMap->TopazContainer.CurrentBlock = PH_FRINFC_TOPAZ_VAL1;
349        NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL0;
350        /* State has to be changed */
351        NdefMap->State = PH_FRINFC_TOPAZ_STATE_READALL;
352        NdefMap->TopazContainer.ReadWriteCompleteFlag =
353            PH_FRINFC_TOPAZ_FLAG0;
354        /* Topaz command = READALL */
355#ifdef TOPAZ_RAW_SUPPORT
356        NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw;
357        NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READALL;
358#else
359
360#ifdef PH_HAL4_ENABLE
361        NdefMap->Cmd.JewelCmd = phHal_eJewel_ReadAll;
362#else
363        NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelReadAll;
364#endif
365
366#endif /* #ifdef TOPAZ_RAW_SUPPORT */
367    }
368
369    NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_READ_OPE;
370    /* Offset = Current, but the read has reached the End of Card */
371    if( (Offset == PH_FRINFC_NDEFMAP_SEEK_CUR) &&
372        (NdefMap->TopazContainer.ReadWriteCompleteFlag ==
373        PH_FRINFC_TOPAZ_FLAG1))
374    {
375        Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
376            NFCSTATUS_EOF_NDEF_CONTAINER_REACHED);
377    }
378    else
379    {
380        /* if the offset is begin then call READALL else copy the data
381        from the user buffer */
382        Result = ((Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN)?
383            phFriNfc_Tpz_H_RdBytes(NdefMap,
384            NdefMap->TopazContainer.CurrentBlock,
385            NdefMap->TopazContainer.ByteNumber):
386        phFriNfc_Tpz_H_CpDataToUsrBuf(NdefMap));
387    }
388
389    return Result;
390}
391
392/*!
393* \brief Initiates Writing of NDEF information to the Remote Device.
394*
395* The function initiates the writing of NDEF information to a Remote Device.
396* It performs a reset of the state and starts the action (state machine).
397* A periodic call of the \ref phFriNfcNdefMap_Process has to be done once the action
398* has been triggered.
399*/
400NFCSTATUS phFriNfc_TopazMap_WrNdef( phFriNfc_NdefMap_t     *NdefMap,
401                                   uint8_t                 *PacketData,
402                                   uint32_t                *PacketDataLength,
403                                   uint8_t                 Offset)
404{
405    NFCSTATUS                   Result =    NFCSTATUS_SUCCESS;
406    uint8_t TempByteVal = 0;
407    /* Copy user buffer to the context */
408    NdefMap->ApduBuffer = PacketData;
409    /* Copy user length to the context */
410    NdefMap->ApduBufferSize = *PacketDataLength;
411    /* Index to know the length written */
412    NdefMap->ApduBuffIndex = PH_FRINFC_TOPAZ_VAL0;
413    /* Update the user memory size to a context variable */
414    NdefMap->WrNdefPacketLength = PacketDataLength;
415    /* Number of bytes written to the card is zero.
416    This variable returns the number of bytes written
417    to the card. */
418    *NdefMap->WrNdefPacketLength = PH_FRINFC_TOPAZ_VAL0;
419    /* Update the CR index to know from which operation completion
420    routine has to be called */
421    NdefMap->TopazContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_WR_NDEF;
422    /* Store the offset in the context */
423    NdefMap->Offset = Offset;
424
425
426    if( (Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN) ||
427        (NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_READ_OPE))
428    {
429        NdefMap->Offset = PH_FRINFC_NDEFMAP_SEEK_BEGIN;
430        /* Initialise current block and byte number */
431        NdefMap->TopazContainer.CurrentBlock = PH_FRINFC_TOPAZ_VAL1;
432        NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL0;
433        /* State has to be changed */
434        NdefMap->State = PH_FRINFC_TOPAZ_STATE_READALL;
435        /* Topaz command = READALL */
436
437#ifdef TOPAZ_RAW_SUPPORT
438        NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw;
439        NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READALL;
440#else
441#ifdef PH_HAL4_ENABLE
442        NdefMap->Cmd.JewelCmd = phHal_eJewel_ReadAll;
443#else
444        NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelReadAll;
445#endif
446#endif  /* #ifdef TOPAZ_RAW_SUPPORT */
447        NdefMap->TopazContainer.ReadWriteCompleteFlag =
448            PH_FRINFC_TOPAZ_FLAG0;
449        NdefMap->TopazContainer.RemainingSize = NdefMap->CardMemSize;
450        TempByteVal = NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1];
451    }
452    else
453    {
454        /* State has to be changed */
455        NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE;
456        /* copy the user data to write into the card */
457        TempByteVal = NdefMap->ApduBuffer[NdefMap->ApduBuffIndex];
458    }
459
460    /* Update the previous operation to write operation */
461    NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_WRITE_OPE;
462    if((Offset == PH_FRINFC_NDEFMAP_SEEK_CUR) &&
463        (NdefMap->TopazContainer.ReadWriteCompleteFlag ==
464        PH_FRINFC_TOPAZ_FLAG1))
465    {
466        /* Offset = Current, but the read has reached the End of Card */
467        Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
468            NFCSTATUS_EOF_NDEF_CONTAINER_REACHED);
469    }
470    else
471    {
472        /* Check the block */
473        phFriNfc_Tpz_H_BlkChk(NdefMap);
474        /* if offset is begin then call READALL else start writing */
475        Result = ((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN)?
476            phFriNfc_Tpz_H_RdBytes(NdefMap, NdefMap->TopazContainer.CurrentBlock,
477            NdefMap->TopazContainer.ByteNumber):
478            phFriNfc_Tpz_H_WrAByte(NdefMap, NdefMap->TopazContainer.CurrentBlock,
479            NdefMap->TopazContainer.ByteNumber,TempByteVal));
480    }
481
482    return Result;
483}
484
485
486/*!
487* \brief Completion Routine, Processing function, needed to avoid long blocking.
488* \note The lower (Overlapped HAL) layer must register a pointer to this function as a Completion
489*       Routine in order to be able to notify the component that an I/O has finished and data are
490*       ready to be processed.
491*
492*/
493
494void phFriNfc_TopazMap_Process( void       *Context,
495                               NFCSTATUS   Status)
496{
497
498    phFriNfc_NdefMap_t              *psNdefMap = NULL;
499
500#ifdef TOPAZ_RF_ERROR_WORKAROUND
501
502    static uint8_t                  rf_error_state = 0;
503
504#endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */
505
506    psNdefMap = (phFriNfc_NdefMap_t *)Context;
507
508    if ((Status & PHNFCSTBLOWER) == (NFCSTATUS_SUCCESS & PHNFCSTBLOWER))
509    {
510        switch (psNdefMap->State)
511        {
512#ifdef FRINFC_READONLY_NDEF
513            case PH_FRINFC_TOPAZ_STATE_READ_ONLY:
514            {
515                if((CC_READ_ONLY_VALUE == *psNdefMap->SendRecvBuf)
516                    && (PH_FRINFC_TOPAZ_VAL1 == *psNdefMap->SendRecvLength))
517                {
518                    /* Do nothing */
519                }
520                else
521                {
522                    Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
523                                        NFCSTATUS_INVALID_RECEIVE_LENGTH);
524                }
525                break;
526            }
527#endif /* #ifdef FRINFC_READONLY_NDEF */
528            case PH_FRINFC_TOPAZ_STATE_WRITE:
529            {
530                Status = phFriNfc_Tpz_H_ProWrUsrData (psNdefMap);
531                break;
532            }
533
534            case PH_FRINFC_TOPAZ_STATE_READID:
535            {
536                Status = phFriNfc_Tpz_H_ProReadID (psNdefMap);
537                break;
538            }
539
540            case PH_FRINFC_TOPAZ_STATE_READALL:
541            {
542                Status = phFriNfc_Tpz_H_ProReadAll (psNdefMap);
543                break;
544            }
545
546            case PH_FRINFC_TOPAZ_STATE_WRITE_NMN:
547            {
548                Status = phFriNfc_Tpz_H_ProWrNMN (psNdefMap);
549                break;
550            }
551
552            case PH_FRINFC_TOPAZ_STATE_WRITE_L_TLV:
553            {
554                Status = phFriNfc_Tpz_H_ProWrTLV (psNdefMap);
555                break;
556            }
557
558            case PH_FRINFC_TOPAZ_STATE_WR_CC_OR_TLV:
559            {
560                Status = phFriNfc_Tpz_H_ProCCTLV (psNdefMap);
561                break;
562            }
563
564#ifdef TOPAZ_RF_ERROR_WORKAROUND
565
566            case PH_FRINFC_TOPAZ_STATE_RF_ERROR_READ:
567            {
568                Status = phFriNfc_Tpz_H_CheckWrittenData (psNdefMap,
569                                                        rf_error_state);
570                break;
571            }
572
573#endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */
574
575            default:
576            {
577                Status = PHNFCSTVAL (CID_FRI_NFC_NDEF_MAP,
578                                    NFCSTATUS_INVALID_DEVICE_REQUEST);
579                break;
580            }
581        }
582    }
583    else
584    {
585#ifdef TOPAZ_RF_ERROR_WORKAROUND
586
587        if ((FRINFC_RF_TIMEOUT_89 == PHNFCSTATUS (Status)) ||
588            (FRINFC_RF_TIMEOUT_90 == PHNFCSTATUS (Status)) ||
589            (NFCSTATUS_RF_TIMEOUT == PHNFCSTATUS (Status)))
590        {
591            uint8_t             byte_number = 0;
592            uint8_t             block_number = 0;
593
594            rf_error_state = psNdefMap->State;
595
596#ifdef TOPAZ_RAW_SUPPORT
597
598            *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ;
599
600#else
601
602#ifdef PH_HAL4_ENABLE
603
604            psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read1;
605
606#else
607
608            psNdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead1;
609
610#endif /* #ifdef PH_HAL4_ENABLE */
611
612#endif /* #ifdef TOPAZ_RAW_SUPPORT */
613
614            /* Update the state variable to the new work around state*/
615            psNdefMap->State = PH_FRINFC_TOPAZ_STATE_RF_ERROR_READ;
616
617            /* Switch is used to know, if the error occured during WRITE or READ */
618            switch (rf_error_state)
619            {
620                case PH_FRINFC_TOPAZ_STATE_WRITE_NMN:
621                {
622                    /* Block and byte number is updated for NMN */
623                    byte_number = PH_FRINFC_TOPAZ_VAL0;
624                    block_number = PH_FRINFC_TOPAZ_VAL1;
625                    break;
626                }
627
628                case PH_FRINFC_TOPAZ_STATE_WRITE_L_TLV:
629                {
630                    /* Get the L field of the TLV block */
631                    block_number = (uint8_t)(((psNdefMap->TLVStruct.NdefTLVByte +
632                                        PH_FRINFC_TOPAZ_VAL1) >
633                                        PH_FRINFC_TOPAZ_VAL7)?
634                                        (psNdefMap->TLVStruct.NdefTLVBlock +
635                                        PH_FRINFC_TOPAZ_VAL1):
636                                        psNdefMap->TLVStruct.NdefTLVBlock);
637                    /* Get the L byte */
638                    byte_number = (uint8_t)((psNdefMap->TLVStruct.NdefTLVByte +
639                                        PH_FRINFC_TOPAZ_VAL1) %
640                                        PH_FRINFC_TOPAZ_VAL8);
641                    break;
642                }
643
644                case PH_FRINFC_TOPAZ_STATE_WR_CC_OR_TLV:
645                {
646                    switch (psNdefMap->TopazContainer.InternalState)
647                    {
648                        case PH_FRINFC_TOPAZ_WR_CC_BYTE0:
649                        {
650                            /* Block and byte number is updated for the CC byte 0 */
651                            block_number = (uint8_t)PH_FRINFC_TOPAZ_VAL1;
652                            byte_number = (uint8_t)PH_FRINFC_TOPAZ_VAL0;
653                            break;
654                        }
655
656                        case PH_FRINFC_TOPAZ_WR_CC_BYTE1:
657                        {
658                            /* Block and byte number is updated for the CC byte 1 */
659                            block_number = (uint8_t)PH_FRINFC_TOPAZ_VAL1;
660                            byte_number = (uint8_t)PH_FRINFC_TOPAZ_VAL1;
661                            break;
662                        }
663
664                        case PH_FRINFC_TOPAZ_WR_CC_BYTE2:
665                        {
666                            /* Block and byte number is updated for the CC byte 2 */
667                            block_number = (uint8_t)PH_FRINFC_TOPAZ_VAL1;
668                            byte_number = (uint8_t)PH_FRINFC_TOPAZ_VAL2;
669                            break;
670                        }
671
672                        case PH_FRINFC_TOPAZ_WR_CC_BYTE3:
673                        {
674                            /* Block and byte number is updated for the CC byte 3 */
675                            block_number = (uint8_t)PH_FRINFC_TOPAZ_VAL1;
676                            byte_number = (uint8_t)PH_FRINFC_TOPAZ_VAL3;
677                            break;
678                        }
679
680                        case PH_FRINFC_TOPAZ_WR_T_OF_TLV:
681                        {
682                            /* Block and byte number is updated for the Type field of the TLV */
683                            block_number = psNdefMap->TLVStruct.NdefTLVBlock;
684                            byte_number = (uint8_t)psNdefMap->TLVStruct.NdefTLVByte;
685                            break;
686                        }
687
688                        default:
689                        {
690                            /* Do nothing */
691                            break;
692                        }
693                    } /* switch (psNdefMap->TopazContainer.InternalState) */
694                    break;
695                }
696
697                case PH_FRINFC_TOPAZ_STATE_WRITE:
698                {
699                    /* Block and byte number is updated for the written error data */
700                    block_number = psNdefMap->TopazContainer.CurrentBlock;
701                    byte_number = psNdefMap->TopazContainer.ByteNumber;
702                    break;
703                }
704
705                default:
706                {
707                    /* Error occured is not during WRITE, so update
708                        state variable to the previous state */
709                    psNdefMap->State = rf_error_state;
710                    break;
711                }
712            } /* switch (rf_error_state) */
713
714            /* The below check is added, to know if the error is for
715            the WRITE or READ scenario,
716            If the error is for READ, then state variable is not updated
717            If the error is for WRITE, then state variable is updated with
718            PH_FRINFC_TOPAZ_STATE_RF_ERROR_READ value */
719            if (PH_FRINFC_TOPAZ_STATE_RF_ERROR_READ == psNdefMap->State)
720            {
721                /* Read the data with the updated block and byte number */
722                Status = phFriNfc_Tpz_H_RdBytes (psNdefMap, block_number,
723                                                byte_number);
724            }
725        }
726
727#endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */
728    }
729
730    /* Call Completion Routine, if Status != PENDING */
731    if (NFCSTATUS_PENDING != Status)
732    {
733        phFriNfc_Tpz_H_Complete(psNdefMap, Status);
734    }
735}
736
737
738#ifdef TOPAZ_RF_ERROR_WORKAROUND
739
740static
741NFCSTATUS
742phFriNfc_Tpz_H_CheckWrittenData (
743    phFriNfc_NdefMap_t          *psNdefMap,
744    uint8_t                     state_rf_error)
745{
746    NFCSTATUS   result = NFCSTATUS_SUCCESS;
747
748    switch (state_rf_error)
749    {
750        case PH_FRINFC_TOPAZ_STATE_WRITE:
751        {
752            result = phFriNfc_Tpz_H_ProWrUsrData (psNdefMap);
753            break;
754        }
755
756        case PH_FRINFC_TOPAZ_STATE_WRITE_NMN:
757        {
758            result = phFriNfc_Tpz_H_ProWrNMN (psNdefMap);
759            break;
760        }
761
762        case PH_FRINFC_TOPAZ_STATE_WRITE_L_TLV:
763        {
764            result = phFriNfc_Tpz_H_ProWrTLV (psNdefMap);
765            break;
766        }
767
768        case PH_FRINFC_TOPAZ_STATE_WR_CC_OR_TLV:
769        {
770            result = phFriNfc_Tpz_H_ProCCTLV (psNdefMap);
771            break;
772        }
773
774        default:
775        {
776            break;
777        }
778    }
779
780    return result;
781}
782
783
784#endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */
785
786static NFCSTATUS phFriNfc_Tpz_H_RdBytes(phFriNfc_NdefMap_t *NdefMap,
787                                        uint16_t             BlockNo,
788                                        uint16_t            ByteNo)
789{
790    NFCSTATUS   Result = NFCSTATUS_SUCCESS;
791#ifdef TOPAZ_RAW_SUPPORT
792    uint8_t index = 0;
793#endif /* #ifdef TOPAZ_RAW_SUPPORT */
794
795    /* set the data for additional data exchange*/
796    NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = PH_FRINFC_TOPAZ_VAL0;
797    NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = PH_FRINFC_TOPAZ_VAL0;
798    NdefMap->psDepAdditionalInfo.NAD = PH_FRINFC_TOPAZ_VAL0;
799
800    NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_TopazMap_Process;
801    NdefMap->MapCompletionInfo.Context = NdefMap;
802
803    *NdefMap->SendRecvLength = NdefMap->TempReceiveLength;
804
805    /* Depending on the jewel command, the send length is decided */
806#ifdef TOPAZ_RAW_SUPPORT
807    switch(NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0])
808#else
809    switch(NdefMap->Cmd.JewelCmd)
810#endif /* #ifdef TOPAZ_RAW_SUPPORT */
811    {
812
813#ifdef TOPAZ_RAW_SUPPORT
814    case PH_FRINFC_TOPAZ_CMD_READID:
815#else
816#ifdef PH_HAL4_ENABLE
817    case phHal_eJewel_RID:
818#else
819    case phHal_eJewelCmdListJewelRid:
820#endif
821#endif /* #ifdef TOPAZ_RAW_SUPPORT */
822
823#ifdef TOPAZ_RAW_SUPPORT
824        NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw;
825        /*Copy command to  Send Buffer*/
826        NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0]  = PH_FRINFC_TOPAZ_CMD_READID;
827        index ++;
828
829        /*Copy UID of the tag to  Send Buffer*/
830        (void)memset(&(NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1]),
831        0x00,(0x06));
832        index = index + 0x06;
833
834        /* Update the length of the command buffer*/
835        NdefMap->SendLength = index;
836#else
837        /* For READ ID and READ ALL, send length is 0 */
838        NdefMap->SendLength = PH_FRINFC_TOPAZ_VAL0;
839#endif /* #ifdef TOPAZ_RAW_SUPPORT */
840        break;
841
842#ifdef TOPAZ_RAW_SUPPORT
843    case PH_FRINFC_TOPAZ_CMD_READALL:
844#else
845#ifdef PH_HAL4_ENABLE
846    case phHal_eJewel_ReadAll:
847#else
848    case phHal_eJewelCmdListJewelReadAll:
849#endif
850#endif /* #ifdef TOPAZ_RAW_SUPPORT */
851
852#ifdef TOPAZ_RAW_SUPPORT
853        NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw;
854        /*Copy command to  Send Buffer*/
855        NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0]  = PH_FRINFC_TOPAZ_CMD_READALL;
856        index ++;
857
858        /*Copy 0x00 to Send Buffer*/
859        NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1] = 0x00;
860        index ++;
861        NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2] = 0x00;
862        index ++;
863
864        /*Copy UID of the tag to  Send Buffer*/
865        (void)memcpy(&(NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL3]),
866        &(NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid),
867        TOPAZ_UID_LENGTH_FOR_READ_WRITE);
868
869        index = (uint8_t)(index + TOPAZ_UID_LENGTH_FOR_READ_WRITE);
870
871        /* Update the length of the command buffer*/
872        NdefMap->SendLength = index;
873#else
874       /* For READ ID and READ ALL, send length is 0 */
875        NdefMap->SendLength = PH_FRINFC_TOPAZ_VAL0;
876#endif /* #ifdef TOPAZ_RAW_SUPPORT */
877        break;
878
879#ifdef TOPAZ_RAW_SUPPORT
880    case PH_FRINFC_TOPAZ_CMD_READ:
881#else
882#ifdef PH_HAL4_ENABLE
883    case phHal_eJewel_Read1:
884#else
885    case phHal_eJewelCmdListJewelRead1:
886#endif
887
888#endif /* #ifdef TOPAZ_RAW_SUPPORT */
889
890#ifdef TOPAZ_RAW_SUPPORT
891        NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw;
892        /*Copy command to  Send Buffer*/
893        NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0]  = PH_FRINFC_TOPAZ_CMD_READ;
894        index ++;
895
896        /*Copy Address to  Send Buffer*/
897        /* Calculate send length
898        7 | 6   5   4   3 | 2   1   0 |
899        |    block no   |  byte no  |
900        */
901        NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1] =
902                (uint8_t)((BlockNo << PH_FRINFC_TOPAZ_SHIFT3) +
903                ByteNo);
904        index ++;
905        /*Copy 0x00 to  Send Buffer*/
906        NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2] = 0x00;
907        index ++;
908
909        /*Copy UID of the tag to  Send Buffer*/
910        (void)memcpy(&(NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL3]),
911        &(NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid),
912        TOPAZ_UID_LENGTH_FOR_READ_WRITE);
913        index = (uint8_t)(index + TOPAZ_UID_LENGTH_FOR_READ_WRITE);
914
915        /* Update the length of the command buffer*/
916        NdefMap->SendLength = index;
917#else
918        /* Calculate send length
919        7 | 6   5   4   3 | 2   1   0 |
920        |    block no   |  byte no  |
921        */
922        NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] =
923                (uint8_t)((BlockNo << PH_FRINFC_TOPAZ_SHIFT3) +
924                ByteNo);
925        NdefMap->SendLength = PH_FRINFC_TOPAZ_VAL1;
926#endif /* #ifdef TOPAZ_RAW_SUPPORT */
927
928        break;
929#ifdef TOPAZ_RAW_SUPPORT
930#else
931#ifdef PH_HAL4_ENABLE
932    case phHal_eJewel_Read:
933        NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = 0x00;
934        NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1] = 0x00;
935        NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2] = 104;
936        NdefMap->SendLength = 3;
937    break;
938#endif
939#endif /* #ifdef TOPAZ_RAW_SUPPORT */
940
941    default:
942        Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
943                            NFCSTATUS_INVALID_DEVICE_REQUEST);
944    }
945
946    if(Result == NFCSTATUS_SUCCESS)
947    {
948        /* Call the Overlapped HAL Transceive function */
949        Result = phFriNfc_OvrHal_Transceive(    NdefMap->LowerDevice,
950                                                &NdefMap->MapCompletionInfo,
951                                                NdefMap->psRemoteDevInfo,
952                                                NdefMap->Cmd,
953                                                &NdefMap->psDepAdditionalInfo,
954                                                NdefMap->SendRecvBuf,
955                                                NdefMap->SendLength,
956                                                NdefMap->SendRecvBuf,
957                                                NdefMap->SendRecvLength);
958    }
959    return Result;
960}
961
962static NFCSTATUS phFriNfc_Tpz_H_WrAByte(phFriNfc_NdefMap_t *NdefMap,
963                                        uint16_t             BlockNo,
964                                        uint16_t             ByteNo,
965                                        uint8_t              ByteVal
966                                        )
967{
968    NFCSTATUS   Result = NFCSTATUS_SUCCESS;
969    uint8_t     index = 0;
970
971
972    PHNFC_UNUSED_VARIABLE(ByteVal);
973    /* set the data for additional data exchange*/
974    NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = PH_FRINFC_TOPAZ_VAL0;
975    NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = PH_FRINFC_TOPAZ_VAL0;
976    NdefMap->psDepAdditionalInfo.NAD = PH_FRINFC_TOPAZ_VAL0;
977
978    NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_TopazMap_Process;
979    NdefMap->MapCompletionInfo.Context = NdefMap;
980
981    *NdefMap->SendRecvLength = NdefMap->TempReceiveLength;
982    /* Command used to write 1 byte */
983#ifdef TOPAZ_RAW_SUPPORT
984    NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw;
985#else
986#ifdef PH_HAL4_ENABLE
987    NdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E;
988#else
989    NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelWriteErase1;
990#endif
991#endif /* #ifdef TOPAZ_RAW_SUPPORT */
992
993#ifdef TOPAZ_RAW_SUPPORT
994    /*Copy command to Send Buffer*/
995    NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0]  = PH_FRINFC_TOPAZ_CMD_WRITE_1E;
996    index ++;
997
998    /*Copy Address to  Send Buffer*/
999    /* Calculate send length
1000    7 | 6   5   4   3 | 2   1   0 |
1001    |    block no   |  byte no  |
1002    */
1003    NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1] =
1004            (uint8_t)((BlockNo << PH_FRINFC_TOPAZ_SHIFT3) +
1005            ByteNo);
1006    index ++;
1007    /*Copy Data byte to Send Buffer*/
1008    NdefMap->SendRecvBuf[index] = ByteVal;
1009    index ++;
1010
1011    /*Copy UID of the tag to  Send Buffer*/
1012    (void)memcpy(&(NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL3]),
1013      &(NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid),
1014      TOPAZ_UID_LENGTH_FOR_READ_WRITE);
1015    index = (uint8_t)(index + TOPAZ_UID_LENGTH_FOR_READ_WRITE);
1016
1017    /* Update the length of the command buffer*/
1018    NdefMap->SendLength = index;
1019
1020#else
1021    /* Depending on the jewel command, the send length is decided */
1022    /* Calculate send length
1023    7 | 6   5   4   3 | 2   1   0 |
1024    |    block no   |  byte no  |
1025    */
1026    NdefMap->SendRecvBuf[index] =
1027                        (uint8_t)((BlockNo << PH_FRINFC_TOPAZ_SHIFT3) +
1028                        ByteNo);
1029    index ++;
1030    NdefMap->SendRecvBuf[index] = ByteVal;
1031    index ++;
1032    NdefMap->SendLength = PH_FRINFC_TOPAZ_VAL2;
1033
1034#endif /* #ifdef TOPAZ_RAW_SUPPORT */
1035
1036    /* Call the Overlapped HAL Transceive function */
1037    Result = phFriNfc_OvrHal_Transceive(    NdefMap->LowerDevice,
1038                                            &NdefMap->MapCompletionInfo,
1039                                            NdefMap->psRemoteDevInfo,
1040                                            NdefMap->Cmd,
1041                                            &NdefMap->psDepAdditionalInfo,
1042                                            NdefMap->SendRecvBuf,
1043                                            NdefMap->SendLength,
1044                                            NdefMap->SendRecvBuf,
1045                                            NdefMap->SendRecvLength);
1046
1047    return Result;
1048}
1049
1050static NFCSTATUS phFriNfc_Tpz_H_ProReadID(phFriNfc_NdefMap_t *NdefMap)
1051{
1052    NFCSTATUS   Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1053        NFCSTATUS_INVALID_RECEIVE_LENGTH);
1054
1055    if(((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] &
1056        PH_FRINFC_TOPAZ_HEADROM0_CHK) == PH_FRINFC_TOPAZ_HEADROM0_VAL) &&
1057        (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL6))
1058    {
1059        /* Copy UID to the context, Used when the READ ALL command is used */
1060        (void)memcpy(NdefMap->TopazContainer.UID,
1061            &NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2],
1062            PH_FRINFC_TOPAZ_VAL4);
1063
1064        /* State has to be changed */
1065        NdefMap->State = PH_FRINFC_TOPAZ_STATE_READALL;
1066        /* Topaz command = READALL */
1067#ifdef TOPAZ_RAW_SUPPORT
1068        NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw;
1069        NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READALL;
1070#else
1071#ifdef PH_HAL4_ENABLE
1072        NdefMap->Cmd.JewelCmd = phHal_eJewel_ReadAll;
1073#else
1074        NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelReadAll;
1075#endif
1076#endif /* #ifdef TOPAZ_RAW_SUPPORT */
1077
1078        /* Read all bytes from the card */
1079        Result = phFriNfc_Tpz_H_RdBytes(NdefMap, NdefMap->TopazContainer.CurrentBlock,
1080            NdefMap->TopazContainer.ByteNumber);
1081    }
1082
1083    return Result;
1084}
1085
1086static NFCSTATUS phFriNfc_Tpz_H_ProReadAll(phFriNfc_NdefMap_t *NdefMap)
1087{
1088    NFCSTATUS   Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1089        NFCSTATUS_INVALID_RECEIVE_LENGTH);
1090    int32_t     memcompare = PH_FRINFC_TOPAZ_VAL0;
1091
1092    /* Compare the UID of READ ALL command with the stored UID */
1093#ifdef PH_HAL4_ENABLE
1094    if ((NdefMap->TopazContainer.UID[0] == NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2]) &&
1095        (NdefMap->TopazContainer.UID[1] == NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2 + 1]) &&
1096        (NdefMap->TopazContainer.UID[2] == NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2 + 2]) &&
1097        (NdefMap->TopazContainer.UID[3] == NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2 + 3]))
1098    {
1099        memcompare = PH_FRINFC_TOPAZ_VAL0;
1100    }
1101    else
1102    {
1103        memcompare = PH_FRINFC_TOPAZ_VAL1;
1104    }
1105#else
1106    memcompare = memcmp(NdefMap->TopazContainer.UID,
1107        &NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2],
1108        PH_FRINFC_TOPAZ_VAL4);
1109#endif /* #ifdef PH_HAL4_ENABLE */
1110
1111    if(((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] &
1112        PH_FRINFC_TOPAZ_HEADROM0_CHK) == PH_FRINFC_TOPAZ_HEADROM0_VAL) &&
1113        (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_READALL_RESP) &&
1114        (memcompare == PH_FRINFC_TOPAZ_VAL0))
1115    {
1116        /* Copy 96 bytes from the read/write memory space */
1117        (void)memcpy(NdefMap->TopazContainer.ReadBuffer,
1118            &NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL10],
1119            PH_FRINFC_TOPAZ_TOTAL_RWBYTES);
1120
1121        /* Check the lock bits and set the card state */
1122        phFriNfc_Tpz_H_ChkLockBits(NdefMap);
1123
1124        Result = phFriNfc_Tpz_H_CallNxtOp(NdefMap);
1125    }
1126    return Result;
1127}
1128
1129static NFCSTATUS phFriNfc_Tpz_H_CallNxtOp(phFriNfc_NdefMap_t *NdefMap)
1130{
1131    NFCSTATUS   Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1132        NFCSTATUS_INVALID_RECEIVE_LENGTH);
1133    /* Depending on the operation (check, read or write ndef), process the
1134    read data */
1135    switch(NdefMap->PrevOperation)
1136    {
1137    case PH_FRINFC_NDEFMAP_CHECK_OPE:
1138        /* Check the capabilty container values, according
1139        to the spec */
1140        Result = phFriNfc_Tpz_H_ChkCCinChkNdef(NdefMap);
1141
1142        if (NdefMap->CardState != PH_NDEFMAP_CARD_STATE_INVALID)
1143        {
1144            /* Check the spec version */
1145            Result = phFriNfc_Tpz_H_ChkSpcVer( NdefMap,
1146                NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL1]);
1147            /*  Check the CC header size: Only valid ones are
1148            0x0C for 96 bytes. */
1149            if ((Result == NFCSTATUS_SUCCESS) &&
1150                ( NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL2] <=
1151                PH_FRINFC_TOPAZ_CC_BYTE2_MAX))
1152            {
1153                Result = phFriNfc_Tpz_H_findNDEFTLV(NdefMap);
1154                /* As there is possibility of either having or not having TLV in
1155                Topaz, no need to send the Actual status to the context*/
1156                Result = NFCSTATUS_SUCCESS;
1157            }
1158        }
1159        else
1160        {
1161            Result = (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1162                                NFCSTATUS_INVALID_FORMAT));
1163        }
1164        break;
1165
1166    case PH_FRINFC_NDEFMAP_READ_OPE:
1167        /* Check the capabilty container values, according
1168        to the spec */
1169        Result = phFriNfc_Tpz_H_ChkCCBytes(NdefMap);
1170
1171        /* If success, find the ndef TLV */
1172        Result = ((Result != NFCSTATUS_SUCCESS)?
1173                (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1174                NFCSTATUS_INVALID_FORMAT)):
1175                phFriNfc_Tpz_H_findNDEFTLV(NdefMap));
1176
1177        if(Result == NFCSTATUS_SUCCESS)
1178        {
1179            NdefMap->TopazContainer.ByteNumber += PH_FRINFC_TOPAZ_VAL2;
1180            /* If success, copy the read bytes to the user buffer */
1181            Result = phFriNfc_Tpz_H_CpDataToUsrBuf(NdefMap);
1182        }
1183        break;
1184
1185    case PH_FRINFC_NDEFMAP_WRITE_OPE:
1186    default:
1187        if((NdefMap->CardState == PH_NDEFMAP_CARD_STATE_READ_WRITE) ||
1188            (NdefMap->CardState == PH_NDEFMAP_CARD_STATE_INITIALIZED))
1189        {
1190            /* Check the capabilty container values, according
1191            to the spec */
1192            Result = phFriNfc_Tpz_H_ChkCCBytes(NdefMap);
1193            if(Result == NFCSTATUS_SUCCESS)
1194            {
1195                /* Find the NDEF TLV */
1196                Result = phFriNfc_Tpz_H_findNDEFTLV(NdefMap);
1197
1198                /* Write the TLV */
1199                NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_T_OF_TLV;
1200            }
1201            else
1202            {
1203                NdefMap->TLVStruct.NdefTLVByte = PH_FRINFC_TOPAZ_VAL4;
1204                NdefMap->TLVStruct.NdefTLVBlock = PH_FRINFC_TOPAZ_VAL1;
1205                NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL4;
1206                /* Write the TLV */
1207                NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_CC_BYTE0;
1208            }
1209            /* Write CC bytes */
1210            Result = phFriNfc_Tpz_H_WrCCorTLV(NdefMap);
1211        }
1212        break;
1213    }
1214    return Result;
1215}
1216
1217static NFCSTATUS phFriNfc_Tpz_H_ChkCCBytes(phFriNfc_NdefMap_t *NdefMap)
1218{
1219    NFCSTATUS   Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1220        NFCSTATUS_NO_NDEF_SUPPORT);
1221
1222    if(NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL0] ==
1223        PH_FRINFC_TOPAZ_CC_BYTE0)
1224    {
1225        /* Check the spec version */
1226        Result = phFriNfc_Tpz_H_ChkSpcVer( NdefMap,
1227            NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL1]);
1228        /*  Check the CC header size: Only valid ones are
1229        0x0C for 96 bytes. */
1230        Result = ((( NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL2] >
1231                    PH_FRINFC_TOPAZ_CC_BYTE2_MAX) || (Result !=
1232                    NFCSTATUS_SUCCESS))?
1233                    (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1234                    NFCSTATUS_EOF_NDEF_CONTAINER_REACHED)):
1235                    Result);
1236
1237        /* Get the read/write card memory size */
1238        NdefMap->TopazContainer.RemainingSize =
1239                NdefMap->CardMemSize = ((Result == NFCSTATUS_SUCCESS)?
1240                (PH_FRINFC_TOPAZ_MAX_CARD_SZ - PH_FRINFC_TOPAZ_VAL4):
1241                NdefMap->CardMemSize);
1242
1243        /* if the call is from write ndef then check for read write access */
1244        if(((NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_WRITE_OPE) &&
1245            (NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL3] !=
1246            PH_FRINFC_TOPAZ_CC_BYTE3_RW) && (Result == NFCSTATUS_SUCCESS)))
1247        {
1248            Result = (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1249                                NFCSTATUS_INVALID_FORMAT));
1250        }
1251
1252        /* if the call is from read ndef then check for read only or read write access */
1253        if(((NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_READ_OPE) &&
1254            ((NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL3] !=
1255            PH_FRINFC_TOPAZ_CC_BYTE3_RW) &&
1256            (NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL3] !=
1257            PH_FRINFC_TOPAZ_CC_BYTE3_RO))&& (Result == NFCSTATUS_SUCCESS)))
1258        {
1259            Result = (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1260                                NFCSTATUS_INVALID_FORMAT));
1261        }
1262    }
1263    return Result;
1264}
1265
1266extern NFCSTATUS phFriNfc_Tpz_H_ChkSpcVer( phFriNfc_NdefMap_t  *NdefMap,
1267                                          uint8_t             VersionNo)
1268{
1269    NFCSTATUS Result = NFCSTATUS_SUCCESS;
1270    uint8_t TagVerNo = VersionNo;
1271
1272    /* To remove "warning (VS C4100) : unreferenced formal parameter" */
1273    PHNFC_UNUSED_VARIABLE(NdefMap);
1274
1275    if ( TagVerNo == 0 )
1276    {
1277        /*Return Status Error � Invalid Format�*/
1278        Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,NFCSTATUS_INVALID_FORMAT);
1279    }
1280    else
1281    {
1282        /* calculate the major and minor version number of T3VerNo */
1283        if( (( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM ==
1284            PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo ) )&&
1285            ( PH_NFCFRI_NDEFMAP_NFCDEV_MINOR_VER_NUM >=
1286            PH_NFCFRI_NDEFMAP_GET_MINOR_TAG_VERNO(TagVerNo))) ||
1287            (( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM ==
1288            PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo ) )&&
1289            ( PH_NFCFRI_NDEFMAP_NFCDEV_MINOR_VER_NUM <
1290            PH_NFCFRI_NDEFMAP_GET_MINOR_TAG_VERNO(TagVerNo) )))
1291        {
1292            Result = PHNFCSTVAL(CID_NFC_NONE,NFCSTATUS_SUCCESS);
1293        }
1294        else
1295        {
1296            if (( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM <
1297                PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo) ) ||
1298                ( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM >
1299                PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo)))
1300            {
1301                Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,NFCSTATUS_INVALID_FORMAT);
1302            }
1303        }
1304    }
1305    return Result;
1306}
1307
1308static NFCSTATUS phFriNfc_Tpz_H_findNDEFTLV(phFriNfc_NdefMap_t *NdefMap)
1309{
1310    NFCSTATUS   Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1311        NFCSTATUS_NO_NDEF_SUPPORT);
1312    uint8_t     index = PH_FRINFC_TOPAZ_VAL4;
1313
1314    /* If remaining size is less than 3 then, there cant be any
1315    TLV present in the card */
1316    while((index < PH_FRINFC_TOPAZ_TOTAL_RWBYTES) &&
1317        (NdefMap->TopazContainer.RemainingSize >= PH_FRINFC_TOPAZ_VAL3))
1318    {
1319        switch(NdefMap->TopazContainer.ReadBuffer[index])
1320        {
1321        case PH_FRINFC_TOPAZ_NDEF_T:
1322            /* To get the length field of the TLV */
1323            index++;
1324            /* Type and length are not data bytes, so to know the exact
1325            remaining size in the card, the below operation is done */
1326            NdefMap->TopazContainer.RemainingSize -= PH_FRINFC_TOPAZ_VAL2;
1327            /* Set the card state depending on the L value */
1328            Result = phFriNfc_MapTool_SetCardState(NdefMap,
1329                (uint32_t)NdefMap->TopazContainer.ReadBuffer[index]);
1330            /* Check the TLV is correct */
1331            if((NdefMap->TopazContainer.ReadBuffer[index] >
1332                NdefMap->TopazContainer.RemainingSize) ||
1333                ((NdefMap->TopazContainer.ReadBuffer[index] ==
1334                PH_FRINFC_TOPAZ_VAL0) && (NdefMap->PrevOperation ==
1335                PH_FRINFC_NDEFMAP_READ_OPE)) || (Result != NFCSTATUS_SUCCESS))
1336            {
1337                /* L field value cant be greater than the remaining size, so error */
1338                Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1339                                    NFCSTATUS_NO_NDEF_SUPPORT);
1340                /* To break out of the loop */
1341                index = PH_FRINFC_TOPAZ_TOTAL_RWBYTES;
1342            }
1343            else
1344            {
1345                /* So remaining size also changes, according to the position of NDEF TLV  */
1346                NdefMap->TLVStruct.BytesRemainLinTLV =
1347                    NdefMap->TopazContainer.ReadBuffer[index];
1348
1349                /* Get the byte number */
1350                NdefMap->TLVStruct.NdefTLVByte = (uint16_t)((index - PH_FRINFC_TOPAZ_VAL1) %
1351                                                    PH_FRINFC_TOPAZ_VAL8);
1352                /* Get the block number */
1353                NdefMap->TLVStruct.NdefTLVBlock = (uint8_t)(((index - PH_FRINFC_TOPAZ_VAL1) /
1354                                                    PH_FRINFC_TOPAZ_VAL8) +
1355                                                    PH_FRINFC_TOPAZ_VAL1);
1356                /* TLV found flag is set */
1357                NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_TOPAZ_FLAG1;
1358                /* To know the position of V field in the TLV */
1359                NdefMap->TopazContainer.ByteNumber = (uint8_t)(((NdefMap->TLVStruct.NdefTLVBlock - 1) * 8) +
1360                                                    NdefMap->TLVStruct.NdefTLVByte);
1361                /* To break out of the loop */
1362                index = PH_FRINFC_TOPAZ_TOTAL_RWBYTES;
1363                Result = NFCSTATUS_SUCCESS;
1364            }
1365            break;
1366
1367        case PH_FRINFC_TOPAZ_NULL_T:
1368            /* Null TLV, Skip the TLV */
1369            NdefMap->TopazContainer.RemainingSize--;
1370            index++;
1371            break;
1372
1373        case PH_FRINFC_TOPAZ_TERM_T:
1374            /* No more TLV present in the card, so error */
1375            index = PH_FRINFC_TOPAZ_TOTAL_RWBYTES;
1376            Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1377                                NFCSTATUS_NO_NDEF_SUPPORT);
1378            break;
1379
1380        default:
1381            /* Go till the length field of the TLV */
1382            index++;
1383            /* Type and length is not the data, so to know the exact
1384            remaining size in the card, the below operation is done */
1385            NdefMap->TopazContainer.RemainingSize -= PH_FRINFC_TOPAZ_VAL2;
1386            if(NdefMap->TopazContainer.ReadBuffer[index] >
1387                NdefMap->TopazContainer.RemainingSize)
1388            {
1389                /* L field value cant be greater than the remaining size, so error */
1390                index = PH_FRINFC_TOPAZ_TOTAL_RWBYTES;
1391                Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1392                                    NFCSTATUS_NO_NDEF_SUPPORT);
1393            }
1394            else
1395            {
1396                /* Remaining size of the free space available in the card changes,
1397                according to the position of NDEF TLV */
1398                NdefMap->TopazContainer.RemainingSize =
1399                    NdefMap->TopazContainer.RemainingSize -
1400                    NdefMap->TopazContainer.ReadBuffer[index];
1401
1402                /* Get the position of the next TLV */
1403                index = (uint8_t)(index +
1404                    (NdefMap->TopazContainer.ReadBuffer[index] +
1405                     PH_FRINFC_TOPAZ_VAL1));
1406            }
1407            break;
1408        }
1409    }
1410
1411    /* If no Ndef TLV found and operation done is read */
1412    if((NdefMap->TLVStruct.NdefTLVFoundFlag == PH_FRINFC_TOPAZ_FLAG0) &&
1413        (NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_READ_OPE))
1414    {
1415        Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1416                            NFCSTATUS_EOF_NDEF_CONTAINER_REACHED);
1417    }
1418    if((NdefMap->TLVStruct.NdefTLVFoundFlag == PH_FRINFC_TOPAZ_FLAG0) &&
1419        ((NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_WRITE_OPE) ||
1420        (NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_CHECK_OPE)))
1421    {
1422        NdefMap->TLVStruct.NdefTLVByte = PH_FRINFC_TOPAZ_VAL4;
1423        NdefMap->TLVStruct.NdefTLVBlock = PH_FRINFC_TOPAZ_VAL1;
1424        NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL4;
1425        NdefMap->TopazContainer.RemainingSize = PH_FRINFC_TOPAZ_TOTAL_RWBYTES1;
1426    }
1427    return Result;
1428}
1429
1430static NFCSTATUS phFriNfc_Tpz_H_CpDataToUsrBuf(phFriNfc_NdefMap_t  *NdefMap)
1431{
1432    NFCSTATUS   Result = NFCSTATUS_SUCCESS;
1433
1434    /* Check the the TLV size and the user size */
1435    if(NdefMap->ApduBufferSize >=
1436        NdefMap->TLVStruct.BytesRemainLinTLV)
1437    {
1438        /* Copy the read bytes to user buffer till the value (V)
1439        of TLV ends */
1440        (void)memcpy(NdefMap->ApduBuffer,
1441            &(NdefMap->TopazContainer.ReadBuffer[
1442                NdefMap->TopazContainer.ByteNumber]),
1443                    NdefMap->TLVStruct.BytesRemainLinTLV);
1444
1445                /* Update the number of read bytes to the user */
1446                *(NdefMap->NumOfBytesRead) =
1447                    NdefMap->TLVStruct.BytesRemainLinTLV;
1448                /* There is no byte to read */
1449                NdefMap->TopazContainer.ByteNumber =
1450                                                    PH_FRINFC_TOPAZ_VAL0;
1451                /* No further read is possible */
1452                NdefMap->TopazContainer.ReadWriteCompleteFlag =
1453                                                    PH_FRINFC_TOPAZ_FLAG1;
1454                /* Remaining size in the card can be greater than length field in
1455                the TLV */
1456                NdefMap->TopazContainer.RemainingSize =
1457                    NdefMap->TopazContainer.RemainingSize -
1458                                        NdefMap->TLVStruct.BytesRemainLinTLV;
1459                /* TLV has been completely read, no more bytes to read */
1460                NdefMap->TLVStruct.BytesRemainLinTLV =
1461                                                    PH_FRINFC_TOPAZ_VAL0;
1462    }
1463    else
1464    {
1465        /* Copy read bytes till the user buffer size */
1466        (void)memcpy(NdefMap->ApduBuffer,
1467                    &(NdefMap->TopazContainer.ReadBuffer[
1468                    NdefMap->TopazContainer.ByteNumber]),
1469                    NdefMap->ApduBufferSize);
1470
1471        /* Update the number of read bytes to the user */
1472        *(NdefMap->NumOfBytesRead) =
1473            NdefMap->ApduBufferSize;
1474        /* Get the next byte number to read */
1475        NdefMap->TopazContainer.ByteNumber =
1476            (uint8_t)(NdefMap->TopazContainer.ByteNumber +
1477                      NdefMap->ApduBufferSize);
1478        /* Free space left in the card */
1479        NdefMap->TopazContainer.RemainingSize
1480            = NdefMap->TopazContainer.RemainingSize
1481                  - (uint16_t)NdefMap->ApduBufferSize;
1482        /* Bytes left in the TLV */
1483        NdefMap->TLVStruct.BytesRemainLinTLV =
1484            NdefMap->TLVStruct.BytesRemainLinTLV -
1485                   (uint16_t)NdefMap->ApduBufferSize;
1486    }
1487    return Result;
1488}
1489
1490static NFCSTATUS phFriNfc_Tpz_H_ProWrNMN(phFriNfc_NdefMap_t *NdefMap)
1491{
1492    NFCSTATUS   Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1493        NFCSTATUS_INVALID_RECEIVE_LENGTH);
1494    uint8_t     BlockNo = PH_FRINFC_TOPAZ_VAL0,
1495        ByteNo = PH_FRINFC_TOPAZ_VAL0;
1496
1497    if((NdefMap->TopazContainer.InternalState ==
1498        PH_FRINFC_TOPAZ_WR_NMN_0) &&
1499        (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] ==
1500        PH_FRINFC_TOPAZ_VAL0) &&
1501        (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1))
1502    {
1503        NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE_L_TLV;
1504        /* Get the L field of the TLV block */
1505        BlockNo = (uint8_t)(((NdefMap->TLVStruct.NdefTLVByte + PH_FRINFC_TOPAZ_VAL1) >
1506                            PH_FRINFC_TOPAZ_VAL7)?
1507                            (NdefMap->TLVStruct.NdefTLVBlock + PH_FRINFC_TOPAZ_VAL1):
1508                            NdefMap->TLVStruct.NdefTLVBlock);
1509        /* Get the L byte */
1510        ByteNo = (uint8_t)((NdefMap->TLVStruct.NdefTLVByte + PH_FRINFC_TOPAZ_VAL1) %
1511                                PH_FRINFC_TOPAZ_VAL8);
1512
1513
1514        /* Here the NMN is written 0, so internal state is used */
1515        NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_L_TLV_0;
1516        /* Write the length value = 0x00 , Write L field of TLV  = 0  inside this*/
1517        Result = phFriNfc_Tpz_H_WrAByte( NdefMap, BlockNo, ByteNo,
1518                                        PH_FRINFC_TOPAZ_VAL0);
1519    }
1520    else
1521    {
1522        if((NdefMap->TopazContainer.InternalState ==
1523            PH_FRINFC_TOPAZ_WR_NMN_E1) &&
1524            (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] ==
1525            PH_FRINFC_TOPAZ_CC_BYTE0) &&
1526            (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1))
1527        {
1528            /* Card state is initialised or invalid */
1529            NdefMap->CardState = (uint8_t)((NdefMap->CardState ==
1530                                    PH_NDEFMAP_CARD_STATE_INITIALIZED)?
1531                                    PH_NDEFMAP_CARD_STATE_READ_WRITE:
1532                                    NdefMap->CardState);
1533            /* update the length to the user */
1534            *NdefMap->WrNdefPacketLength = NdefMap->ApduBuffIndex;
1535            Result = NFCSTATUS_SUCCESS;
1536        }
1537    }
1538    return Result;
1539}
1540
1541static NFCSTATUS phFriNfc_Tpz_H_ProWrTLV(phFriNfc_NdefMap_t *NdefMap)
1542{
1543    NFCSTATUS   Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1544        NFCSTATUS_INVALID_RECEIVE_LENGTH);
1545    if((NdefMap->TopazContainer.InternalState ==
1546        PH_FRINFC_TOPAZ_WR_L_TLV_0) &&
1547        (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] ==
1548        PH_FRINFC_TOPAZ_VAL0) &&
1549        (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1))
1550    {
1551        /* state is writing user data to the card */
1552        NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE;
1553
1554        NdefMap->TopazContainer.ByteNumber++;
1555        /* Check the byte number */
1556        phFriNfc_Tpz_H_BlkChk(NdefMap);
1557
1558        /* Write data to the specified location */
1559        /* Write the data to the card from the user buffer */
1560        Result = phFriNfc_Tpz_H_WrAByte( NdefMap,
1561                                        NdefMap->TopazContainer.CurrentBlock,
1562                                        NdefMap->TopazContainer.ByteNumber,
1563                                        NdefMap->ApduBuffer[NdefMap->ApduBuffIndex]
1564                                        );
1565    }
1566    else
1567    {
1568        if((NdefMap->TopazContainer.InternalState ==
1569            PH_FRINFC_TOPAZ_WR_L_TLV) &&
1570            (((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN) &&
1571            (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] ==
1572            NdefMap->ApduBuffIndex)) ||
1573            ((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_CUR) &&
1574            (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] ==
1575            (NdefMap->ApduBuffIndex + NdefMap->TLVStruct.BytesRemainLinTLV)))) &&
1576            (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1))
1577        {
1578            /* Update the L value in the context */
1579            NdefMap->TLVStruct.BytesRemainLinTLV =
1580                ((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN)?
1581                NdefMap->ApduBuffIndex:
1582            (NdefMap->TLVStruct.BytesRemainLinTLV + NdefMap->ApduBuffIndex));
1583
1584            /* Write 0xE1 in block number = 1 and byte number = 0 */
1585            Result = phFriNfc_Tpz_H_WrByte0ValE1(NdefMap);
1586        }
1587    }
1588    return Result;
1589}
1590
1591static NFCSTATUS phFriNfc_Tpz_H_ProWrUsrData(phFriNfc_NdefMap_t *NdefMap)
1592{
1593    NFCSTATUS   Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1594        NFCSTATUS_INVALID_RECEIVE_LENGTH);
1595    /* send buffer should be equal to receive buffer */
1596    if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] ==
1597        NdefMap->ApduBuffer[NdefMap->ApduBuffIndex]) &&
1598        (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1))
1599    {
1600        /* Increment the index */
1601        NdefMap->ApduBuffIndex += PH_FRINFC_TOPAZ_VAL1;
1602
1603        /* Remaining space left in the card is less by one */
1604        NdefMap->TopazContainer.RemainingSize -= PH_FRINFC_TOPAZ_VAL1;
1605
1606        /* Increment the byte number */
1607        NdefMap->TopazContainer.ByteNumber++;
1608
1609        /* Check the block number */
1610        phFriNfc_Tpz_H_BlkChk(NdefMap);
1611
1612        /* check for the user space or the card size */
1613        if((NdefMap->ApduBufferSize == NdefMap->ApduBuffIndex) ||
1614            (NdefMap->TopazContainer.RemainingSize == PH_FRINFC_TOPAZ_VAL0))
1615        {
1616            /* Set write complete, if the end of card is reached */
1617            NdefMap->TopazContainer.ReadWriteCompleteFlag = (uint8_t)
1618                ((NdefMap->TopazContainer.RemainingSize == PH_FRINFC_TOPAZ_VAL0)?
1619                PH_FRINFC_TOPAZ_FLAG1:PH_FRINFC_TOPAZ_FLAG0);
1620
1621            Result = phFriNfc_Tpz_H_WrLByte(NdefMap);
1622        }
1623        else
1624        {
1625            /* State is continued to be in write */
1626            NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE;
1627
1628            /* Write the byte to the specified location , and Byte to write */
1629            Result = phFriNfc_Tpz_H_WrAByte(NdefMap, NdefMap->TopazContainer.CurrentBlock,
1630                                            NdefMap->TopazContainer.ByteNumber,
1631                                            NdefMap->ApduBuffer[NdefMap->ApduBuffIndex]
1632                                            );
1633        }
1634    }
1635    return Result;
1636}
1637
1638static NFCSTATUS phFriNfc_Tpz_H_WrLByte(phFriNfc_NdefMap_t  *NdefMap)
1639{
1640    NFCSTATUS   Result = NFCSTATUS_SUCCESS;
1641    uint8_t     BlockNo = PH_FRINFC_TOPAZ_VAL0,
1642        ByteNo = PH_FRINFC_TOPAZ_VAL0;
1643    uint8_t TempByteVal = 0;
1644    BlockNo = (uint8_t)(((NdefMap->TLVStruct.NdefTLVByte +
1645                            PH_FRINFC_TOPAZ_VAL1) >
1646                            PH_FRINFC_TOPAZ_VAL7)?
1647                            (NdefMap->TLVStruct.NdefTLVBlock +
1648                            PH_FRINFC_TOPAZ_VAL1):
1649    NdefMap->TLVStruct.NdefTLVBlock);
1650
1651    ByteNo = (uint8_t)((NdefMap->TLVStruct.NdefTLVByte +
1652                        PH_FRINFC_TOPAZ_VAL1) % PH_FRINFC_TOPAZ_VAL8);
1653    /* Update L field */
1654    NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE_L_TLV;
1655    /* Internal state for write */
1656    NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_L_TLV;
1657    /* Update the length field depending on the offset */
1658    TempByteVal = (uint8_t)
1659                    ((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN)?
1660                    NdefMap->ApduBuffIndex:
1661                    (NdefMap->ApduBuffIndex +
1662                    NdefMap->TLVStruct.BytesRemainLinTLV));
1663    /* Write the L field */
1664    Result = phFriNfc_Tpz_H_WrAByte(NdefMap, BlockNo, ByteNo,TempByteVal);
1665    return Result;
1666}
1667
1668static NFCSTATUS phFriNfc_Tpz_H_WrByte0ValE1(phFriNfc_NdefMap_t   *NdefMap)
1669{
1670    NFCSTATUS   Result = NFCSTATUS_SUCCESS;
1671
1672    /* Update L field */
1673    NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE_NMN;
1674    /* Internal state for writing 0xE1 */
1675    NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_NMN_E1;
1676    /* Update the length field depending on the offset */
1677    /* Write the L field */
1678    Result = phFriNfc_Tpz_H_WrAByte(NdefMap, PH_FRINFC_TOPAZ_VAL1,
1679                                    PH_FRINFC_TOPAZ_VAL0,PH_FRINFC_TOPAZ_CC_BYTE0);
1680    return Result;
1681}
1682
1683static void phFriNfc_Tpz_H_Complete(phFriNfc_NdefMap_t  *NdefMap,
1684                                    NFCSTATUS           Status)
1685{
1686    /* set the state back to the Reset_Init state*/
1687    NdefMap->State =  PH_FRINFC_NDEFMAP_STATE_RESET_INIT;
1688
1689    /* set the completion routine*/
1690    NdefMap->CompletionRoutine[NdefMap->TopazContainer.CRIndex].
1691        CompletionRoutine(NdefMap->CompletionRoutine->Context, Status);
1692}
1693
1694static void phFriNfc_Tpz_H_BlkChk(phFriNfc_NdefMap_t  *NdefMap)
1695{
1696    NdefMap->TopazContainer.CurrentBlock =
1697                    (uint8_t)((NdefMap->TopazContainer.ByteNumber >
1698                    PH_FRINFC_TOPAZ_VAL7)?
1699                    (NdefMap->TopazContainer.CurrentBlock +
1700                    PH_FRINFC_TOPAZ_VAL1):
1701                    NdefMap->TopazContainer.CurrentBlock);
1702
1703    NdefMap->TopazContainer.ByteNumber = (uint8_t)(NdefMap->TopazContainer.ByteNumber %
1704                                        PH_FRINFC_TOPAZ_VAL8);
1705}
1706
1707static NFCSTATUS phFriNfc_Tpz_H_ChkCCinChkNdef(phFriNfc_NdefMap_t  *NdefMap)
1708{
1709    NFCSTATUS   Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1710                                    NFCSTATUS_NO_NDEF_SUPPORT);
1711
1712    if(NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL0] ==
1713        PH_FRINFC_TOPAZ_CC_BYTE0)
1714    {
1715        /* Check the most significant nibble of byte 3 (RWA) = 0 */
1716        Result = (((NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL3] &
1717                    PH_FRINFC_TOPAZ_BYTE3_MSB)== PH_FRINFC_TOPAZ_VAL0)?
1718                    NFCSTATUS_SUCCESS:
1719                    Result);
1720
1721        /* Card size is initialised */
1722        NdefMap->CardMemSize = NdefMap->TopazContainer.RemainingSize =
1723                            ((Result == NFCSTATUS_SUCCESS)?
1724                            (PH_FRINFC_TOPAZ_MAX_CARD_SZ - PH_FRINFC_TOPAZ_VAL4):
1725                            NdefMap->CardMemSize);
1726    }
1727
1728    if (NdefMap->CardState != PH_NDEFMAP_CARD_STATE_READ_ONLY)
1729    {
1730        NdefMap->CardState = (uint8_t)((Result == NFCSTATUS_SUCCESS)?
1731                            PH_NDEFMAP_CARD_STATE_INITIALIZED:
1732                            PH_NDEFMAP_CARD_STATE_INVALID);
1733    }
1734
1735    return Result;
1736}
1737
1738static void phFriNfc_Tpz_H_ChkLockBits(phFriNfc_NdefMap_t  *NdefMap)
1739{
1740    /* Set the card state */
1741    NdefMap->CardState =  (uint8_t)
1742        (((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_LOCKBIT_BYTENO_0] ==
1743        PH_FRINFC_TOPAZ_LOCKBIT_BYTE114) &&
1744        ((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_LOCKBIT_BYTENO_1] ==
1745        PH_FRINFC_TOPAZ_LOCKBIT_BYTE115_1) ||
1746        (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_LOCKBIT_BYTENO_1] ==
1747        PH_FRINFC_TOPAZ_LOCKBIT_BYTE115_2)))?
1748        PH_NDEFMAP_CARD_STATE_READ_WRITE:
1749        PH_NDEFMAP_CARD_STATE_READ_ONLY);
1750
1751    /* Set the card state from CC bytes */
1752    if (NdefMap->CardState == PH_NDEFMAP_CARD_STATE_READ_WRITE)
1753    {
1754        if (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_CC_BYTENO_3] == PH_FRINFC_TOPAZ_CC_READWRITE)
1755        {
1756            NdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_WRITE;
1757        }
1758        else if (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_CC_BYTENO_3] == PH_FRINFC_TOPAZ_CC_READONLY)
1759        {
1760            NdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_ONLY;
1761        }
1762        else
1763        {
1764            NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID;
1765        }
1766    }
1767}
1768
1769static NFCSTATUS phFriNfc_Tpz_H_WrCCorTLV(phFriNfc_NdefMap_t  *NdefMap)
1770{
1771    NFCSTATUS   Result = NFCSTATUS_SUCCESS;
1772    uint8_t     ByteNo = PH_FRINFC_TOPAZ_VAL0,
1773        BlockNo = PH_FRINFC_TOPAZ_VAL0;
1774    uint8_t TempByteVal = 0;
1775    switch(NdefMap->TopazContainer.InternalState)
1776    {
1777    case PH_FRINFC_TOPAZ_WR_CC_BYTE0:
1778        /* To write the CC bytes */
1779        TempByteVal = PH_FRINFC_TOPAZ_CC_BYTE0;
1780        ByteNo = (uint8_t)PH_FRINFC_TOPAZ_VAL0;
1781        BlockNo = PH_FRINFC_TOPAZ_VAL1;
1782        break;
1783
1784    case PH_FRINFC_TOPAZ_WR_CC_BYTE1:
1785        /* To write the CC bytes */
1786        TempByteVal = PH_FRINFC_TOPAZ_CC_BYTE1;
1787        ByteNo = (uint8_t)PH_FRINFC_TOPAZ_VAL1;
1788        BlockNo = PH_FRINFC_TOPAZ_VAL1;
1789        break;
1790
1791    case PH_FRINFC_TOPAZ_WR_CC_BYTE2:
1792        /* To write the CC bytes */
1793        TempByteVal = PH_FRINFC_TOPAZ_CC_BYTE2_MAX;
1794        ByteNo = (uint8_t)PH_FRINFC_TOPAZ_VAL2;
1795        BlockNo = PH_FRINFC_TOPAZ_VAL1;
1796        break;
1797
1798    case PH_FRINFC_TOPAZ_WR_CC_BYTE3:
1799        /* To write the CC bytes */
1800        TempByteVal = PH_FRINFC_TOPAZ_CC_BYTE3_RW;
1801        ByteNo = (uint8_t)PH_FRINFC_TOPAZ_VAL3;
1802        BlockNo = PH_FRINFC_TOPAZ_VAL1;
1803        break;
1804
1805    case PH_FRINFC_TOPAZ_WR_T_OF_TLV:
1806    default:
1807        /* To write the NDEF TLV (if not present) */
1808        TempByteVal = PH_FRINFC_TOPAZ_NDEF_T;
1809        ByteNo = (uint8_t)NdefMap->TLVStruct.NdefTLVByte;
1810        BlockNo = NdefMap->TLVStruct.NdefTLVBlock;
1811        break;
1812    }
1813    NdefMap->State = PH_FRINFC_TOPAZ_STATE_WR_CC_OR_TLV;
1814    Result = phFriNfc_Tpz_H_WrAByte( NdefMap, BlockNo, ByteNo,TempByteVal);
1815    return Result;
1816}
1817
1818static NFCSTATUS phFriNfc_Tpz_H_ProCCTLV(phFriNfc_NdefMap_t  *NdefMap)
1819{
1820    NFCSTATUS   Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1821        NFCSTATUS_INVALID_RECEIVE_LENGTH);
1822    switch(NdefMap->TopazContainer.InternalState)
1823    {
1824    case PH_FRINFC_TOPAZ_WR_CC_BYTE0:
1825        /* Process the CC byte */
1826        /* Check the response */
1827        if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] ==
1828            PH_FRINFC_TOPAZ_CC_BYTE0) &&
1829            (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1))
1830        {
1831            NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_CC_BYTE1;
1832            Result = phFriNfc_Tpz_H_WrCCorTLV(NdefMap);
1833        }
1834        break;
1835
1836    case PH_FRINFC_TOPAZ_WR_CC_BYTE1:
1837        /* Process the CC byte */
1838        /* Check the response */
1839        if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] ==
1840            PH_FRINFC_TOPAZ_CC_BYTE1) &&
1841            (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1))
1842        {
1843            NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_CC_BYTE2;
1844            Result = phFriNfc_Tpz_H_WrCCorTLV(NdefMap);
1845        }
1846        break;
1847
1848    case PH_FRINFC_TOPAZ_WR_CC_BYTE2:
1849        /* Process the CC byte */
1850        /* Check the response */
1851        if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] ==
1852            PH_FRINFC_TOPAZ_CC_BYTE2_MAX) &&
1853            (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1))
1854        {
1855            NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_CC_BYTE3;
1856            Result = phFriNfc_Tpz_H_WrCCorTLV(NdefMap);
1857        }
1858        break;
1859
1860    case PH_FRINFC_TOPAZ_WR_CC_BYTE3:
1861        /* Process the CC byte */
1862        /* Check the response */
1863        if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] ==
1864            PH_FRINFC_TOPAZ_CC_BYTE3_RW) &&
1865            (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1))
1866        {
1867            NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_T_OF_TLV;
1868            Result = phFriNfc_Tpz_H_WrCCorTLV(NdefMap);
1869        }
1870        break;
1871
1872    case PH_FRINFC_TOPAZ_WR_T_OF_TLV:
1873    default:
1874        /* Check the response */
1875        if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] ==
1876            PH_FRINFC_TOPAZ_NDEF_T) &&
1877            (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1))
1878        {
1879            /* Increment the Byte Number */
1880            NdefMap->TopazContainer.ByteNumber++;
1881            /* Check the block and byte number */
1882            phFriNfc_Tpz_H_BlkChk(NdefMap);
1883            /* Process the T of NDEF TLV */
1884            NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE_NMN;
1885
1886            /* Here the NMN is written 0, so internal state is used */
1887            NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_NMN_0;
1888
1889            /*Inside this call Write NMN (block number 1 and byte number 0) = 0 */
1890            Result = phFriNfc_Tpz_H_WrAByte( NdefMap, PH_FRINFC_TOPAZ_VAL1,
1891                PH_FRINFC_TOPAZ_VAL0,PH_FRINFC_TOPAZ_VAL0);
1892        }
1893        break;
1894    }
1895    return Result;
1896}
1897
1898#ifdef UNIT_TEST
1899#include <phUnitTestNfc_Topaz_static.c>
1900#endif
1901
1902#endif  /* PH_FRINFC_MAP_TOPAZ_DISABLED */
1903