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