/*
 * Copyright (C) 2010 NXP Semiconductors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*!
 * \file phLibNfc_ndef_raw.c

 * Project: NFC FRI 1.1
 *
 * $Date: Mon Dec 13 14:14:15 2010 $
 * $Author: ing02260 $
 * $Revision: 1.74 $
 * $Aliases:  $
 *
 */

/*
************************* Header Files ****************************************
*/

#include <phLibNfcStatus.h>
#include <phLibNfc.h>
#include <phHal4Nfc.h>
#include <phOsalNfc.h>
#include <phLibNfc_Internal.h>
#include <phLibNfc_ndef_raw.h>
#include <phLibNfc_initiator.h>
#include <phLibNfc_discovery.h>
#include <phFriNfc_NdefReg.h>
#include <phFriNfc_MifareStdMap.h>

/*
*************************** Macro's  ****************************************
*/

#ifndef STATIC_DISABLE
#define STATIC static
#else
//#undef STATIC
#define STATIC 
#endif

#define     TOPAZ_NDEF_BITMASK             0x10U
#define     TOPAZ_LEN_BITMASK              0x02U
#define     TOPAZ_DYNAMIC_LEN               460U
#define     TOPAZ_STATIC_CARD_LEN           128U
#define     MIFARE_STD_BLOCK_SIZE          0x10U
/*
*************************** Global Variables **********************************
*/
phLibNfc_Ndef_Info_t NdefInfo;
phFriNfc_NdefRecord_t *pNdefRecord=NULL;
/*
*************************** Static Function Declaration ***********************
*/

/* Response callback for Check Ndef */
STATIC 
void phLibNfc_Ndef_CheckNdef_Cb(void *pContext, NFCSTATUS status);

/* Response callback for Ndef Write */
STATIC 
void phLibNfc_Ndef_Write_Cb(void* Context,NFCSTATUS status);

/* Response callback for Ndef Read*/
STATIC 
void phLibNfc_Ndef_Read_Cb(void* Context,NFCSTATUS status);

/* Response callback forNdef Format*/
STATIC 
void phLibNfc_Ndef_format_Cb(void *Context,NFCSTATUS status);

#ifdef LIBNFC_READONLY_NDEF
STATIC
void
phLibNfc_Ndef_ReadOnly_Cb (
    void        *p_context,
    NFCSTATUS   status);
#endif /* #ifdef LIBNFC_READONLY_NDEF */

/* Response callback for Search Ndef Content */
STATIC
void phLibNfc_Ndef_SrchNdefCnt_Cb(void *context, NFCSTATUS status);

/* Response callback for Ndef Record Type Discovery */
STATIC
void phLibNfc_Ndef_Rtd_Cb( void *CallBackParam);

/* Response callback for Check Ndef timer callback */
STATIC void CheckNdef_timer_cb(uint32_t timer_id, void *pContext);

/*Callback for Presence check call from Chk Ndef*/
STATIC void phLibNfc_Ndef_ChkNdef_Pchk_Cb(void   *pContext,
                                NFCSTATUS  status
                                );
/*
*************************** Function Definitions ******************************
*/

/**
* This function reads an NDEF message from  already connected tag.
* the NDEF message  is read starting after the position of the
* last read operation of the same tag during current session.
*/

NFCSTATUS phLibNfc_Ndef_Read( phLibNfc_Handle                   hRemoteDevice,
                            phNfc_sData_t                      *psRd,
                            phLibNfc_Ndef_EOffset_t             Offset,
                            pphLibNfc_RspCb_t                   pNdefRead_RspCb,
                            void*                               pContext
                            )
{
    NFCSTATUS RetVal = NFCSTATUS_FAILED;

    if((NULL == gpphLibContext)|| 
        (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateShutdown))
    {
        RetVal = NFCSTATUS_NOT_INITIALISED;
    }
    else if((NULL == psRd) || (NULL == pNdefRead_RspCb)
        || (NULL == psRd->buffer)
        || (0 == psRd->length)
        || (NULL == pContext)
        || (0 == hRemoteDevice))
    {
        RetVal= NFCSTATUS_INVALID_PARAMETER;
    }    
    else if(gpphLibContext->LibNfcState.next_state == eLibNfcHalStateShutdown)
    {
        RetVal = NFCSTATUS_SHUTDOWN;
    }
    else if(0 == gpphLibContext->Connected_handle)
    {   /*presently no target or tag is connected*/ 
        RetVal=NFCSTATUS_TARGET_NOT_CONNECTED;        
    }
    else if(hRemoteDevice != gpphLibContext->Connected_handle)
    {   /*This handle of the device sent by application is not connected */ 
        RetVal=NFCSTATUS_INVALID_HANDLE;        
    }
    else if((TRUE == gpphLibContext->status.GenCb_pending_status)       
            ||(NULL!=gpphLibContext->CBInfo.pClientRdNdefCb)
            ||(CHK_NDEF_NOT_DONE == gpphLibContext->ndef_cntx.is_ndef))
    {
        /*Previous callback is pending*/
        RetVal = NFCSTATUS_REJECTED;
    }
    else if(gpphLibContext->ndef_cntx.is_ndef == FALSE)
    {
        /*no Ndef Support in tag*/
         RetVal = NFCSTATUS_NON_NDEF_COMPLIANT;
    }
    else if((gpphLibContext->ndef_cntx.is_ndef == TRUE)
        &&(0 == gpphLibContext->ndef_cntx.NdefActualSize))
    {
        /*Card is empty- So Returning length as zero*/
        psRd->length = 0;
        RetVal = NFCSTATUS_SUCCESS;
    }
#ifdef LLCP_TRANSACT_CHANGES
    else if ((LLCP_STATE_RESET_INIT != gpphLibContext->llcp_cntx.sLlcpContext.state)
            && (LLCP_STATE_CHECKED != gpphLibContext->llcp_cntx.sLlcpContext.state))
    {
        RetVal= NFCSTATUS_BUSY;
    }
#endif /* #ifdef LLCP_TRANSACT_CHANGES */
    else
    {
        gpphLibContext->psRemoteDevList->psRemoteDevInfo->SessionOpened = SESSION_OPEN;
        gpphLibContext->ndef_cntx.eLast_Call = NdefRd;
        if((((phHal_sRemoteDevInformation_t*)hRemoteDevice)->RemDevType == 
            phHal_eMifare_PICC) && (((phHal_sRemoteDevInformation_t*)
            hRemoteDevice)->RemoteDevInfo.Iso14443A_Info.Sak != 0)&&
            ((NULL == gpphLibContext->psBufferedAuth)
            ||(phHal_eMifareAuthentA == gpphLibContext->psBufferedAuth->cmd.MfCmd))
            )
        {
            if(NULL != gpphLibContext->psBufferedAuth)
            {
                if(NULL != gpphLibContext->psBufferedAuth->sRecvData.buffer)
                {
                    phOsalNfc_FreeMemory(
                        gpphLibContext->psBufferedAuth->sRecvData.buffer);
                }
                if(NULL != gpphLibContext->psBufferedAuth->sSendData.buffer)
                {
                    phOsalNfc_FreeMemory(
                        gpphLibContext->psBufferedAuth->sSendData.buffer);
                }
                phOsalNfc_FreeMemory(gpphLibContext->psBufferedAuth);
            }
            gpphLibContext->psBufferedAuth
                =(phLibNfc_sTransceiveInfo_t *) 
                phOsalNfc_GetMemory(sizeof(phLibNfc_sTransceiveInfo_t));            
            gpphLibContext->psBufferedAuth->addr = 
             (uint8_t)gpphLibContext->ndef_cntx.psNdefMap
             ->StdMifareContainer.currentBlock;
            gpphLibContext->psBufferedAuth->cmd.MfCmd = phHal_eMifareRead16;
            gpphLibContext->psBufferedAuth->sSendData.length
                = 0;            
            gpphLibContext->psBufferedAuth->sRecvData.length
                = MIFARE_STD_BLOCK_SIZE;                      
            gpphLibContext->psBufferedAuth->sRecvData.buffer
                = (uint8_t *)phOsalNfc_GetMemory(MIFARE_STD_BLOCK_SIZE);
            gpphLibContext->psBufferedAuth->sSendData.buffer
             = (uint8_t *)phOsalNfc_GetMemory(MIFARE_STD_BLOCK_SIZE);
        }
        if(eLibNfcHalStatePresenceChk !=
                gpphLibContext->LibNfcState.next_state)
        {
            uint8_t     cr_index = 0;
            gpphLibContext->ndef_cntx.psUpperNdefMsg = psRd;
            for (cr_index = 0; cr_index < PH_FRINFC_NDEFMAP_CR; cr_index++)
            {
                RetVal= phFriNfc_NdefMap_SetCompletionRoutine(
                                    gpphLibContext->ndef_cntx.psNdefMap,
                                    cr_index,
                                    phLibNfc_Ndef_Read_Cb,
                                    (void *)gpphLibContext);

            }
            gpphLibContext->ndef_cntx.NdefContinueRead =(uint8_t) ((phLibNfc_Ndef_EBegin==Offset) ?
                                                    PH_FRINFC_NDEFMAP_SEEK_BEGIN :
                                                    PH_FRINFC_NDEFMAP_SEEK_CUR);
            /* call below layer Ndef Read*/
            RetVal = phFriNfc_NdefMap_RdNdef(gpphLibContext->ndef_cntx.psNdefMap,
                            gpphLibContext->ndef_cntx.psUpperNdefMsg->buffer,
                            (uint32_t*)&gpphLibContext->ndef_cntx.psUpperNdefMsg->length,
                            gpphLibContext->ndef_cntx.NdefContinueRead);

            RetVal = PHNFCSTATUS(RetVal);
            if(NFCSTATUS_INSUFFICIENT_STORAGE == RetVal)
            {
                gpphLibContext->ndef_cntx.psUpperNdefMsg->length = 0;
                RetVal = NFCSTATUS_SUCCESS;
            }
        }
        else
        {
             gpphLibContext->CBInfo.pClientRdNdefCb= NULL;
             RetVal = NFCSTATUS_PENDING;
        }
        if(NFCSTATUS_PENDING == RetVal)
        {
            gpphLibContext->CBInfo.pClientRdNdefCb = pNdefRead_RspCb;
            gpphLibContext->CBInfo.pClientRdNdefCntx = pContext;
            gpphLibContext->status.GenCb_pending_status=TRUE;
			gpphLibContext->LibNfcState.next_state = eLibNfcHalStateTransaction; 
           
        }
        else if (NFCSTATUS_SUCCESS == RetVal)
        {
            RetVal= NFCSTATUS_SUCCESS;
        }
        else
        {
            /*Ndef read failed*/
            RetVal = NFCSTATUS_FAILED;
        }
    }
    return RetVal;
}
/* Response callback for phLibNfc_Ndef_Read */
STATIC
void phLibNfc_Ndef_Read_Cb(void* Context,NFCSTATUS status)
{
    NFCSTATUS               RetStatus = NFCSTATUS_SUCCESS;
    pphLibNfc_RspCb_t       pClientCb=NULL;
    phLibNfc_LibContext_t   *pLibNfc_Ctxt = (phLibNfc_LibContext_t *)Context;
    void                    *pUpperLayerContext=NULL;
    phHal_sRemoteDevInformation_t   *ps_rem_dev_info = NULL;

    if(pLibNfc_Ctxt != gpphLibContext)
    {
        /*wrong context returned*/
        phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1);
    }
    else
    {
        if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state)
        {   /*shutdown called before completion of Ndef read allow
              shutdown to happen */
            phLibNfc_Pending_Shutdown();
            RetStatus = NFCSTATUS_SHUTDOWN;    
        }
        else if(eLibNfcHalStateRelease == gpphLibContext->LibNfcState.next_state)
        {
            RetStatus = NFCSTATUS_ABORTED;
        }
        else
        {
            gpphLibContext->status.GenCb_pending_status = FALSE;
            if (gpphLibContext->psBufferedAuth != NULL && gpphLibContext->ndef_cntx.psNdefMap != NULL) {
                   gpphLibContext->psBufferedAuth->addr = (uint8_t)
                   gpphLibContext->ndef_cntx.psNdefMap->StdMifareContainer.currentBlock;
            }

            if(NFCSTATUS_FAILED == status )
            {
                /*During Ndef read operation tag was not present in RF
                field of reader*/
                RetStatus = NFCSTATUS_FAILED; 
                gpphLibContext->LastTrancvSuccess = FALSE;
                gpphLibContext->ndef_cntx.is_ndef = FALSE;
                ps_rem_dev_info = (phHal_sRemoteDevInformation_t *)
                                    gpphLibContext->Connected_handle;
                if ((phHal_eMifare_PICC == ps_rem_dev_info->RemDevType &&
                    ((0x08 == (ps_rem_dev_info->RemoteDevInfo.Iso14443A_Info.Sak & 0x08)) ||
                    (0x01 == ps_rem_dev_info->RemoteDevInfo.Iso14443A_Info.Sak))))
                {

                    /* card type is mifare 1k/4k, then reconnect */
                    RetStatus = phHal4Nfc_Connect(gpphLibContext->psHwReference,  
                                ps_rem_dev_info,
                                (pphHal4Nfc_ConnectCallback_t)
                                phLibNfc_Reconnect_Mifare_Cb,
                                (void *)gpphLibContext);
                }

            }  
            else if(status == NFCSTATUS_SUCCESS)
            {
                gpphLibContext->LastTrancvSuccess = TRUE;
                RetStatus = NFCSTATUS_SUCCESS;
            }
		    else
		    {
                gpphLibContext->LastTrancvSuccess = FALSE;
				RetStatus = NFCSTATUS_FAILED;
			}
        }
        /*update the current state as connected*/
        phLibNfc_UpdateCurState(status,gpphLibContext);

        pClientCb = gpphLibContext->CBInfo.pClientRdNdefCb;
        pUpperLayerContext = gpphLibContext->CBInfo.pClientRdNdefCntx;

        gpphLibContext->CBInfo.pClientRdNdefCb = NULL;
        gpphLibContext->CBInfo.pClientRdNdefCntx = NULL;
        if(NFCSTATUS_PENDING != RetStatus)
        {
            if (NULL != pClientCb)
            {
                /*Notify to upper layer status and read bytes*/
                pClientCb(pUpperLayerContext,RetStatus);            
            }
        }
    }
    return;
}

/**
* Write NDEF to a tag.
*
* This function allows the user to write a NDEF data to already connected NFC
* tag.Function writes   a complete NDEF message to a tag. If a NDEF message
* already exists in the tag, it will be overwritten. When the transaction is
* complete,a notification callback is notified.
*/
NFCSTATUS phLibNfc_Ndef_Write(
                            phLibNfc_Handle          hRemoteDevice,
                            phNfc_sData_t           *psWr,                              
                            pphLibNfc_RspCb_t        pNdefWrite_RspCb,
                            void*                    pContext
                            )
{
    NFCSTATUS RetVal = NFCSTATUS_FAILED;
    uint8_t             NdefWriteType=0xFF;
    /*LibNfc is initilized or not */
    if((NULL == gpphLibContext)||
        (gpphLibContext->LibNfcState.cur_state
                            == eLibNfcHalStateShutdown))
    {   
        RetVal = NFCSTATUS_NOT_INITIALISED;
    }/*Check for application has sent the valid parameters*/
    else if((NULL == psWr) || (NULL == pNdefWrite_RspCb)
        || (NULL == psWr->buffer)
        || (NULL == pContext)
        || (0 ==hRemoteDevice))
    {
        RetVal= NFCSTATUS_INVALID_PARAMETER;
    }   
    else if(gpphLibContext->LibNfcState.next_state
                            == eLibNfcHalStateShutdown)
    {   /* Lib Nfc Shutdown*/
        RetVal= NFCSTATUS_SHUTDOWN;
    }
    else if(0 == gpphLibContext->Connected_handle)
    {       
        RetVal=NFCSTATUS_TARGET_NOT_CONNECTED;        
    }
    else if(hRemoteDevice != gpphLibContext->Connected_handle)
    {       
        RetVal=NFCSTATUS_INVALID_HANDLE;        
    }    
    else if((TRUE == gpphLibContext->status.GenCb_pending_status)||        
           (gpphLibContext->ndef_cntx.is_ndef == CHK_NDEF_NOT_DONE))
    {
         /* Previous callback is pending or Tag is not NDEF tag*/
        RetVal = NFCSTATUS_REJECTED;
        PHDBG_INFO("LIbNfc:Previous Callback is Pending");
    }
    else if(FALSE == gpphLibContext->ndef_cntx.is_ndef)
    {
        RetVal = NFCSTATUS_NON_NDEF_COMPLIANT;
    }
    else if(psWr->length > gpphLibContext->ndef_cntx.NdefLength)
    {
        RetVal = NFCSTATUS_NOT_ENOUGH_MEMORY;
    }
#ifdef LLCP_TRANSACT_CHANGES
    else if ((LLCP_STATE_RESET_INIT != gpphLibContext->llcp_cntx.sLlcpContext.state)
            && (LLCP_STATE_CHECKED != gpphLibContext->llcp_cntx.sLlcpContext.state))
    {
        RetVal= NFCSTATUS_BUSY;
    }
#endif /* #ifdef LLCP_TRANSACT_CHANGES */
    else
    {
        uint8_t         cr_index = 0;
        gpphLibContext->ndef_cntx.psUpperNdefMsg = psWr;
        gpphLibContext->ndef_cntx.AppWrLength= psWr->length;
        gpphLibContext->ndef_cntx.eLast_Call = NdefWr;
        gpphLibContext->psRemoteDevList->psRemoteDevInfo->SessionOpened 
            = SESSION_OPEN;
        if((((phHal_sRemoteDevInformation_t*)hRemoteDevice)->RemDevType == 
               phHal_eMifare_PICC) && (((phHal_sRemoteDevInformation_t*)
               hRemoteDevice)->RemoteDevInfo.Iso14443A_Info.Sak != 0)&&
               ((NULL == gpphLibContext->psBufferedAuth)
                ||(phHal_eMifareAuthentA == 
                   gpphLibContext->psBufferedAuth->cmd.MfCmd))
               )
        {
            if(NULL != gpphLibContext->psBufferedAuth)
            {
                if(NULL != gpphLibContext->psBufferedAuth->sRecvData.buffer)
                {
                    phOsalNfc_FreeMemory(
                        gpphLibContext->psBufferedAuth->sRecvData.buffer);
                }
                if(NULL != gpphLibContext->psBufferedAuth->sSendData.buffer)
                {
                    phOsalNfc_FreeMemory(
                        gpphLibContext->psBufferedAuth->sSendData.buffer);
                }
                phOsalNfc_FreeMemory(gpphLibContext->psBufferedAuth);
            }
            gpphLibContext->psBufferedAuth
                =(phLibNfc_sTransceiveInfo_t *) 
                phOsalNfc_GetMemory(sizeof(phLibNfc_sTransceiveInfo_t));            
            gpphLibContext->psBufferedAuth->addr = 
             (uint8_t)gpphLibContext->ndef_cntx.psNdefMap
             ->StdMifareContainer.currentBlock;
            gpphLibContext->psBufferedAuth->cmd.MfCmd = phHal_eMifareRead16;
            gpphLibContext->psBufferedAuth->sSendData.length
                = 0;            
            gpphLibContext->psBufferedAuth->sRecvData.length
                = MIFARE_STD_BLOCK_SIZE;                      
            gpphLibContext->psBufferedAuth->sRecvData.buffer
                = (uint8_t *)phOsalNfc_GetMemory(MIFARE_STD_BLOCK_SIZE);  
             gpphLibContext->psBufferedAuth->sSendData.buffer
                = (uint8_t *)phOsalNfc_GetMemory(MIFARE_STD_BLOCK_SIZE);
        }
        if(eLibNfcHalStatePresenceChk ==
                gpphLibContext->LibNfcState.next_state)
        {
            gpphLibContext->CBInfo.pClientWrNdefCb = NULL;
            RetVal = NFCSTATUS_PENDING;
        }
        else
        {
            for (cr_index = 0; cr_index < PH_FRINFC_NDEFMAP_CR; cr_index++)
            {
                /* Registering the Completion Routine.*/
                RetVal= phFriNfc_NdefMap_SetCompletionRoutine(
                                    gpphLibContext->ndef_cntx.psNdefMap,
                                    cr_index,
                                    phLibNfc_Ndef_Write_Cb,
                                    (void *)gpphLibContext);

            }
            if(0 == psWr->length)
            {
                 /* Length of bytes to be written Zero- Erase the Tag  */
                RetVal = phFriNfc_NdefMap_EraseNdef(gpphLibContext->ndef_cntx.psNdefMap);
            }
            else
            {
                /*Write from beginning or current location*/
                NdefWriteType = PH_FRINFC_NDEFMAP_SEEK_BEGIN; 
                /*Call FRI Ndef Write*/
                RetVal=phFriNfc_NdefMap_WrNdef(gpphLibContext->ndef_cntx.psNdefMap,
                            gpphLibContext->ndef_cntx.psUpperNdefMsg->buffer,
                            (uint32_t*)&gpphLibContext->ndef_cntx.psUpperNdefMsg->length,
                            NdefWriteType);
            }
            if(NFCSTATUS_PENDING == RetVal)
            {
                gpphLibContext->CBInfo.pClientWrNdefCb = pNdefWrite_RspCb;
                gpphLibContext->CBInfo.pClientWrNdefCntx = pContext;
                gpphLibContext->status.GenCb_pending_status=TRUE;
                gpphLibContext->LibNfcState.next_state = eLibNfcHalStateTransaction;
            }
            else
            {
                RetVal = NFCSTATUS_FAILED;
            }
        }    
    }
    return RetVal;
}

/* Response callback for phLibNfc_Ndef_Write */
STATIC
void phLibNfc_Ndef_Write_Cb(void* Context,NFCSTATUS status)
{

    pphLibNfc_RspCb_t       pClientCb=NULL;
    phLibNfc_LibContext_t   *pLibNfc_Ctxt = (phLibNfc_LibContext_t *)Context;
    void                    *pUpperLayerContext=NULL;
    phHal_sRemoteDevInformation_t   *ps_rem_dev_info = NULL;

    if(pLibNfc_Ctxt != gpphLibContext)
    {   /*wrong context returned*/
        phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1);
    }
    else
    {
        if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state)
        {   /*shutdown called before completion of Ndef write allow
              shutdown to happen */
            phLibNfc_Pending_Shutdown();
            status = NFCSTATUS_SHUTDOWN;    
        }
        else if(eLibNfcHalStateRelease == gpphLibContext->LibNfcState.next_state)
        {
            status = NFCSTATUS_ABORTED;
        }
        else
        {
            gpphLibContext->status.GenCb_pending_status = FALSE;
            if (gpphLibContext->psBufferedAuth != NULL && gpphLibContext->ndef_cntx.psNdefMap != NULL) {
                gpphLibContext->psBufferedAuth->addr = (uint8_t)
                    gpphLibContext->ndef_cntx.psNdefMap->TLVStruct.NdefTLVBlock;
            }
            if(status == NFCSTATUS_FAILED )
            {
				status = NFCSTATUS_FAILED;
                gpphLibContext->LastTrancvSuccess = FALSE;
                /*During Ndef write operation tag was not present in RF
                field of reader*/
                ps_rem_dev_info = (phHal_sRemoteDevInformation_t *)
                                    gpphLibContext->Connected_handle;
               if ((phHal_eMifare_PICC == ps_rem_dev_info->RemDevType &&
                    0x08 == (ps_rem_dev_info->RemoteDevInfo.Iso14443A_Info.Sak & 0x08)))
                {

               
                    /* card type is mifare 1k/4k, then reconnect */
                    status = phHal4Nfc_Connect(gpphLibContext->psHwReference,  
                                ps_rem_dev_info,
                                (pphHal4Nfc_ConnectCallback_t)
                                phLibNfc_Reconnect_Mifare_Cb,
                                (void *)gpphLibContext);
                }
            }
            else if( status== NFCSTATUS_SUCCESS)
            {
                gpphLibContext->LastTrancvSuccess = TRUE;
                status = NFCSTATUS_SUCCESS;
                if(gpphLibContext->ndef_cntx.AppWrLength >
                                 gpphLibContext->ndef_cntx.NdefLength)
                {
                    status = NFCSTATUS_NOT_ENOUGH_MEMORY;
                }
                else
                {
                    pLibNfc_Ctxt->ndef_cntx.NdefActualSize = 
                                    pLibNfc_Ctxt->ndef_cntx.psUpperNdefMsg->length;
                }
            }           
            else
            {
                gpphLibContext->LastTrancvSuccess = FALSE;
				status = NFCSTATUS_FAILED;;
			}
        }
        phLibNfc_UpdateCurState(status,gpphLibContext);

        pClientCb = gpphLibContext->CBInfo.pClientWrNdefCb;
        pUpperLayerContext = gpphLibContext->CBInfo.pClientWrNdefCntx;

        gpphLibContext->CBInfo.pClientWrNdefCb = NULL;
        gpphLibContext->CBInfo.pClientWrNdefCntx = NULL;
        if(NFCSTATUS_PENDING !=status)
        {
            if (NULL != pClientCb)
            {
                /*Notify to upper layer status and No. of bytes
                actually written */
                pClientCb(pUpperLayerContext, status);          
            }
        }
    }
    return;
}


/**
* Initialize structures needed for the Ndef 
* related operation such as Check Ndef, read, write
* and Ndef foramt.only once allocation 
*/
void phLibNfc_Ndef_Init(void)
{
    if(gpphLibContext->psTransInfo==NULL)
    {
        /*Allocate memory for Transceiveinformation Structure*/
        gpphLibContext->psTransInfo = (phLibNfc_sTransceiveInfo_t *)
            phOsalNfc_GetMemory(sizeof(phLibNfc_sTransceiveInfo_t));
    }
    if(gpphLibContext->psTransInfo==NULL)
    {
        /*exception: Not enough memory*/
        phOsalNfc_RaiseException(phOsalNfc_e_NoMemory,1);
        
    }
    if(NULL == gpphLibContext->ndef_cntx.psNdefMap)
    {
        /*Allocate memory for NDEF Mapping Component Context Structure*/
        gpphLibContext->ndef_cntx.psNdefMap = (phFriNfc_NdefMap_t *)
                    phOsalNfc_GetMemory(sizeof(phFriNfc_NdefMap_t));
    }
    if(NULL != gpphLibContext->ndef_cntx.psNdefMap)
    {
        /*Allocation successful*/
        (void)memset(gpphLibContext->ndef_cntx.psNdefMap,0,sizeof(phFriNfc_NdefMap_t));
        gpphLibContext->ndef_cntx.NdefSendRecvLen = NDEF_SENDRCV_BUF_LEN;
        gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf =
                (uint8_t*) phOsalNfc_GetMemory(gpphLibContext->
                ndef_cntx.NdefSendRecvLen);

        if(NULL != gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf)
        {
            (void)memset(gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf,
                0,
                gpphLibContext->ndef_cntx.NdefSendRecvLen);

            gpphLibContext->psOverHalCtxt =(phFriNfc_OvrHal_t *)
                phOsalNfc_GetMemory(sizeof(phFriNfc_OvrHal_t));
        }
    }
    if(NULL == gpphLibContext->psOverHalCtxt)
    {   /*exception: Not enough memory*/
        phOsalNfc_RaiseException(phOsalNfc_e_NoMemory,1);
    }
    else
    {
        
        (void)memset(gpphLibContext->psOverHalCtxt,0,
            sizeof(phFriNfc_OvrHal_t));
        
        /* Initialize the Overlapped hal structure*/
        gpphLibContext->psOverHalCtxt->psHwReference =
             gpphLibContext->psHwReference;
        if(NULL == gpphLibContext->psDevInputParam )
        {
            gpphLibContext->psDevInputParam = (phHal_sDevInputParam_t *)
                phOsalNfc_GetMemory(sizeof(phHal_sDevInputParam_t));
        }
        gpphLibContext->ndef_cntx.is_ndef = CHK_NDEF_NOT_DONE;      
    }
    if(NULL == gpphLibContext->ndef_cntx.ndef_fmt)
    {
        /*Allocate memory for Ndef format structure*/
        gpphLibContext->ndef_cntx.ndef_fmt = (phFriNfc_sNdefSmtCrdFmt_t *)
                phOsalNfc_GetMemory(sizeof(phFriNfc_sNdefSmtCrdFmt_t));
    }
    if(NULL != gpphLibContext->ndef_cntx.ndef_fmt)
    {
        (void)memset(gpphLibContext->ndef_cntx.ndef_fmt,
                        0,
                        sizeof(phFriNfc_sNdefSmtCrdFmt_t));
    }
    else
    {
        /*exception: Not enough memory*/
        phOsalNfc_RaiseException(phOsalNfc_e_NoMemory,1);
    }
    return;
}
/**
* Free the allocated memory used for Ndef operations 
*/
void phLibNfc_Ndef_DeInit(void)
{
    /* If only allocated then only free the memory*/
    if(gpphLibContext->ndef_cntx.psNdefMap !=NULL)
    {
        if(gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf !=NULL)
        {
            phOsalNfc_FreeMemory(gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf);
            gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf=NULL;
        }
        phOsalNfc_FreeMemory(gpphLibContext->ndef_cntx.psNdefMap);
        gpphLibContext->ndef_cntx.psNdefMap =NULL;
    }

    if(NULL != gpphLibContext->ndef_cntx.ndef_fmt)
    {
        phOsalNfc_FreeMemory(gpphLibContext->ndef_cntx.ndef_fmt);
        gpphLibContext->ndef_cntx.ndef_fmt = NULL;
    }

    if(gpphLibContext->psOverHalCtxt !=NULL)
    {
        phOsalNfc_FreeMemory(gpphLibContext->psOverHalCtxt);
        gpphLibContext->psOverHalCtxt =NULL;
    }
    if(gpphLibContext->psDevInputParam !=NULL)
    {
        phOsalNfc_FreeMemory(gpphLibContext->psDevInputParam);
        gpphLibContext->psDevInputParam = NULL;
    }
    if(gpphLibContext->psTransInfo!=NULL)
    {
        phOsalNfc_FreeMemory(gpphLibContext->psTransInfo);
        gpphLibContext->psTransInfo= NULL;
    }
}


/**
* This function allows  the user to check whether a particular Remote Device
* is NDEF compliant or not
*/
NFCSTATUS phLibNfc_Ndef_CheckNdef(phLibNfc_Handle       hRemoteDevice,
                        pphLibNfc_ChkNdefRspCb_t        pCheckNdef_RspCb,
                        void*                           pContext)
{
    NFCSTATUS RetVal = NFCSTATUS_FAILED;
    
    
    if((NULL == gpphLibContext)|| 
        (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateShutdown))
    {
        /*Lib Nfc not initialized*/
        RetVal = NFCSTATUS_NOT_INITIALISED;
    }
    else if((NULL == pCheckNdef_RspCb)||
        (NULL==pContext)||
        (hRemoteDevice == 0))
    {
        /*parameter sent by upper layer are not valid */
        RetVal= NFCSTATUS_INVALID_PARAMETER;
    }
    else if(gpphLibContext->LibNfcState.next_state == eLibNfcHalStateShutdown)
    {
        RetVal = NFCSTATUS_SHUTDOWN;
    }    
    else if(0 == gpphLibContext->Connected_handle)
    {       
        RetVal=NFCSTATUS_TARGET_NOT_CONNECTED;        
    }
    else if(hRemoteDevice != gpphLibContext->Connected_handle)
    {       
        RetVal=NFCSTATUS_INVALID_HANDLE;        
    }
#ifdef LLCP_TRANSACT_CHANGES
    else if ((LLCP_STATE_RESET_INIT != gpphLibContext->llcp_cntx.sLlcpContext.state)
            && (LLCP_STATE_CHECKED != gpphLibContext->llcp_cntx.sLlcpContext.state))
    {
        RetVal= NFCSTATUS_BUSY;
    }
#endif /* #ifdef LLCP_TRANSACT_CHANGES */
    else
    {
        uint8_t     cr_index = 0;
        static uint16_t     data_cnt = 0;
        /* Allocate memory for the ndef related structure */       
        gpphLibContext->ndef_cntx.NdefSendRecvLen=300;
        gpphLibContext->ndef_cntx.eLast_Call = ChkNdef;
        
        /* Resets the component instance */
        RetVal = phFriNfc_NdefMap_Reset( gpphLibContext->ndef_cntx.psNdefMap,
                            gpphLibContext->psOverHalCtxt,
                            (phLibNfc_sRemoteDevInformation_t*)hRemoteDevice,
                            gpphLibContext->psDevInputParam,
                            gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf,
                            gpphLibContext->ndef_cntx.NdefSendRecvLen,
                            gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf,
                            &(gpphLibContext->ndef_cntx.NdefSendRecvLen),
                            &(data_cnt));


        for (cr_index = 0; cr_index < PH_FRINFC_NDEFMAP_CR; cr_index++)
        {
            /* Register the callback for the check ndef */
            RetVal = phFriNfc_NdefMap_SetCompletionRoutine(
                                gpphLibContext->ndef_cntx.psNdefMap,
                                cr_index,
                                phLibNfc_Ndef_CheckNdef_Cb,
                                (void *)gpphLibContext);
        }
        /*call below layer check Ndef function*/
        RetVal = phFriNfc_NdefMap_ChkNdef(gpphLibContext->ndef_cntx.psNdefMap);
        RetVal =PHNFCSTATUS(RetVal);

        if(RetVal== NFCSTATUS_PENDING)
        {
            RetVal = NFCSTATUS_PENDING;
        }        
        else if((RetVal == NFCSTATUS_FAILED) || (RetVal ==(PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
                    NFCSTATUS_INVALID_REMOTE_DEVICE))))
        {
			      RetVal= NFCSTATUS_FAILED;            
        }
        else
        {
            if((0x00 == gpphLibContext->ndef_cntx.Chk_Ndef_Timer_Id)||
              (PH_OSALNFC_INVALID_TIMER_ID == gpphLibContext->ndef_cntx.Chk_Ndef_Timer_Id))
	          {
		            gpphLibContext->ndef_cntx.Chk_Ndef_Timer_Id =
			          phOsalNfc_Timer_Create();      			
	          }	
	          if((0x00 == gpphLibContext->ndef_cntx.Chk_Ndef_Timer_Id)||
              (PH_OSALNFC_INVALID_TIMER_ID == gpphLibContext->ndef_cntx.Chk_Ndef_Timer_Id))
	          {
		            RetVal = NFCSTATUS_FAILED;
	          }
	          else
	          {
	              phOsalNfc_Timer_Start(gpphLibContext->ndef_cntx.Chk_Ndef_Timer_Id,
			          CHK_NDEF_TIMER_TIMEOUT,CheckNdef_timer_cb,NULL);	
                RetVal = NFCSTATUS_PENDING;
	          }            
        }
        if(RetVal== NFCSTATUS_PENDING)
        {
            gpphLibContext->CBInfo.pClientCkNdefCb = pCheckNdef_RspCb;
            gpphLibContext->CBInfo.pClientCkNdefCntx = pContext;
            gpphLibContext->status.GenCb_pending_status=TRUE;
            gpphLibContext->LibNfcState.next_state = eLibNfcHalStateTransaction;
        }
        
    }
    return RetVal;
}

/* Response callback for phLibNfc_Ndef_CheckNdef */
STATIC
void phLibNfc_Ndef_CheckNdef_Cb(void *pContext,NFCSTATUS status)
{
    phLibNfc_ChkNdef_Info_t    Ndef_Info;
    NFCSTATUS RetStatus = NFCSTATUS_SUCCESS;
    pphLibNfc_ChkNdefRspCb_t       pClientCb=NULL;
    phLibNfc_LibContext_t           *pLibNfc_Ctxt = 
                                    (phLibNfc_LibContext_t *)pContext;
    void                    *pUpperLayerContext=NULL;
    phHal_sRemoteDevInformation_t   *ps_rem_dev_info = NULL;                                    

    Ndef_Info.ActualNdefMsgLength = 0;
    Ndef_Info.MaxNdefMsgLength = 0;
    Ndef_Info.NdefCardState = PHLIBNFC_NDEF_CARD_INVALID;
    if(pLibNfc_Ctxt != gpphLibContext)
    {    /*wrong context returned from below layer*/
        phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1);
    }
    else
    {
        ps_rem_dev_info = (phHal_sRemoteDevInformation_t *)
                                    gpphLibContext->Connected_handle;
        if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state)
        {   /*shutdown called before completion of check Ndef, allow
              shutdown to happen */
            phLibNfc_Pending_Shutdown();
            RetStatus = NFCSTATUS_SHUTDOWN;    
        }
        else if(eLibNfcHalStateRelease == gpphLibContext->LibNfcState.next_state)
        {
            RetStatus = NFCSTATUS_ABORTED;          
        }
        else
        {
            if(status == NFCSTATUS_SUCCESS)
            {
                /*Tag is Ndef tag*/
                gpphLibContext->ndef_cntx.is_ndef = TRUE;
                (void)phFriNfc_NdefMap_GetContainerSize(
                                pLibNfc_Ctxt->ndef_cntx.psNdefMap,
                                &(pLibNfc_Ctxt->ndef_cntx.NdefLength),
                                &(pLibNfc_Ctxt->ndef_cntx.NdefActualSize));
                /*Get the data size support by particular ndef card */
                Ndef_Info.ActualNdefMsgLength = pLibNfc_Ctxt->ndef_cntx.NdefActualSize;
                Ndef_Info.MaxNdefMsgLength = pLibNfc_Ctxt->ndef_cntx.NdefLength;
                gpphLibContext->LastTrancvSuccess = TRUE;
                RetStatus =NFCSTATUS_SUCCESS;
            }
            else if (PHNFCSTATUS(status) != NFCSTATUS_MORE_INFORMATION )
            {
                /*Ndef check Failed.Issue a PresenceChk to ascertain if tag is
                  still in the field*/
                RetStatus = phHal4Nfc_PresenceCheck(
                                    gpphLibContext->psHwReference,
                                    phLibNfc_Ndef_ChkNdef_Pchk_Cb,
                                    (void *)gpphLibContext
                                    );
            }             
            else 
            { 
				RetStatus = NFCSTATUS_FAILED; 
                gpphLibContext->LastTrancvSuccess = FALSE;
                gpphLibContext->ndef_cntx.is_ndef = FALSE;
                               
                if ((phHal_eMifare_PICC == ps_rem_dev_info->RemDevType) && 
                    (0x08 == (ps_rem_dev_info->RemoteDevInfo.Iso14443A_Info.Sak & 0x08)))
                {

                    /* card type is mifare 1k/4k, then reconnect */
                    RetStatus = phHal4Nfc_Connect(gpphLibContext->psHwReference,  
                                ps_rem_dev_info,
                                (pphHal4Nfc_ConnectCallback_t)
                                phLibNfc_Reconnect_Mifare_Cb,
                                (void *)gpphLibContext);
                }   
                else
                {
                   if((phHal_eJewel_PICC == ps_rem_dev_info->RemDevType)
                       &&(TOPAZ_NDEF_BITMASK & 
                          ps_rem_dev_info->RemoteDevInfo.Jewel_Info.HeaderRom0))
                    {                        
                        gpphLibContext->ndef_cntx.is_ndef = TRUE;
                        RetStatus = phFriNfc_NdefMap_GetContainerSize(
                                        pLibNfc_Ctxt->ndef_cntx.psNdefMap,
                                        &(pLibNfc_Ctxt->ndef_cntx.NdefLength),
                                        &(pLibNfc_Ctxt->ndef_cntx.NdefActualSize));
                        /*Get the data size support by particular ndef card */
                        Ndef_Info.ActualNdefMsgLength = 
                            pLibNfc_Ctxt->ndef_cntx.NdefActualSize;
                        Ndef_Info.MaxNdefMsgLength 
                            = pLibNfc_Ctxt->ndef_cntx.NdefLength
                            = (TOPAZ_LEN_BITMASK & 
                            ps_rem_dev_info->RemoteDevInfo.Jewel_Info.HeaderRom0?
                            TOPAZ_DYNAMIC_LEN:TOPAZ_STATIC_CARD_LEN);   
                        RetStatus = NFCSTATUS_SUCCESS;
                    }
                }                         
            }
            gpphLibContext->LibNfcState.cur_state=eLibNfcHalStateConnect;
        }
        gpphLibContext->status.GenCb_pending_status = FALSE;
        /* Update the current state */
        phLibNfc_UpdateCurState(RetStatus,gpphLibContext);
        if(NFCSTATUS_PENDING != RetStatus)
        {
            if(((ps_rem_dev_info->RemDevType == phHal_eMifare_PICC) 
                && (ps_rem_dev_info->RemoteDevInfo.Iso14443A_Info.Sak != 0)&&
               ((NULL == gpphLibContext->psBufferedAuth)
                ||(phHal_eMifareAuthentA == gpphLibContext->psBufferedAuth->cmd.MfCmd)))
               )
            {
                if(NULL != gpphLibContext->psBufferedAuth)
                {
                    if(NULL != gpphLibContext->psBufferedAuth->sRecvData.buffer)
                    {
                        phOsalNfc_FreeMemory(
                            gpphLibContext->psBufferedAuth->sRecvData.buffer);
                    }
                    if(NULL != gpphLibContext->psBufferedAuth->sSendData.buffer)
                    {
                        phOsalNfc_FreeMemory(
                            gpphLibContext->psBufferedAuth->sSendData.buffer);
                    }
                    phOsalNfc_FreeMemory(gpphLibContext->psBufferedAuth);
                }
                gpphLibContext->psBufferedAuth
                    =(phLibNfc_sTransceiveInfo_t *) 
                    phOsalNfc_GetMemory(sizeof(phLibNfc_sTransceiveInfo_t));                
                gpphLibContext->psBufferedAuth->addr = 
                (uint8_t)gpphLibContext->ndef_cntx.psNdefMap
                ->StdMifareContainer.currentBlock;
                gpphLibContext->psBufferedAuth->cmd.MfCmd = phHal_eMifareRead16;
                gpphLibContext->psBufferedAuth->sSendData.length
                    = 0;            
                gpphLibContext->psBufferedAuth->sRecvData.length
                    = MIFARE_STD_BLOCK_SIZE;                      
                gpphLibContext->psBufferedAuth->sRecvData.buffer
                    = (uint8_t *)phOsalNfc_GetMemory(MIFARE_STD_BLOCK_SIZE);
                gpphLibContext->psBufferedAuth->sSendData.buffer
                    = (uint8_t *)phOsalNfc_GetMemory(MIFARE_STD_BLOCK_SIZE); 
            }
            pClientCb = gpphLibContext->CBInfo.pClientCkNdefCb;
            pUpperLayerContext = gpphLibContext->CBInfo.pClientCkNdefCntx;
            gpphLibContext->CBInfo.pClientCkNdefCb = NULL;
            gpphLibContext->CBInfo.pClientCkNdefCntx = NULL;
            if(NULL != pClientCb)
            {
                if (!RetStatus)
                {
                    switch (pLibNfc_Ctxt->ndef_cntx.psNdefMap->CardState)
                    {
                        case PH_NDEFMAP_CARD_STATE_INITIALIZED:
                        {
                            Ndef_Info.NdefCardState = 
                                            PHLIBNFC_NDEF_CARD_INITIALISED;
                            break;
                        }

                        case PH_NDEFMAP_CARD_STATE_READ_ONLY:
                        {
                            Ndef_Info.NdefCardState = 
                                            PHLIBNFC_NDEF_CARD_READ_ONLY;
                            break;
                        }

                        case PH_NDEFMAP_CARD_STATE_READ_WRITE:
                        {
                            Ndef_Info.NdefCardState = 
                                            PHLIBNFC_NDEF_CARD_READ_WRITE;
                            break;
                        }

                        default:
                        {
                            Ndef_Info.NdefCardState = 
                                            PHLIBNFC_NDEF_CARD_INVALID;
                            break;
                        }
                    }
                }
                /* call the upper check ndef callback */
                pClientCb(pUpperLayerContext,Ndef_Info,RetStatus);
            }
        }
    }
    return;
}

/*Callback for Presence check call from Chk Ndef*/
STATIC void phLibNfc_Ndef_ChkNdef_Pchk_Cb(void   *pContext,
                                NFCSTATUS  status
                                )
{
    phLibNfc_ChkNdef_Info_t    Ndef_Info = {0,0,0};
    NFCSTATUS RetStatus = NFCSTATUS_SUCCESS;
    pphLibNfc_ChkNdefRspCb_t       pClientCb=NULL;
    phLibNfc_LibContext_t           *pLibNfc_Ctxt = 
                                    (phLibNfc_LibContext_t *)pContext;
    void                    *pUpperLayerContext=NULL;
    phHal_sRemoteDevInformation_t   *ps_rem_dev_info = NULL;  
    if(NFCSTATUS_SUCCESS == status)
    {
        RetStatus = NFCSTATUS_FAILED;
        gpphLibContext->ndef_cntx.is_ndef = FALSE;
    }
    else
    {
        RetStatus = NFCSTATUS_TARGET_LOST;
    }    
    if(pLibNfc_Ctxt != gpphLibContext)
    {    /*wrong context returned from below layer*/
        phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1);
    }
    else
    {
        ps_rem_dev_info = (phHal_sRemoteDevInformation_t *)
                                    gpphLibContext->Connected_handle;
        if(((ps_rem_dev_info->RemDevType == phHal_eMifare_PICC) 
            && (ps_rem_dev_info->RemoteDevInfo.Iso14443A_Info.Sak != 0)&&
            ((NULL == gpphLibContext->psBufferedAuth)
            ||(phHal_eMifareAuthentA == gpphLibContext->psBufferedAuth->cmd.MfCmd)))
            )
        {
            if(NULL != gpphLibContext->psBufferedAuth)
            {
                if(NULL != gpphLibContext->psBufferedAuth->sRecvData.buffer)
                {
                    phOsalNfc_FreeMemory(
                        gpphLibContext->psBufferedAuth->sRecvData.buffer);
                }
                if(NULL != gpphLibContext->psBufferedAuth->sSendData.buffer)
                {
                    phOsalNfc_FreeMemory(
                        gpphLibContext->psBufferedAuth->sSendData.buffer);
                }
                phOsalNfc_FreeMemory(gpphLibContext->psBufferedAuth);
            }
            gpphLibContext->psBufferedAuth
                =(phLibNfc_sTransceiveInfo_t *) 
                phOsalNfc_GetMemory(sizeof(phLibNfc_sTransceiveInfo_t));                
            gpphLibContext->psBufferedAuth->addr = 
            (uint8_t)gpphLibContext->ndef_cntx.psNdefMap
            ->StdMifareContainer.currentBlock;
            gpphLibContext->psBufferedAuth->cmd.MfCmd = phHal_eMifareRead16;
            gpphLibContext->psBufferedAuth->sSendData.length
                = 0;            
            gpphLibContext->psBufferedAuth->sRecvData.length
                = MIFARE_STD_BLOCK_SIZE;                      
            gpphLibContext->psBufferedAuth->sRecvData.buffer
                = (uint8_t *)phOsalNfc_GetMemory(MIFARE_STD_BLOCK_SIZE);
            gpphLibContext->psBufferedAuth->sSendData.buffer
                = (uint8_t *)phOsalNfc_GetMemory(MIFARE_STD_BLOCK_SIZE); 
        }
        pClientCb = gpphLibContext->CBInfo.pClientCkNdefCb;
        pUpperLayerContext = gpphLibContext->CBInfo.pClientCkNdefCntx;
        gpphLibContext->CBInfo.pClientCkNdefCb = NULL;
        gpphLibContext->CBInfo.pClientCkNdefCntx = NULL;
        if(NULL != pClientCb)
        {
            Ndef_Info.NdefCardState = PHLIBNFC_NDEF_CARD_INVALID;
            /* call the upper check ndef callback */
            pClientCb(pUpperLayerContext,Ndef_Info,RetStatus);
        }
    }
    return;
}
/* Check Ndef Timer Callback*/
STATIC void CheckNdef_timer_cb(uint32_t timer_id, void *pContext)
{
	PHNFC_UNUSED_VARIABLE(pContext);
   phOsalNfc_Timer_Stop(timer_id);
	phOsalNfc_Timer_Delete(gpphLibContext->ndef_cntx.Chk_Ndef_Timer_Id);
	gpphLibContext->ndef_cntx.Chk_Ndef_Timer_Id = 0x00;
	phLibNfc_Ndef_CheckNdef_Cb((void *)gpphLibContext,NFCSTATUS_MORE_INFORMATION);
}

void phLibNfc_Reconnect_Mifare_Cb (
                    void                            *pContext,
                    phHal_sRemoteDevInformation_t   *psRemoteDevInfo,
                    NFCSTATUS                       status)
{
    phLibNfc_ChkNdef_Info_t     Ndef_Info;      
    phLibNfc_LibContext_t       *pLibNfc_Ctxt = 
                                (phLibNfc_LibContext_t *)pContext;
    void                        *pUpperLayerContext = NULL;
    switch(gpphLibContext->ndef_cntx.eLast_Call)
    {
        case ChkNdef:
        {
            pphLibNfc_ChkNdefRspCb_t    pClientCb=NULL;
            pClientCb = pLibNfc_Ctxt->CBInfo.pClientCkNdefCb;
            pUpperLayerContext = pLibNfc_Ctxt->CBInfo.pClientCkNdefCntx;
            pLibNfc_Ctxt->CBInfo.pClientCkNdefCb = NULL;
            pLibNfc_Ctxt->CBInfo.pClientCkNdefCntx = NULL;
            if (NULL != pClientCb)
            {
                status = (NFCSTATUS_SUCCESS == status?
                        NFCSTATUS_FAILED:NFCSTATUS_TARGET_LOST);
                Ndef_Info.ActualNdefMsgLength = 0;
                Ndef_Info.MaxNdefMsgLength = 0;
                /* call the upper check ndef callback */
                pClientCb(pUpperLayerContext,Ndef_Info,status);
            }
        }
        break;
        case NdefRd:
        {
            pphLibNfc_RspCb_t       pClientCb = pLibNfc_Ctxt->CBInfo.pClientRdNdefCb; 
            pUpperLayerContext = pLibNfc_Ctxt->CBInfo.pClientRdNdefCntx;
            pLibNfc_Ctxt->CBInfo.pClientRdNdefCb = NULL;
            pLibNfc_Ctxt->CBInfo.pClientRdNdefCntx = NULL;
            if (NULL != pClientCb)
            {
                status = (NFCSTATUS_SUCCESS == status?
                        NFCSTATUS_FAILED:NFCSTATUS_TARGET_LOST);            
                /* call the upper ndef read callback */
                pClientCb(pUpperLayerContext,status);
            }
        }
        break;
        case NdefWr:
        {
            pphLibNfc_RspCb_t       pClientCb =  pLibNfc_Ctxt->CBInfo.pClientWrNdefCb;        
            pUpperLayerContext = pLibNfc_Ctxt->CBInfo.pClientWrNdefCntx;
            pLibNfc_Ctxt->CBInfo.pClientWrNdefCb = NULL;
            pLibNfc_Ctxt->CBInfo.pClientWrNdefCntx = NULL;
            if (NULL != pClientCb)
            {
                status = (NFCSTATUS_SUCCESS == status?
                        NFCSTATUS_FAILED:NFCSTATUS_TARGET_LOST);              
                /* call the upper ndef write callback */
                pClientCb(pUpperLayerContext,status);
            }
        }
        break;
        case NdefFmt:
#ifdef LIBNFC_READONLY_NDEF
        case NdefReadOnly:
#endif /* #ifdef LIBNFC_READONLY_NDEF */
        {
            pphLibNfc_RspCb_t       pClientCb =
                           pLibNfc_Ctxt->ndef_cntx.pClientNdefFmtCb;  
            pUpperLayerContext= pLibNfc_Ctxt->ndef_cntx.pClientNdefFmtCntx;
            pLibNfc_Ctxt->ndef_cntx.pClientNdefFmtCb = NULL;
            pLibNfc_Ctxt->ndef_cntx.pClientNdefFmtCntx = NULL;
            if (NULL != pClientCb)
            {
                status = (NFCSTATUS_SUCCESS == status?
                        NFCSTATUS_FAILED:NFCSTATUS_TARGET_LOST);            
                /* call the upper ndef format callback */
                pClientCb(pUpperLayerContext,status);
            }
        }
        break;
        case RawTrans:
        {
            phNfc_sData_t trans_resp;           
            pphLibNfc_TransceiveCallback_t pClientCb =
                           pLibNfc_Ctxt->CBInfo.pClientTransceiveCb;
            trans_resp.length = 0;
            pUpperLayerContext = pLibNfc_Ctxt->CBInfo.pClientTranseCntx;
            pLibNfc_Ctxt->CBInfo.pClientTranseCntx= NULL;
            pLibNfc_Ctxt->CBInfo.pClientTransceiveCb= NULL;
            if (NULL != pClientCb)
            {
                status = (NFCSTATUS_SUCCESS == status?
                        NFCSTATUS_FAILED:NFCSTATUS_TARGET_LOST);             
                /* call the upper transceive callback */
                pClientCb(pUpperLayerContext,
                        (phLibNfc_Handle)psRemoteDevInfo,
                        & trans_resp,
                        status);                
            }
        }
        break;
        default:
        {
        }
        break;
    }
    
}
/**
* Target format to make it NDEF compliant
*/
NFCSTATUS phLibNfc_RemoteDev_FormatNdef(phLibNfc_Handle         hRemoteDevice,
                                        phNfc_sData_t*          pScrtKey,
                                        pphLibNfc_RspCb_t       pNdefformat_RspCb,
                                        void*                   pContext
                                        )
{
    NFCSTATUS RetVal = NFCSTATUS_FAILED;
    
    static uint8_t       mif_std_key[6] ={0},
                         Index = 0;
    if((NULL == gpphLibContext)
        ||(gpphLibContext->LibNfcState.cur_state
                            == eLibNfcHalStateShutdown))
    {
        /*Lib Nfc not initialized*/
        RetVal = NFCSTATUS_NOT_INITIALISED;
    }    
    else if((NULL == pContext) 
        || (NULL == pNdefformat_RspCb)       
        ||(NULL == pScrtKey)
        ||(0 == hRemoteDevice))
    {
        RetVal= NFCSTATUS_INVALID_PARAMETER;
    }
    else if(gpphLibContext->LibNfcState.next_state
                            == eLibNfcHalStateShutdown)
    {
        RetVal= NFCSTATUS_SHUTDOWN;
    }
    else if(0 == gpphLibContext->Connected_handle)
    {       
        RetVal=NFCSTATUS_TARGET_NOT_CONNECTED;        
    }
    else if(hRemoteDevice != gpphLibContext->Connected_handle)
    {       
        RetVal=NFCSTATUS_INVALID_HANDLE;        
    }
    else if((TRUE == gpphLibContext->status.GenCb_pending_status)||
        (NULL != gpphLibContext->ndef_cntx.pClientNdefFmtCb)
        ||(gpphLibContext->ndef_cntx.is_ndef == TRUE))
    {
        /*Previous Callback is Pending*/
        RetVal = NFCSTATUS_REJECTED;
        PHDBG_INFO("LIbNfc:Previous Callback is Pending");
    }
#ifdef LLCP_TRANSACT_CHANGES
    else if ((LLCP_STATE_RESET_INIT != gpphLibContext->llcp_cntx.sLlcpContext.state)
            && (LLCP_STATE_CHECKED != gpphLibContext->llcp_cntx.sLlcpContext.state))
    {
        RetVal= NFCSTATUS_BUSY;
    }
#endif /* #ifdef LLCP_TRANSACT_CHANGES */
    else
    {
        uint8_t   fun_id;       
        gpphLibContext->ndef_cntx.eLast_Call = NdefFmt;        
        gpphLibContext->ndef_cntx.NdefSendRecvLen = NDEF_SENDRCV_BUF_LEN;
    
        /* Call ndef format reset, this will initialize the ndef
        format structure, and appropriate values are filled */
        RetVal = phFriNfc_NdefSmtCrd_Reset(gpphLibContext->ndef_cntx.ndef_fmt,
                            gpphLibContext->psOverHalCtxt,
                            (phHal_sRemoteDevInformation_t*)hRemoteDevice,
                            gpphLibContext->psDevInputParam,
                            gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf,
                            &(gpphLibContext->ndef_cntx.NdefSendRecvLen));
        for(fun_id = 0; fun_id < PH_FRINFC_SMTCRDFMT_CR; fun_id++)
        {
            /* Register for all the callbacks */
            RetVal = phFriNfc_NdefSmtCrd_SetCR(gpphLibContext->ndef_cntx.ndef_fmt,
                        fun_id,
                        phLibNfc_Ndef_format_Cb,
                        gpphLibContext);
        }
        /* mif_std_key is required to format the mifare 1k/4k card */
        for (Index =0 ;Index < (pScrtKey->length); Index++ )
        {
            mif_std_key[Index] = *(pScrtKey->buffer++);
        }
        /* Start smart card formatting function   */
        RetVal = phFriNfc_NdefSmtCrd_Format(gpphLibContext->ndef_cntx.ndef_fmt,
                                        mif_std_key);
		RetVal = PHNFCSTATUS(RetVal);
        if(RetVal== NFCSTATUS_PENDING)
        {
            gpphLibContext->ndef_cntx.pClientNdefFmtCb = pNdefformat_RspCb;
            gpphLibContext->ndef_cntx.pClientNdefFmtCntx = pContext;
            gpphLibContext->status.GenCb_pending_status=TRUE;
            gpphLibContext->LibNfcState.next_state = eLibNfcHalStateTransaction;
        }
        else
        {
            RetVal = NFCSTATUS_FAILED;
        }       
    }
    return RetVal;
}

#ifdef LIBNFC_READONLY_NDEF

NFCSTATUS
phLibNfc_ConvertToReadOnlyNdef (
    phLibNfc_Handle         hRemoteDevice,
    phNfc_sData_t*          pScrtKey,
    pphLibNfc_RspCb_t       pNdefReadOnly_RspCb,
    void*                   pContext
    )
{
    NFCSTATUS           ret_val = NFCSTATUS_FAILED;
    static uint8_t      mif_std_key[6] ={0},
                        Index = 0;

    if ((NULL == gpphLibContext)
        || (gpphLibContext->LibNfcState.cur_state
                            == eLibNfcHalStateShutdown))
    {
        /* LibNfc not initialized */
        ret_val = NFCSTATUS_NOT_INITIALISED;
    }
    else if ((NULL == pContext)
        || (NULL == pNdefReadOnly_RspCb)
        || (0 == hRemoteDevice))
    {
        ret_val = NFCSTATUS_INVALID_PARAMETER;
    }
    else if (gpphLibContext->LibNfcState.next_state
            == eLibNfcHalStateShutdown)
    {
        ret_val = NFCSTATUS_SHUTDOWN;
    }
    else if (0 == gpphLibContext->Connected_handle)
    {
        ret_val = NFCSTATUS_TARGET_NOT_CONNECTED;
    }
    else if (hRemoteDevice != gpphLibContext->Connected_handle)
    {
        ret_val = NFCSTATUS_INVALID_HANDLE;
    }
    else if ((TRUE == gpphLibContext->status.GenCb_pending_status)
        || (NULL != gpphLibContext->ndef_cntx.pClientNdefFmtCb)
        || (FALSE == gpphLibContext->ndef_cntx.is_ndef))
    {
        /* Previous Callback is Pending */
        ret_val = NFCSTATUS_REJECTED;
        PHDBG_INFO("LIbNfc:Previous Callback is Pending");
    }
    else
    {
        gpphLibContext->ndef_cntx.eLast_Call = NdefReadOnly;

        if(eLibNfcHalStatePresenceChk != gpphLibContext->LibNfcState.next_state)
        {
            phHal_sRemoteDevInformation_t           *ps_rem_dev_info = 
                                                (phHal_sRemoteDevInformation_t *)hRemoteDevice;
            uint8_t                                 fun_id;

            switch (ps_rem_dev_info->RemDevType)
            {
                case phHal_eMifare_PICC:
                case phHal_eISO14443_A_PICC:
                {
                    if ((phHal_eMifare_PICC == ps_rem_dev_info->RemDevType)
                        && (0x00 != ps_rem_dev_info->RemoteDevInfo.Iso14443A_Info.Sak))
                    {
                        for (fun_id = 0; fun_id < PH_FRINFC_NDEFMAP_CR; fun_id++)
                        {
                            /* Register the callback for the check ndef */
                            ret_val = phFriNfc_NdefMap_SetCompletionRoutine (
                                      gpphLibContext->ndef_cntx.psNdefMap,
                                      fun_id, phLibNfc_Ndef_ReadOnly_Cb,
                                      (void *)gpphLibContext);
                        }

                        /* Start mifare NFC read only function   */
                        /* mif_std_key is required to format the mifare 1k/4k card */
                        if(pScrtKey != NULL && pScrtKey->length == MIFARE_STD_KEY_LEN)
                        {
                            for (Index =0 ;Index < (pScrtKey->length); Index++ )
                            {
                                mif_std_key[Index] = *(pScrtKey->buffer++);
                            }

                            ret_val = phFriNfc_MifareStdMap_ConvertToReadOnly (
                                      gpphLibContext->ndef_cntx.psNdefMap, mif_std_key);
                            ret_val = PHNFCSTATUS(ret_val);
                        }
                    }
                    else
                    {
                        gpphLibContext->ndef_cntx.NdefSendRecvLen = NDEF_SENDRCV_BUF_LEN;

                        /* Call ndef format reset, this will initialize the ndef
                        format structure, and appropriate values are filled */
                        ret_val = phFriNfc_NdefSmtCrd_Reset (gpphLibContext->ndef_cntx.ndef_fmt,
                                                gpphLibContext->psOverHalCtxt,
                                                (phHal_sRemoteDevInformation_t*)hRemoteDevice,
                                                gpphLibContext->psDevInputParam,
                                                gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf,
                                                &(gpphLibContext->ndef_cntx.NdefSendRecvLen));

                        for(fun_id = 0; fun_id < PH_FRINFC_SMTCRDFMT_CR; fun_id++)
                        {
                            /* Register for all the callbacks */
                            ret_val = phFriNfc_NdefSmtCrd_SetCR (gpphLibContext->ndef_cntx.ndef_fmt,
                                                                fun_id, phLibNfc_Ndef_ReadOnly_Cb,
                                                                gpphLibContext);
                        }

                        /* Start smart card formatting function   */
                        ret_val = phFriNfc_NdefSmtCrd_ConvertToReadOnly (
                                                        gpphLibContext->ndef_cntx.ndef_fmt);
                        ret_val = PHNFCSTATUS(ret_val);
                    }
                    break;
                }

                case phHal_eJewel_PICC:
                case phHal_eISO15693_PICC:
                {
// MC: Got the feedback this was #if 0'd because it was resetting the lock bits
// read in check NDEF, and these should not be reset here already.
#if 0
                    static uint16_t     data_cnt = 0;

                    /* Resets the component instance */
                    ret_val = phFriNfc_NdefMap_Reset (gpphLibContext->ndef_cntx.psNdefMap,
                                        gpphLibContext->psOverHalCtxt,
                                        (phLibNfc_sRemoteDevInformation_t*)hRemoteDevice,
                                        gpphLibContext->psDevInputParam,
                                        gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf,
                                        gpphLibContext->ndef_cntx.NdefSendRecvLen,
                                        gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf,
                                        &(gpphLibContext->ndef_cntx.NdefSendRecvLen),
                                        &(data_cnt));
#endif /* #if 0 */


                    for (fun_id = 0; fun_id < PH_FRINFC_NDEFMAP_CR; fun_id++)
                    {
                        /* Register the callback for the check ndef */
                        ret_val = phFriNfc_NdefMap_SetCompletionRoutine (
                                            gpphLibContext->ndef_cntx.psNdefMap,
                                            fun_id, phLibNfc_Ndef_ReadOnly_Cb,
                                            (void *)gpphLibContext);
                    }

                    /* call below layer check Ndef function */
                    ret_val = phFriNfc_NdefMap_ConvertToReadOnly (
                                            gpphLibContext->ndef_cntx.psNdefMap);
                    ret_val = PHNFCSTATUS(ret_val);
                    break;
                }

                default:
                {
                    /* Tag not supported */
                    ret_val = NFCSTATUS_REJECTED;
                    break;
                }
            }            
        }
        else
        {
             gpphLibContext->ndef_cntx.pClientNdefFmtCb= NULL;
             ret_val = NFCSTATUS_PENDING;
        }

        if (NFCSTATUS_PENDING == ret_val)
        {
            gpphLibContext->ndef_cntx.pClientNdefFmtCb = pNdefReadOnly_RspCb;
            gpphLibContext->ndef_cntx.pClientNdefFmtCntx = pContext;

            gpphLibContext->status.GenCb_pending_status = TRUE;
            gpphLibContext->LibNfcState.next_state = eLibNfcHalStateTransaction;
        }
        else
        {
            ret_val = NFCSTATUS_FAILED;
        }
    }
    return ret_val;
}

#endif /* #ifdef LIBNFC_READONLY_NDEF */

/**
* Response callback for NDEF format.
*/
STATIC
void phLibNfc_Ndef_format_Cb(void *Context,NFCSTATUS  status)
{
    NFCSTATUS RetStatus = NFCSTATUS_SUCCESS;
    pphLibNfc_RspCb_t       pClientCb=NULL;
    phLibNfc_LibContext_t   *pLibNfc_Ctxt = (phLibNfc_LibContext_t *)Context;
    void                    *pUpperLayerContext=NULL;
    phHal_sRemoteDevInformation_t   *ps_rem_dev_info = NULL;
    if(pLibNfc_Ctxt != gpphLibContext)
    {   /*wrong context returned*/
        phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1);
    }
    else
    {
        if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state)
        {
            /*shutdown is pending so issue shutdown*/
            phLibNfc_Pending_Shutdown();
            RetStatus = NFCSTATUS_SHUTDOWN;    
        }
        else if(eLibNfcHalStateRelease == gpphLibContext->LibNfcState.next_state)
        {
            RetStatus = NFCSTATUS_ABORTED;          
        }
        else
        {
            gpphLibContext->status.GenCb_pending_status = FALSE;
            if(NFCSTATUS_SUCCESS == status)
            {
                RetStatus = NFCSTATUS_SUCCESS;
            }            
            else if(PHNFCSTATUS(status)==NFCSTATUS_FAILED)
            {
                RetStatus = NFCSTATUS_FAILED;
                ps_rem_dev_info = (phHal_sRemoteDevInformation_t *)
                                    gpphLibContext->Connected_handle;
                if ((phHal_eMifare_PICC == ps_rem_dev_info->RemDevType) && 
                    (0x08 == (ps_rem_dev_info->RemoteDevInfo.Iso14443A_Info.Sak & 0x08)))
                {

                    /* card type is mifare 1k/4k, then reconnect */
                    RetStatus = phHal4Nfc_Connect(gpphLibContext->psHwReference,  
                                (phHal_sRemoteDevInformation_t *)
                                gpphLibContext->Connected_handle,
                                (pphHal4Nfc_ConnectCallback_t)
                                phLibNfc_Reconnect_Mifare_Cb,
                                (void *)gpphLibContext);
                }
            }
			else
            {
                /*Target was removed during transaction*/
                RetStatus = NFCSTATUS_FAILED;
            }
            gpphLibContext->LibNfcState.cur_state =eLibNfcHalStateConnect;
        }
        phLibNfc_UpdateCurState(status,gpphLibContext);
        
        pClientCb = gpphLibContext->ndef_cntx.pClientNdefFmtCb;
        pUpperLayerContext= gpphLibContext->ndef_cntx.pClientNdefFmtCntx;
        gpphLibContext->ndef_cntx.pClientNdefFmtCb = NULL;
        gpphLibContext->ndef_cntx.pClientNdefFmtCntx = NULL;
        if(NFCSTATUS_PENDING != RetStatus)
        {
            if (NULL != pClientCb)
            {
                /* Call the tag format upper layer callback */
                pClientCb(pUpperLayerContext,RetStatus);
            }
        }
    }
    return;
}

#ifdef LIBNFC_READONLY_NDEF
STATIC
void
phLibNfc_Ndef_ReadOnly_Cb (
    void        *p_context,
    NFCSTATUS   status)
{
    NFCSTATUS                       ret_status = NFCSTATUS_SUCCESS;
    pphLibNfc_RspCb_t               p_client_cb = NULL;
    phLibNfc_LibContext_t           *pLibNfc_Ctxt = (phLibNfc_LibContext_t *)p_context;
    void                            *p_upper_layer_ctxt = NULL;

    if(pLibNfc_Ctxt != gpphLibContext)
    {
        /*wrong context returned*/
        phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1);
    }
    else
    {
        if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state)
        {
            /*shutdown is pending so issue shutdown*/
            phLibNfc_Pending_Shutdown();
            ret_status = NFCSTATUS_SHUTDOWN;
        }
        else if(eLibNfcHalStateRelease == gpphLibContext->LibNfcState.next_state)
        {
            ret_status = NFCSTATUS_ABORTED;
        }
        else
        {
            gpphLibContext->status.GenCb_pending_status = FALSE;
            if(NFCSTATUS_SUCCESS == status)
            {
                gpphLibContext->ndef_cntx.psNdefMap->CardState = 
                                                PH_NDEFMAP_CARD_STATE_READ_ONLY;
                ret_status = NFCSTATUS_SUCCESS;
            }
            else
            {
                ret_status = NFCSTATUS_FAILED;
            }
            gpphLibContext->LibNfcState.cur_state =eLibNfcHalStateConnect;
        }

        phLibNfc_UpdateCurState(status, gpphLibContext);

        p_client_cb = gpphLibContext->ndef_cntx.pClientNdefFmtCb;
        p_upper_layer_ctxt = gpphLibContext->ndef_cntx.pClientNdefFmtCntx;
        gpphLibContext->ndef_cntx.pClientNdefFmtCb = NULL;
        gpphLibContext->ndef_cntx.pClientNdefFmtCntx = NULL;
        if(NFCSTATUS_PENDING != ret_status)
        {
            if (NULL != p_client_cb)
            {
                /* Call the tag format upper layer callback */
                p_client_cb (p_upper_layer_ctxt, ret_status);
            }
        }
    }
}
#endif /* #ifdef LIBNFC_READONLY_NDEF */

STATIC
void phLibNfc_Ndef_SrchNdefCnt_Cb(void *context, NFCSTATUS status)
{
    static NFCSTATUS RegPrSt=FALSE;
    uint8_t RegStatus=0;
    NFCSTATUS RetVal = NFCSTATUS_SUCCESS ;  
    uint32_t Index=0;   
    
    
	  PHNFC_UNUSED_VARIABLE(context);
    if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state)
    {   /*shutdown called before completion of Ndef read allow
              shutdown to happen */
        phLibNfc_Pending_Shutdown();
        RetVal = NFCSTATUS_SHUTDOWN;    
    }
    else if(eLibNfcHalStateRelease == gpphLibContext->LibNfcState.next_state)
    {
        RetVal = NFCSTATUS_ABORTED;
    }
    else if(NFCSTATUS_SUCCESS != status)
    {
        RetVal = status;
    }
    else
    {
     /* This conditional branch is for QMORE fix */
    }
    gpphLibContext->status.GenCb_pending_status = FALSE;
    
    phLibNfc_UpdateCurState(status,gpphLibContext);
    /* Read is not success send failed to upperlayer Call back*/
    if( RetVal!= NFCSTATUS_SUCCESS ) 
    {
        if((RetVal!=NFCSTATUS_SHUTDOWN)&& (RetVal!=NFCSTATUS_ABORTED))
        {
            RetVal= NFCSTATUS_FAILED;
        }
        gpphLibContext->CBInfo.pClientNdefNtfRespCb(
                            gpphLibContext->CBInfo.pClientNdefNtfRespCntx,
                            NULL,
                            gpphLibContext->Connected_handle,
                            RetVal);
        gpphLibContext->CBInfo.pClientNdefNtfRespCb = NULL;     
        gpphLibContext->CBInfo.pClientNdefNtfRespCntx = NULL;
        return; 
    }

    /*Get the Number of records ( If Raw record parameter is null then API gives number of Records*/
    RetVal = phFriNfc_NdefRecord_GetRecords(
                            gpphLibContext->phLib_NdefRecCntx.ndef_message.buffer,
                            gpphLibContext->phLib_NdefRecCntx.ndef_message.length,
                            NULL,
                            gpphLibContext->phLib_NdefRecCntx.IsChunked,
                            &(gpphLibContext->phLib_NdefRecCntx.NumberOfRawRecords));

    NdefInfo.pNdefMessage = gpphLibContext->phLib_NdefRecCntx.ndef_message.buffer;
    NdefInfo.NdefMessageLengthActual = gpphLibContext->ndef_cntx.NdefActualSize;
    NdefInfo.NdefMessageLengthMaximum = gpphLibContext->ndef_cntx.NdefLength;
    NdefInfo.NdefRecordCount =0;

    /*Allocate memory to hold the records Read*/
    NdefInfo.pNdefRecord = phOsalNfc_GetMemory
        (sizeof(phFriNfc_NdefRecord_t)* gpphLibContext->phLib_NdefRecCntx.NumberOfRawRecords );  
    if(NULL==NdefInfo.pNdefRecord)
    {
        gpphLibContext->CBInfo.pClientNdefNtfRespCb(
                            gpphLibContext->CBInfo.pClientNdefNtfRespCntx,
                            NULL,
                            gpphLibContext->Connected_handle,
                            NFCSTATUS_FAILED);
        gpphLibContext->CBInfo.pClientNdefNtfRespCb = NULL;     
        gpphLibContext->CBInfo.pClientNdefNtfRespCntx = NULL;
        return;     
    }

    pNdefRecord=NdefInfo.pNdefRecord;   
    /*If phLibNfc_Ndef_SearchNdefContent Reg type is NULL return all the Records*/
    if(gpphLibContext->ndef_cntx.pNdef_NtfSrch_Type==NULL)
    {
        RetVal = phFriNfc_NdefRecord_GetRecords(
                        gpphLibContext->phLib_NdefRecCntx.ndef_message.buffer,
                        gpphLibContext->phLib_NdefRecCntx.ndef_message.length,
                        gpphLibContext->phLib_NdefRecCntx.RawRecords,
                        gpphLibContext->phLib_NdefRecCntx.IsChunked,
                        &(gpphLibContext->phLib_NdefRecCntx.NumberOfRawRecords));

        for (Index = 0; Index < gpphLibContext->phLib_NdefRecCntx.NumberOfRawRecords; Index++)
        {
            RetVal = phFriNfc_NdefRecord_Parse( 
                        pNdefRecord,
                        gpphLibContext->phLib_NdefRecCntx.RawRecords[Index]);
            pNdefRecord++;
            NdefInfo.NdefRecordCount++;
        }
    }
    else
    {
        
        /* Look for registerd TNF */
        RetVal = phFriNfc_NdefReg_DispatchPacket( 
                    &(gpphLibContext->phLib_NdefRecCntx.NdefReg),
                    gpphLibContext->phLib_NdefRecCntx.ndef_message.buffer,
                    (uint16_t)gpphLibContext->phLib_NdefRecCntx.ndef_message.length);
        if(NFCSTATUS_SUCCESS != RetVal)
        {
            /*phFriNfc_NdefReg_DispatchPacket is failed call upper layer*/
            gpphLibContext->CBInfo.pClientNdefNtfRespCb(gpphLibContext->CBInfo.pClientNdefNtfRespCntx,
                                                    NULL,gpphLibContext->Connected_handle,NFCSTATUS_FAILED);
            gpphLibContext->CBInfo.pClientNdefNtfRespCb = NULL;     
            gpphLibContext->CBInfo.pClientNdefNtfRespCntx = NULL;
            return; 
        }

        while(1 != RegStatus)
        {
            /* Process the NDEF records, If match FOUND we will get Call back*/
            RegStatus = phFriNfc_NdefReg_Process(   &(gpphLibContext->phLib_NdefRecCntx.NdefReg),
                                                &RegPrSt);
            if(RegPrSt == TRUE)
            {
                /*  Processing Done */
                break;
            }
            /*If match found the CbParam will be updated by lower layer, copy the record info*/
            for(Index=0;Index<gpphLibContext->phLib_NdefRecCntx.CbParam.Count;Index++)
            {
                pNdefRecord->Tnf  = gpphLibContext->phLib_NdefRecCntx.CbParam.Records[Index].Tnf;
                pNdefRecord->TypeLength  = 
                    gpphLibContext->phLib_NdefRecCntx.CbParam.Records[Index].TypeLength;
                pNdefRecord->PayloadLength  = 
                    gpphLibContext->phLib_NdefRecCntx.CbParam.Records[Index].PayloadLength;
                pNdefRecord->IdLength  = 
                    gpphLibContext->phLib_NdefRecCntx.CbParam.Records[Index].IdLength;
                pNdefRecord->Flags = 
                    gpphLibContext->phLib_NdefRecCntx.CbParam.Records[Index].Flags;

                pNdefRecord->Id = phOsalNfc_GetMemory(pNdefRecord->IdLength);
                pNdefRecord->Type = phOsalNfc_GetMemory(pNdefRecord->TypeLength);
                pNdefRecord->PayloadData = phOsalNfc_GetMemory(pNdefRecord->PayloadLength);         
                
                (void)memcpy(pNdefRecord->Id,
                    gpphLibContext->phLib_NdefRecCntx.CbParam.Records[Index].Id,
                    pNdefRecord->IdLength);
                (void)memcpy(pNdefRecord->PayloadData,
                    gpphLibContext->phLib_NdefRecCntx.CbParam.Records[Index].PayloadData,
                    pNdefRecord->PayloadLength);
                (void)memcpy(pNdefRecord->Type,
                    gpphLibContext->phLib_NdefRecCntx.CbParam.Records[Index].Type,
                    pNdefRecord->TypeLength);

                pNdefRecord++;
                NdefInfo.NdefRecordCount++;
            }
        }
    }
    /* If no record found call upper layer with failed status*/
    if(pNdefRecord == NdefInfo.pNdefRecord)
    {
        NdefInfo.NdefRecordCount =0;
        gpphLibContext->CBInfo.pClientNdefNtfRespCb(
                    gpphLibContext->CBInfo.pClientNdefNtfRespCntx,
                    &NdefInfo,gpphLibContext->Connected_handle,
                    NFCSTATUS_SUCCESS);
    
    }
    else
    {
        /*Call upperlayer Call back with match records*/

        gpphLibContext->CBInfo.pClientNdefNtfRespCb(
                    gpphLibContext->CBInfo.pClientNdefNtfRespCntx,
                    &NdefInfo,gpphLibContext->Connected_handle,
                    NFCSTATUS_SUCCESS);
        /*Remove entry from FRI*/
        RetVal = phFriNfc_NdefReg_RmCb( 
                    &(gpphLibContext->phLib_NdefRecCntx.NdefReg),
                    gpphLibContext->phLib_NdefRecCntx.NdefCb );
        /*Free the memory*/
        if(gpphLibContext->ndef_cntx.pNdef_NtfSrch_Type!=NULL)
        {
            pNdefRecord=NdefInfo.pNdefRecord;
            for(Index=0;Index<gpphLibContext->phLib_NdefRecCntx.CbParam.Count;Index++)
            {
                phOsalNfc_FreeMemory(pNdefRecord->Id);
                phOsalNfc_FreeMemory(pNdefRecord->PayloadData);
                phOsalNfc_FreeMemory(pNdefRecord->Type);
                pNdefRecord++;
            }
        }
    }

    gpphLibContext->CBInfo.pClientNdefNtfRespCb = NULL;     
    gpphLibContext->CBInfo.pClientNdefNtfRespCntx = NULL;
    
}

STATIC
void phLibNfc_Ndef_Rtd_Cb( void *CallBackParam)
{
    /*There will be single call back given to all match
      It's processed in phLibNfc_Ndef_SrchNdefCnt_Cb*/  
    PHNFC_UNUSED_VARIABLE(CallBackParam);
}

NFCSTATUS phLibNfc_Ndef_SearchNdefContent(  
                                phLibNfc_Handle                 hRemoteDevice,
                                phLibNfc_Ndef_SrchType_t*       psSrchTypeList,  
                                uint8_t                         uNoSrchRecords,
                                pphLibNfc_Ndef_Search_RspCb_t   pNdefNtfRspCb,  
                                void *                          pContext   
                                )
{

     NFCSTATUS  RetVal =NFCSTATUS_SUCCESS;
     uint32_t Index=0;
     uint8_t     cr_index = 0;


      if((NULL == gpphLibContext) ||
        (gpphLibContext->LibNfcState.cur_state
                            == eLibNfcHalStateShutdown))
      {
         RetVal = NFCSTATUS_NOT_INITIALISED;
      }
     /* Check the state for DeInit is called or not,if yes return NFCSTATUS_SHUTDOWN*/
      else if(gpphLibContext->LibNfcState.next_state
                            == eLibNfcHalStateShutdown)
     {       
        RetVal= NFCSTATUS_SHUTDOWN;
     }
     else if( (NULL == pNdefNtfRspCb) ||
        (NULL == pContext ) ||
        (0 == hRemoteDevice))
     {
        RetVal= NFCSTATUS_INVALID_PARAMETER;        
     } 
     else if( (NULL != psSrchTypeList) && (0==uNoSrchRecords))
     {
        RetVal= NFCSTATUS_INVALID_PARAMETER;        
     }
     else if(0 == gpphLibContext->Connected_handle)
     {   /*presently no target or tag is connected*/ 
        RetVal=NFCSTATUS_TARGET_NOT_CONNECTED;        
     }
     else if(hRemoteDevice != gpphLibContext->Connected_handle)
     {   /*This handle of the device sent by application is not connected */ 
        RetVal=NFCSTATUS_INVALID_HANDLE;        
     }  
     else if((TRUE == gpphLibContext->status.GenCb_pending_status)       
        ||(NULL!=gpphLibContext->CBInfo.pClientNdefNtfRespCb))
     {
        /*Previous callback is pending*/
        RetVal = NFCSTATUS_REJECTED;
     }
     else
     {
        gpphLibContext->ndef_cntx.pNdef_NtfSrch_Type = psSrchTypeList;

        if(psSrchTypeList!=NULL)
        {
            /*Maximum records supported*/
            gpphLibContext->phLib_NdefRecCntx.NumberOfRecords = 255;
            /*Reset the FRI component to add the Reg type*/
            RetVal = phFriNfc_NdefReg_Reset( 
                            &(gpphLibContext->phLib_NdefRecCntx.NdefReg),
                            gpphLibContext->phLib_NdefRecCntx.NdefTypes_array,
                            &(gpphLibContext->phLib_NdefRecCntx.RecordsExtracted),
                            &(gpphLibContext->phLib_NdefRecCntx.CbParam),
                            gpphLibContext->phLib_NdefRecCntx.ChunkedRecordsarray,  
                            gpphLibContext->phLib_NdefRecCntx.NumberOfRecords);

            gpphLibContext->phLib_NdefRecCntx.NdefCb = phOsalNfc_GetMemory(sizeof(phFriNfc_NdefReg_Cb_t));
            if(gpphLibContext->phLib_NdefRecCntx.NdefCb==NULL)
            {
                /*exception: Not enough memory*/
                phOsalNfc_RaiseException(phOsalNfc_e_NoMemory,1);
            }
            gpphLibContext->phLib_NdefRecCntx.NdefCb->NdefCallback = phLibNfc_Ndef_Rtd_Cb;
            /*Copy the TNF types to search in global structure*/    
            gpphLibContext->phLib_NdefRecCntx.NdefCb->NumberOfRTDs = uNoSrchRecords;
            for(Index=0;Index<uNoSrchRecords;Index++)
            {
                gpphLibContext->phLib_NdefRecCntx.NdefCb->NdefType[Index] = psSrchTypeList->Type;
                gpphLibContext->phLib_NdefRecCntx.NdefCb->Tnf[Index] = psSrchTypeList->Tnf ; 
                gpphLibContext->phLib_NdefRecCntx.NdefCb->NdeftypeLength[Index] = psSrchTypeList->TypeLength;
                psSrchTypeList++;
            }
            /* Add the TNF type to FRI component*/

            RetVal = phFriNfc_NdefReg_AddCb(&(gpphLibContext->phLib_NdefRecCntx.NdefReg),
                                                gpphLibContext->phLib_NdefRecCntx.NdefCb );

        }
        gpphLibContext->phLib_NdefRecCntx.ndef_message.buffer = 
            phOsalNfc_GetMemory(gpphLibContext->ndef_cntx.NdefActualSize);
        gpphLibContext->phLib_NdefRecCntx.ndef_message.length = 
            gpphLibContext->ndef_cntx.NdefActualSize;
        /*Set Complete routine for NDEF Read*/
        for (cr_index = 0; cr_index < PH_FRINFC_NDEFMAP_CR; cr_index++)
        {
            RetVal= phFriNfc_NdefMap_SetCompletionRoutine(
                                gpphLibContext->ndef_cntx.psNdefMap,
                                cr_index,
                                phLibNfc_Ndef_SrchNdefCnt_Cb,
                                (void *)gpphLibContext);

        }
        gpphLibContext->ndef_cntx.NdefContinueRead = PH_FRINFC_NDEFMAP_SEEK_BEGIN;
        /* call below layer Ndef Read*/
        RetVal = phFriNfc_NdefMap_RdNdef(gpphLibContext->ndef_cntx.psNdefMap,
                        gpphLibContext->phLib_NdefRecCntx.ndef_message.buffer,
                        (uint32_t*)&gpphLibContext->phLib_NdefRecCntx.ndef_message.length,
                        PH_FRINFC_NDEFMAP_SEEK_BEGIN);

        if(NFCSTATUS_PENDING == RetVal)
        {
            gpphLibContext->CBInfo.pClientNdefNtfRespCb = pNdefNtfRspCb;        
            gpphLibContext->CBInfo.pClientNdefNtfRespCntx = pContext;
            gpphLibContext->status.GenCb_pending_status=TRUE;
            gpphLibContext->LibNfcState.next_state = eLibNfcHalStateTransaction;
        }
        else if (NFCSTATUS_SUCCESS == RetVal)
        {
            RetVal= NFCSTATUS_SUCCESS;
        }
        else
        {
            /*Ndef read failed*/
            RetVal = NFCSTATUS_FAILED;
        }
    }
    return RetVal;

}

