static NFCSTATUS
phFriNfc_TopazFormat_WriteByte(phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt,
                               uint8_t BlockNo,
                               uint8_t ByteNo,
                               uint8_t ByteToWrite)
{
    NFCSTATUS wStatus = NFCSTATUS_SUCCESS;
    uint8_t writeCmd[7] = { 0 };

    PH_LOG_NDEF_FUNC_ENTRY();

    assert(NdefSmtCrdFmt != NULL);

    writeCmd[0] = PH_FRINFC_TOPAZ_CMD_WRITE_1E;

    /* Block and byte numbers need to be in the following format:
    7 | 6   5   4   3 | 2   1   0 |
    0 |     Block     |   Byte    |
    */
    writeCmd[1] = ((BlockNo & 0x0F) << 3) | (ByteNo & 0x07);

    writeCmd[2] = ByteToWrite;

    /* Copy the UID to the end of command buffer */
    phOsalNfc_MemCopy(&writeCmd[3],
                      NdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid,
                      TOPAZ_UID_LENGTH);

    wStatus = phFriNfc_TopazFormat_Transceive(NdefSmtCrdFmt,
                                              writeCmd,
                                              sizeof(writeCmd));

    PH_LOG_NDEF_FUNC_EXIT();
    return wStatus;
}
NFCSTATUS
phFriNfc_TopazFormat_Format(phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt)
{
    NFCSTATUS wStatus = NFCSTATUS_SUCCESS;

    PH_LOG_NDEF_FUNC_ENTRY();

    if (NdefSmtCrdFmt == NULL)
    {
        wStatus = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, NFCSTATUS_INVALID_PARAMETER);
    }
    else
    {
        NdefSmtCrdFmt->State = 0;

        phOsalNfc_SetMemory(&NdefSmtCrdFmt->AddInfo.Type1Info,
                            0,
                            sizeof(NdefSmtCrdFmt->AddInfo.Type1Info));

        NdefSmtCrdFmt->AddInfo.Type1Info.CurrentBlock = 0x01;
        NdefSmtCrdFmt->AddInfo.Type1Info.CurrentByte = 0;

        wStatus = phFriNfc_TopazFormat_WriteByte(NdefSmtCrdFmt,
                                                 NdefSmtCrdFmt->AddInfo.Type1Info.CurrentBlock,
                                                 NdefSmtCrdFmt->AddInfo.Type1Info.CurrentByte,
                                                 c_staticTopazFormat[NdefSmtCrdFmt->AddInfo.Type1Info.CurrentByte]);
    }

    PH_LOG_NDEF_FUNC_EXIT();
    return wStatus;
}
static NFCSTATUS
phFriNfc_TopazDynamicFormat_ProcessWritingTermTlvBytes(phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt)
{
    static const uint8_t c_expectedResponse[] =
    {
        PH_FRINFC_TOPAZ_TLV_TERM_T, /* Terminator TLV */
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Rest of data bytes are zeros */
    };

    NFCSTATUS wStatus = NFCSTATUS_SUCCESS;

    PH_LOG_NDEF_FUNC_ENTRY();

    assert(NdefSmtCrdFmt != NULL);

    if ((*NdefSmtCrdFmt->SendRecvLength != sizeof(c_expectedResponse)) ||
        (0 != phOsalNfc_MemCompare(NdefSmtCrdFmt->SendRecvBuf,
                                   (void*)c_expectedResponse,
                                   sizeof(c_expectedResponse))))
    {
        PH_LOG_NDEF_WARN_STR("Unexpected response received. Formatting failed");
        wStatus = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, NFCSTATUS_FORMAT_ERROR);
    }
    else
    {
        PH_LOG_NDEF_INFO_STR("Successfully formatted dynamic Topaz card");
    }

    PH_LOG_NDEF_FUNC_EXIT();
    return wStatus;
}
static NFCSTATUS phFriNfc_MfUL_H_Transceive(phFriNfc_sNdefSmtCrdFmt_t    *NdefSmtCrdFmt)
{
    NFCSTATUS   Result = NFCSTATUS_SUCCESS;
    PH_LOG_NDEF_FUNC_ENTRY();
    /* set the data for additional data exchange*/
    NdefSmtCrdFmt->psDepAdditionalInfo.DepFlags.MetaChaining = 0;
    NdefSmtCrdFmt->psDepAdditionalInfo.DepFlags.NADPresent = 0;
    NdefSmtCrdFmt->psDepAdditionalInfo.NodeAddress = 0;

    /*set the completion routines for the card operations*/
    NdefSmtCrdFmt->SmtCrdFmtCompletionInfo.CompletionRoutine = phFriNfc_NdefSmtCrd_Process;
    NdefSmtCrdFmt->SmtCrdFmtCompletionInfo.Context = NdefSmtCrdFmt;

    *NdefSmtCrdFmt->SendRecvLength = PH_FRINFC_SMTCRDFMT_MAX_SEND_RECV_BUF_SIZE;

    /* Call the Overlapped HAL Transceive function */
    Result = phFriNfc_OvrHal_Transceive(    NdefSmtCrdFmt->LowerDevice,
                                            &NdefSmtCrdFmt->SmtCrdFmtCompletionInfo,
                                            NdefSmtCrdFmt->psRemoteDevInfo,
                                            NdefSmtCrdFmt->Cmd,
                                            &NdefSmtCrdFmt->psDepAdditionalInfo,
                                            NdefSmtCrdFmt->SendRecvBuf,
                                            NdefSmtCrdFmt->SendLength,
                                            NdefSmtCrdFmt->SendRecvBuf,
                                            NdefSmtCrdFmt->SendRecvLength);
    PH_LOG_NDEF_FUNC_EXIT();
    return Result;
}
static NFCSTATUS phFriNfc_MfUL_H_WrRd( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt )
{
    NFCSTATUS   Result = NFCSTATUS_SUCCESS;
    PH_LOG_NDEF_FUNC_ENTRY();
    /* Fill the send buffer */
    phFriNfc_MfUL_H_fillSendBuf(NdefSmtCrdFmt,
                            NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock);

    /* Call transceive */
    Result = phFriNfc_MfUL_H_Transceive (NdefSmtCrdFmt);
    PH_LOG_NDEF_FUNC_EXIT();
    return Result;
}
void phFriNfc_MfUL_Reset(phFriNfc_sNdefSmtCrdFmt_t    *NdefSmtCrdFmt)
{
    uint8_t OTPByte[] = PH_FRINFC_MFUL_FMT_OTP_BYTES;
    PH_LOG_NDEF_FUNC_ENTRY();
    NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = PH_FRINFC_MFUL_FMT_VAL_0;
    phOsalNfc_MemCopy(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
                OTPByte,
                sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes));
    NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes[0] = 0;
    NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes[1] = 0;
    NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes[2] = 0;
    NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes[3] = 0;
    PH_LOG_NDEF_FUNC_EXIT();
}
static NFCSTATUS
phFriNfc_TopazDynamicFormat_ProcessWritingMemCtrlBytes(phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt)
{
    static const uint8_t c_expectedResponse[] =
    {
        PH_FRINFC_TOPAZ_TLV_LOCK_CTRL_V2, /* Lock control bytes */
        PH_FRINFC_TOPAZ_TLV_MEM_CTRL_T, PH_FRINFC_TOPAZ_TLV_MEM_CTRL_L, PH_FRINFC_TOPAZ_TLV_MEM_CTRL_V0, PH_FRINFC_TOPAZ_TLV_MEM_CTRL_V1, PH_FRINFC_TOPAZ_TLV_MEM_CTRL_V2, /* Memory control bytes */
        PH_FRINFC_TOPAZ_TLV_NDEF_T, PH_FRINFC_TOPAZ_TLV_NDEF_L, /* NDEF TLV */
    };

    uint8_t write8Cmd[] =
    {
        PH_FRINFC_TOPAZ_CMD_WRITE_E8, /* WRITE-E8 */
        0x03, /* Block 0x3 */
        PH_FRINFC_TOPAZ_TLV_TERM_T, /* Terminator TLV */
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Rest of data bytes are zeros */
        0x00, 0x00, 0x00, 0x00 /* UID bytes (need to be copied over) */
    };

    NFCSTATUS wStatus = NFCSTATUS_SUCCESS;

    PH_LOG_NDEF_FUNC_ENTRY();

    assert(NdefSmtCrdFmt != NULL);

    if ((*NdefSmtCrdFmt->SendRecvLength != sizeof(c_expectedResponse)) ||
        (0 != phOsalNfc_MemCompare(NdefSmtCrdFmt->SendRecvBuf,
                                   (void*)c_expectedResponse,
                                   sizeof(c_expectedResponse))))
    {
        PH_LOG_NDEF_WARN_STR("Unexpected response received. Formatting failed");
        wStatus = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, NFCSTATUS_FORMAT_ERROR);
    }
    else
    {
        /* Copy the UID to the end of command buffer */
        phOsalNfc_MemCopy(&write8Cmd[10],
                          NdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid,
                          TOPAZ_UID_LENGTH);

        NdefSmtCrdFmt->State = PH_FRINFC_TOPAZ_STATE_WRITE_TERM_TLV_BYTES;
        wStatus = phFriNfc_TopazFormat_Transceive(NdefSmtCrdFmt,
                                                  write8Cmd,
                                                  sizeof(write8Cmd));
    }

    PH_LOG_NDEF_FUNC_EXIT();
    return wStatus;
}
static NFCSTATUS phFriNfc_MfUL_H_ProWrOTPBytes( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt )
{
    NFCSTATUS   Result = NFCSTATUS_SUCCESS;
    PH_LOG_NDEF_FUNC_ENTRY();
    /* Card already have the OTP bytes so write TLV */
    NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_WR_TLV;

    /* Write NDEF TLV in block number 4 */
    NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock =
                                PH_FRINFC_MFUL_FMT_VAL_4;

    Result = phFriNfc_MfUL_H_WrRd(NdefSmtCrdFmt);
    PH_LOG_NDEF_FUNC_EXIT();
    return Result;
}
NFCSTATUS
phFriNfc_MfUL_ConvertToReadOnly (
    phFriNfc_sNdefSmtCrdFmt_t    *NdefSmtCrdFmt)
{
    NFCSTATUS               result = NFCSTATUS_SUCCESS;
    PH_LOG_NDEF_FUNC_ENTRY();
    NdefSmtCrdFmt->AddInfo.Type2Info.DefaultLockBytesFlag = TRUE;
    NdefSmtCrdFmt->AddInfo.Type2Info.ReadDataIndex = 0;

    NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_RD_16BYTES;

    result = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt);
    PH_LOG_NDEF_FUNC_EXIT();
    return result;
}
static int MemCompare1 ( void *s1, void *s2, unsigned int n )
{
    int8_t   diff = 0;
    int8_t *char_1  =(int8_t *)s1;
    int8_t *char_2  =(int8_t *)s2;
    PH_LOG_NDEF_FUNC_ENTRY();
    if(NULL == s1 || NULL == s2)
    {
    }
    else
    {
        for(;((n>0)&&(diff==0));n--,char_1++,char_2++)
        {
            diff = *char_1 - *char_2;
        }
    }
    PH_LOG_NDEF_FUNC_EXIT();
    return (int)diff;
}
void
phFriNfc_TopazFormat_Process(void* Context,
                             NFCSTATUS Status)
{
    NFCSTATUS wStatus = Status;
    phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt = (phFriNfc_sNdefSmtCrdFmt_t*)Context;

    PH_LOG_NDEF_FUNC_ENTRY();

    if (NdefSmtCrdFmt == NULL)
    {
        wStatus = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, NFCSTATUS_INVALID_PARAMETER);
    }
    else if (wStatus == NFCSTATUS_SUCCESS)
    {
        if (*NdefSmtCrdFmt->SendRecvLength != 1 ||
            NdefSmtCrdFmt->SendRecvBuf[0] != c_staticTopazFormat[NdefSmtCrdFmt->AddInfo.Type1Info.CurrentByte])
        {
            PH_LOG_NDEF_WARN_STR("Unexpected response received. Formatting failed");
            wStatus = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, NFCSTATUS_FORMAT_ERROR);
        }
        else
        {
            NdefSmtCrdFmt->AddInfo.Type1Info.CurrentByte++;
            if (NdefSmtCrdFmt->AddInfo.Type1Info.CurrentByte < ARRAYSIZE(c_staticTopazFormat))
            {
                wStatus = phFriNfc_TopazFormat_WriteByte(NdefSmtCrdFmt,
                                                         NdefSmtCrdFmt->AddInfo.Type1Info.CurrentBlock,
                                                         NdefSmtCrdFmt->AddInfo.Type1Info.CurrentByte,
                                                         c_staticTopazFormat[NdefSmtCrdFmt->AddInfo.Type1Info.CurrentByte]);
            }
        }
    }

    /* If status is not pending (i.e. we are waiting for a response from the card), then call the
    completion routine */
    if (wStatus != NFCSTATUS_PENDING)
    {
        phFriNfc_SmtCrdFmt_HCrHandler(NdefSmtCrdFmt, wStatus);
    }

    PH_LOG_NDEF_FUNC_EXIT();
}
static NFCSTATUS
phFriNfc_TopazFormat_Transceive(phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt,
                                const uint8_t* SendBuffer,
                                uint16_t SendBufferLength)
{
    NFCSTATUS wStatus = NFCSTATUS_SUCCESS;

    PH_LOG_NDEF_FUNC_ENTRY();

    assert(NdefSmtCrdFmt != NULL);
    assert(SendBuffer != NULL);
    assert(SendBufferLength != 0 && SendBufferLength <= PH_FRINFC_SMTCRDFMT_MAX_SEND_RECV_BUF_SIZE);

    /* Fill the send buffer */
    NdefSmtCrdFmt->Cmd.JewelCmd = phNfc_eJewel_Raw;
    phOsalNfc_MemCopy(NdefSmtCrdFmt->SendRecvBuf, SendBuffer, SendBufferLength);
    NdefSmtCrdFmt->SendLength = SendBufferLength;

    /* Set the data for additional data exchange */
    NdefSmtCrdFmt->psDepAdditionalInfo.DepFlags.MetaChaining = 0;
    NdefSmtCrdFmt->psDepAdditionalInfo.DepFlags.NADPresent = 0;
    NdefSmtCrdFmt->psDepAdditionalInfo.NodeAddress = 0;

    /* Set the completion routines for the card operations */
    NdefSmtCrdFmt->SmtCrdFmtCompletionInfo.CompletionRoutine = phFriNfc_NdefSmtCrd_Process;
    NdefSmtCrdFmt->SmtCrdFmtCompletionInfo.Context = NdefSmtCrdFmt;

    *NdefSmtCrdFmt->SendRecvLength = PH_FRINFC_SMTCRDFMT_MAX_SEND_RECV_BUF_SIZE;

    wStatus = phFriNfc_OvrHal_Transceive(NdefSmtCrdFmt->LowerDevice,
                                         &NdefSmtCrdFmt->SmtCrdFmtCompletionInfo,
                                         NdefSmtCrdFmt->psRemoteDevInfo,
                                         NdefSmtCrdFmt->Cmd,
                                         &NdefSmtCrdFmt->psDepAdditionalInfo,
                                         NdefSmtCrdFmt->SendRecvBuf,
                                         NdefSmtCrdFmt->SendLength,
                                         NdefSmtCrdFmt->SendRecvBuf,
                                         NdefSmtCrdFmt->SendRecvLength);

    PH_LOG_NDEF_FUNC_EXIT();
    return wStatus;
}
NFCSTATUS phFriNfc_MfUL_Format(phFriNfc_sNdefSmtCrdFmt_t    *NdefSmtCrdFmt)
{
    NFCSTATUS               Result = NFCSTATUS_SUCCESS;
    uint8_t                 OTPByte[] = PH_FRINFC_MFUL_FMT_OTP_BYTES;
    PH_LOG_NDEF_FUNC_ENTRY();
    NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = PH_FRINFC_MFUL_FMT_VAL_0;
    phOsalNfc_MemCopy(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
                OTPByte,
                sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes));

    /* Set the state */
    NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RD_16BYTES;
    /* Initialise current block to the lock bits block */
    NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = PH_FRINFC_MFUL_FMT_VAL_2;

    /* Start authentication */
    Result = phFriNfc_MfUL_H_WrRd(NdefSmtCrdFmt);
    PH_LOG_NDEF_FUNC_EXIT();
    return Result;
}
void
phFriNfc_TopazDynamicFormat_Process(void* Context,
                                    NFCSTATUS Status)
{
    NFCSTATUS wStatus = Status;
    phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt = (phFriNfc_sNdefSmtCrdFmt_t*)Context;

    PH_LOG_NDEF_FUNC_ENTRY();

    if (NdefSmtCrdFmt == NULL)
    {
        wStatus = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, NFCSTATUS_INVALID_PARAMETER);
    }
    else if (wStatus == NFCSTATUS_SUCCESS)
    {
        switch (NdefSmtCrdFmt->State)
        {
        case PH_FRINFC_TOPAZ_STATE_WRITE_CC_BYTES:
            wStatus = phFriNfc_TopazDynamicFormat_ProcessWritingCCBytes(NdefSmtCrdFmt);
            break;
        case PH_FRINFC_TOPAZ_STATE_WRITE_MEM_CTRL_BYTES:
            wStatus = phFriNfc_TopazDynamicFormat_ProcessWritingMemCtrlBytes(NdefSmtCrdFmt);
            break;
        case PH_FRINFC_TOPAZ_STATE_WRITE_TERM_TLV_BYTES:
            wStatus = phFriNfc_TopazDynamicFormat_ProcessWritingTermTlvBytes(NdefSmtCrdFmt);
            break;
        default:
            wStatus = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, NFCSTATUS_INVALID_DEVICE_REQUEST);
            break;
        }
    }

    /* If status is not pending (i.e. we are waiting for a response from the card), then call the
       completion routine */
    if (wStatus != NFCSTATUS_PENDING)
    {
        phFriNfc_SmtCrdFmt_HCrHandler(NdefSmtCrdFmt, wStatus);
    }

    PH_LOG_NDEF_FUNC_EXIT();
}
NFCSTATUS
phFriNfc_TopazDynamicFormat_Format(phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt)
{
    uint8_t write8Cmd[] =
    {
        PH_FRINFC_TOPAZ_CMD_WRITE_E8, /* WRITE-E8 */
        0x01, /* Block 0x1 */
        PH_FRINFC_TOPAZ_CC_BYTE0, PH_FRINFC_TOPAZ_CC_BYTE1, PH_FRINFC_TOPAZ_DYNAMIC_CC_BYTE2_MMSIZE, PH_FRINFC_TOPAZ_CC_BYTE3_RW, /* CC bytes */
        PH_FRINFC_TOPAZ_TLV_LOCK_CTRL_T, PH_FRINFC_TOPAZ_TLV_LOCK_CTRL_L, PH_FRINFC_TOPAZ_TLV_LOCK_CTRL_V0, PH_FRINFC_TOPAZ_TLV_LOCK_CTRL_V1, /* Lock control bytes */
        0x00, 0x00, 0x00, 0x00 /* UID bytes (need to be copied over) */
    };

    NFCSTATUS wStatus = NFCSTATUS_SUCCESS;

    PH_LOG_NDEF_FUNC_ENTRY();

    if (NdefSmtCrdFmt == NULL)
    {
        wStatus = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, NFCSTATUS_INVALID_PARAMETER);
    }
    else
    {
        /* Copy the UID to the end of command buffer */
        phOsalNfc_MemCopy(&write8Cmd[10],
                          NdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid,
                          TOPAZ_UID_LENGTH);

        NdefSmtCrdFmt->State = PH_FRINFC_TOPAZ_STATE_WRITE_CC_BYTES;
        wStatus = phFriNfc_TopazFormat_Transceive(NdefSmtCrdFmt,
                                                  write8Cmd,
                                                  sizeof(write8Cmd));
    }

    PH_LOG_NDEF_FUNC_EXIT();
    return wStatus;
}
static void phFriNfc_MfUL_H_fillSendBuf( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt,
                                 uint8_t                    BlockNo)
{
    uint8_t     NDEFTLV1[4] = {0x01, 0x03, 0xA0, 0x10};
    uint8_t     NDEFTLV2[4] = {0x44, 0x03, 0x00, 0xFE};
    uint8_t     NDEFTLV[4] = {0x03, 0x00, 0xFE, 0x00};

    PH_LOG_NDEF_FUNC_ENTRY();

    /* First byte for send buffer is always the block number */
    NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_0] = (uint8_t)BlockNo;
    switch(NdefSmtCrdFmt->State)
    {
        case PH_FRINFC_MFUL_FMT_RO_RD_16BYTES:
        {
            NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareRead;
            *NdefSmtCrdFmt->SendRecvBuf = RD_LOCK_OTP_BLOCK_NUMBER;
            /* Send length for read command is always one */
            NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_1;
            break;
        }
        case PH_FRINFC_MFUL_FMT_RO_NDEF_PARSE_RD_BYTES:
        {
            NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareRead;
            *NdefSmtCrdFmt->SendRecvBuf =
                    NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock;
            /* Send length for read command is always one */
            NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_1;
            break;
        }

        case PH_FRINFC_MFUL_FMT_RO_RD_DYN_LOCK_BYTES:
        {
            NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareRead;
            *NdefSmtCrdFmt->SendRecvBuf = NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock;
            /* Send length for read command is always one */
            NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_1;
            break;
        }

        case PH_FRINFC_MFUL_FMT_RO_WR_DYN_LOCK_BYTES:
        {
            NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4;
            /* Send length for read command is always one */
            NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_5;
            *NdefSmtCrdFmt->SendRecvBuf = NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock;
            (void)phOsalNfc_MemCopy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1],
                         NdefSmtCrdFmt->AddInfo.Type2Info.DynLockBytes,
                         PH_FRINFC_MFUL_FMT_VAL_4);
            break;
        }

        case PH_FRINFC_MFUL_FMT_RO_WR_LOCK_BYTES:
        {
            NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4;
            /* Send length for read command is always one */
            NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_5;
            *NdefSmtCrdFmt->SendRecvBuf = RD_LOCK_OTP_BLOCK_NUMBER;
            (void)phOsalNfc_MemCopy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1],
                         NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes,
                         PH_FRINFC_MFUL_FMT_VAL_4);
            break;
        }

        case PH_FRINFC_MFUL_FMT_RO_WR_OTP_BYTES:
        {
            NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4;
            /* Send length for read command is always one */
            NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_5;
            *NdefSmtCrdFmt->SendRecvBuf = OTP_BLOCK_NUMBER;
            phOsalNfc_MemCopy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1],
                         NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
                         PH_FRINFC_MFUL_FMT_VAL_4);
            break;
        }

    case PH_FRINFC_MFUL_FMT_RD_16BYTES:
        NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareRead;
        /* Send length for read command is always one */
        NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_1;
        break;

    case PH_FRINFC_MFUL_FMT_WR_OTPBYTES:
        /* Send length for read command is always Five */
        NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_5;
        /* Write command */
        NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4;
        /* Copy the OTP bytes */
        phOsalNfc_MemCopy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1],
                    NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
                    PH_FRINFC_MFUL_FMT_VAL_4);
        break;

    case PH_FRINFC_MFUL_FMT_WR_TLV:
        /* Send length for read command is always Five */
        NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_5;
        /* Write command */
        NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4;
        /* Copy the NDEF TLV */

        if (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD)
        {
            phOsalNfc_MemCopy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1],
                    NDEFTLV1,
                    PH_FRINFC_MFUL_FMT_VAL_4);
        }
        else if (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_UL_CARD)
        {
            phOsalNfc_MemCopy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1],
                NDEFTLV,
                PH_FRINFC_MFUL_FMT_VAL_4);
        }
        else
        {
        }
        break;

    case PH_FRINFC_MFUL_FMT_WR_TLV1:
        if (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD)
        {
            /* Send length for write command is always Five */
            NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_5;
            /* Write command */
            NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4;
            phOsalNfc_MemCopy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1],
                        NDEFTLV2,
                        PH_FRINFC_MFUL_FMT_VAL_4);
        }
        break;

    default:
        break;
    }
    PH_LOG_NDEF_FUNC_EXIT();
}
void phFriNfc_MfUL_Process(void             *Context,
                           NFCSTATUS        Status)
{
    phFriNfc_sNdefSmtCrdFmt_t  *NdefSmtCrdFmt = (phFriNfc_sNdefSmtCrdFmt_t *)Context;
    PH_LOG_NDEF_FUNC_ENTRY();
    if(Status == NFCSTATUS_SUCCESS)
    {
        switch(NdefSmtCrdFmt->State)
        {
        case PH_FRINFC_MFUL_FMT_RD_16BYTES:
            Status = phFriNfc_MfUL_H_ProRd16Bytes(NdefSmtCrdFmt);
            break;

        case PH_FRINFC_MFUL_FMT_WR_OTPBYTES:
            Status = phFriNfc_MfUL_H_ProWrOTPBytes(NdefSmtCrdFmt);
            break;

        case PH_FRINFC_MFUL_FMT_WR_TLV:
            if (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD)
            {
                /* Write NDEF TLV in block number 5 */
                NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock =
                                                        PH_FRINFC_MFUL_FMT_VAL_5;
                /* Card already have the OTP bytes so write TLV */
                NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_WR_TLV1;

                Status = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt);
            }
            break;

        case PH_FRINFC_MFUL_FMT_RO_RD_16BYTES:
        {
            if (MIFARE_UL_READ_MAX_SIZE == *NdefSmtCrdFmt->SendRecvLength)
            {
                uint8_t         otp_lock_page_size = 0;
                uint8_t         i = 0;

                otp_lock_page_size = sizeof (NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes);
                (void)phOsalNfc_MemCopy ((void *)NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes,
                            (void *)NdefSmtCrdFmt->SendRecvBuf,
                            sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes));

                NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes[2] = (uint8_t)
                                    (NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes[2]
                                    | MIFARE_UL_LOCK_BYTE1_VALUE);
                NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes[3] = MIFARE_UL_LOCK_BYTE2_VALUE;
                i = (uint8_t)(i + otp_lock_page_size);

                otp_lock_page_size = sizeof (NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes);

                phOsalNfc_MemCopy ((void *)NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
                            (void *)(NdefSmtCrdFmt->SendRecvBuf + i),
                            sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes));

                NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes[(otp_lock_page_size - 1)] =
                                                        READ_ONLY_VALUE_IN_OTP;

                switch (NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes[TYPE_2_MEM_SIZE_POSITION])
                {
                    case TYPE_2_STATIC_MEM_SIZE_VALUE:
                    {
                        NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_WR_OTP_BYTES;
                        Status = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt);
                        break;
                    }

                    case TYPE_2_DYNAMIC_MEM_SIZE_VALUE:
                    {
                        NdefSmtCrdFmt->State =
                                PH_FRINFC_MFUL_FMT_RO_NDEF_PARSE_RD_BYTES;

                        /* Start reading from block 4 */
                        NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = 4;
                        Status = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt);
                        break;
                    }

                    default:
                    {
                        Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
                                            NFCSTATUS_INVALID_DEVICE_REQUEST);
                        break;
                    }
                }
            }
            else
            {
                Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
                                    NFCSTATUS_INVALID_RECEIVE_LENGTH);
            }
            break;
        }

        case PH_FRINFC_MFUL_FMT_RO_WR_OTP_BYTES:
        {
            switch (NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes[TYPE_2_MEM_SIZE_POSITION])
            {
                case TYPE_2_STATIC_MEM_SIZE_VALUE:
                case TYPE_2_DYNAMIC_MEM_SIZE_VALUE:
                {
                    NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_WR_LOCK_BYTES;
                    Status = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt);
                    break;
                }

                default:
                {
                    Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
                                        NFCSTATUS_INVALID_DEVICE_REQUEST);
                    break;
                }
            }
            break;
        }

        case PH_FRINFC_MFUL_FMT_RO_NDEF_PARSE_RD_BYTES:
        {
            if (MIFARE_UL_READ_MAX_SIZE == *NdefSmtCrdFmt->SendRecvLength)
            {
                Status = phFriNfc_MfUL_ParseTLVs (NdefSmtCrdFmt,
                                        NdefSmtCrdFmt->SendRecvBuf,
                                        (uint8_t)*NdefSmtCrdFmt->SendRecvLength);

                if (!Status)
                {
                    NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock =
                        NdefSmtCrdFmt->AddInfo.Type2Info.LockBlockNumber;
                    Status = phFriNfc_MfUL_ReadWriteLockBytes (NdefSmtCrdFmt);
                }
            }
            else
            {
                Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
                                    NFCSTATUS_INVALID_RECEIVE_LENGTH);
            }
            break;
        }

        case PH_FRINFC_MFUL_FMT_RO_RD_DYN_LOCK_BYTES:
        {
            if (MIFARE_UL_READ_MAX_SIZE == *NdefSmtCrdFmt->SendRecvLength)
            {
                (void)phOsalNfc_MemCopy ((void *)NdefSmtCrdFmt->AddInfo.Type2Info.ReadData,
                            (void *)NdefSmtCrdFmt->SendRecvBuf,
                            sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.ReadData));

                NdefSmtCrdFmt->AddInfo.Type2Info.ReadDataIndex = 0;

                Status = phFriNfc_MfUL_UpdateAndWriteLockBits (NdefSmtCrdFmt);

            }
            else
            {
                Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
                                    NFCSTATUS_INVALID_RECEIVE_LENGTH);
            }
            break;
        }

        case PH_FRINFC_MFUL_FMT_RO_WR_DYN_LOCK_BYTES:
        {
            NdefSmtCrdFmt->AddInfo.Type2Info.ReadDataIndex = (uint8_t)
                                    (NdefSmtCrdFmt->AddInfo.Type2Info.ReadDataIndex +
                                    MFUL_BLOCK_SIZE_IN_BYTES);

            if (!phFriNfc_MfUL_CalcRemainingLockBits (NdefSmtCrdFmt))
            {
                /* There is no lock bits to write, then write OTP bytes */
                NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_WR_OTP_BYTES;
                Status = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt);
            }
            else if ((NdefSmtCrdFmt->AddInfo.Type2Info.ReadDataIndex <
                MIFARE_UL_READ_MAX_SIZE)
                && (phFriNfc_MfUL_CalcRemainingLockBits (NdefSmtCrdFmt)))
            {
                /* If remaining lock bits has to be written and the data is already read */
                Status = phFriNfc_MfUL_UpdateAndWriteLockBits (NdefSmtCrdFmt);
            }
            else
            {
                /* Increment current block by 4 because if a data is read then 16
                    bytes will be given which is 4 blocks */
                NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = (uint8_t)
                            (NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock + 4);
                Status = phFriNfc_MfUL_ReadWriteLockBytes (NdefSmtCrdFmt);
            }
            break;
        }

        case PH_FRINFC_MFUL_FMT_RO_WR_LOCK_BYTES:
        {
            /* Do nothing */
            break;
        }

        case PH_FRINFC_MFUL_FMT_WR_TLV1:
            break;

        default:
            Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
                                NFCSTATUS_INVALID_DEVICE_REQUEST);
            break;
        }
    }
    /* Status is not success then call completion routine */
    if(Status != NFCSTATUS_PENDING)
    {
        phFriNfc_SmtCrdFmt_HCrHandler(NdefSmtCrdFmt, Status);
    }
    PH_LOG_NDEF_FUNC_EXIT();
}
static NFCSTATUS phFriNfc_MfUL_H_ProRd16Bytes( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt )
{
    NFCSTATUS   Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
                                    NFCSTATUS_FORMAT_ERROR);
    uint32_t    memcompare = PH_FRINFC_MFUL_FMT_VAL_0;
    uint8_t     ZeroBuf[] = {0x00, 0x00, 0x00, 0x00};
    uint8_t     OTPByteUL[] = PH_FRINFC_MFUL_FMT_OTP_BYTES;
    uint8_t     OTPByteULC[] = PH_FRINFC_MFULC_FMT_OTP_BYTES;

    PH_LOG_NDEF_FUNC_ENTRY();
    /* Check the lock bits (byte number 2 and 3 of block number 2) */
    if ((NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_2] ==
        PH_FRINFC_MFUL_FMT_LOCK_BITS_VAL) &&
        (NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_3] ==
        PH_FRINFC_MFUL_FMT_LOCK_BITS_VAL))
    {
        if (NdefSmtCrdFmt->SendRecvBuf[8] == 0x02 &&
            NdefSmtCrdFmt->SendRecvBuf[9] == 0x00)
        {
            NdefSmtCrdFmt->CardType = PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD;

            phOsalNfc_MemCopy(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
                        OTPByteULC,
                        sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes));
        }
        else if (NdefSmtCrdFmt->SendRecvBuf[8] == 0xFF &&
                NdefSmtCrdFmt->SendRecvBuf[9] == 0xFF)
        {
            NdefSmtCrdFmt->CardType = PH_FRINFC_NDEFMAP_MIFARE_UL_CARD;

            phOsalNfc_MemCopy(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
                        OTPByteUL,
                        sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes));
        }
        else
        {
            NdefSmtCrdFmt->CardType = PH_FRINFC_NDEFMAP_MIFARE_UL_CARD;
        }

        memcompare = (uint32_t)
                    MemCompare1(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_4],
                            NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
                            PH_FRINFC_MFUL_FMT_VAL_4);

        if (memcompare == PH_FRINFC_MFUL_FMT_VAL_0)
        {
            /* Write NDEF TLV in block number 4 */
            NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock =
                                                PH_FRINFC_MFUL_FMT_VAL_4;
            /* Card already have the OTP bytes so write TLV */
            NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_WR_TLV;
        }
        else
        {
            /* IS the card new, OTP bytes = {0x00, 0x00, 0x00, 0x00} */
            memcompare = (uint32_t)MemCompare1(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_4],
                                ZeroBuf,
                                PH_FRINFC_MFUL_FMT_VAL_4);
            /* If OTP bytes are Zero then the card is Zero */
            if (memcompare == PH_FRINFC_MFUL_FMT_VAL_0)
            {
                /* Write OTP bytes in block number 3 */
                NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock =
                                                PH_FRINFC_MFUL_FMT_VAL_3;
                /* Card already have the OTP bytes so write TLV */
                NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_WR_OTPBYTES;
            }
        }
    }

    if(
        ((NdefSmtCrdFmt->State == PH_FRINFC_MFUL_FMT_WR_TLV) ||
        (NdefSmtCrdFmt->State == PH_FRINFC_MFUL_FMT_WR_OTPBYTES)) &&
        ((NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD) ||
        (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_UL_CARD))
        )
    {
        Result = phFriNfc_MfUL_H_WrRd(NdefSmtCrdFmt);
    }
    PH_LOG_NDEF_FUNC_EXIT();
    return Result;
}