/*
 * 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.c

 * Project: NFC FRI / HALDL
 *
 * $Date: Tue Jun  1 14:53:48 2010 $
 * $Author: ing07385 $
 * $Revision: 1.89 $
 * $Aliases: NFC_FRI1.1_WK1024_SDK $
 *
 */


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

#define LOG_TAG "NFC"

#include <phLibNfc.h>
#include <phDal4Nfc.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 <phNfcStatus.h>
#include <cutils/log.h>
/*
*************************** Macro's  ******************************************
*/

extern int dlopen_firmware();

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


/*
*************************** Global Variables **********************************
*/


pphLibNfc_LibContext_t gpphLibContext=NULL;

/*
*************************** Static Function Declaration ***********************
*/

/* Init callback */
STATIC void phLibNfc_InitCb(void *pContext,NFCSTATUS status);

/* Shutdown callback */
STATIC void phLibNfc_ShutdownCb(void *pContext,NFCSTATUS status);

/**Default notification handler registered with lower layer immediately after 
   successful initialization*/
STATIC void phLibNfc_DefaultHandler(
                                void                        *context,                                 
                                phHal_eNotificationType_t    type,
                                phHal4Nfc_NotificationInfo_t info,
                                NFCSTATUS                    status
                                );
/*
*************************** Function Definitions ******************************
*/

NFCSTATUS phLibNfc_Mgt_ConfigureDriver (pphLibNfc_sConfig_t     psConfig,
                                        void **                 ppDriverHandle)
{
    if(NULL != gpphLibContext)
    {
        return NFCSTATUS_ALREADY_INITIALISED;
    }   

    return phDal4Nfc_Config(psConfig, ppDriverHandle);
}

NFCSTATUS phLibNfc_Mgt_UnConfigureDriver (void *                 pDriverHandle)
{
    if(NULL != gpphLibContext)
    {
        return NFCSTATUS_ALREADY_INITIALISED;
    }   

   return phDal4Nfc_ConfigRelease(pDriverHandle);
}

NFCSTATUS phLibNfc_HW_Reset ()
{
    NFCSTATUS Status = NFCSTATUS_SUCCESS;

    Status = phDal4Nfc_Reset(1);
    Status = phDal4Nfc_Reset(0);
    Status = phDal4Nfc_Reset(1);

    return Status;
}

NFCSTATUS phLibNfc_Download_Mode ()
{
   return phDal4Nfc_Download();
}

int phLibNfc_Load_Firmware_Image ()
{
    int status;
    status = dlopen_firmware();
    return status;
}

// Function for delay the recovery in case wired mode is set
// to complete the possible pending transaction with SE
void phLibNfc_Mgt_Recovery ()
{
    /* Wait before recovery if wired mode */
    if (gpphLibContext->sSeContext.eActivatedMode == phLibNfc_SE_ActModeWired)
    {
        usleep (12000000);
    }

    return;
}

extern uint8_t nxp_nfc_isoxchg_timeout;
NFCSTATUS phLibNfc_SetIsoXchgTimeout(uint8_t timeout) {
    nxp_nfc_isoxchg_timeout = timeout;
    return NFCSTATUS_SUCCESS;
}

int phLibNfc_GetIsoXchgTimeout() {
    return nxp_nfc_isoxchg_timeout;
}

extern uint32_t nxp_nfc_hci_response_timeout;
NFCSTATUS phLibNfc_SetHciTimeout(uint32_t timeout_in_ms) {
    nxp_nfc_hci_response_timeout = timeout_in_ms;
    return NFCSTATUS_SUCCESS;
}

int phLibNfc_GetHciTimeout() {
    return nxp_nfc_hci_response_timeout;
}

extern uint8_t nxp_nfc_felica_timeout;
NFCSTATUS phLibNfc_SetFelicaTimeout(uint8_t timeout_in_ms) {
    nxp_nfc_felica_timeout = timeout_in_ms;
    return NFCSTATUS_SUCCESS;
}

int phLibNfc_GetFelicaTimeout() {
    return nxp_nfc_felica_timeout;
}

extern uint8_t nxp_nfc_mifareraw_timeout;
NFCSTATUS phLibNfc_SetMifareRawTimeout(uint8_t timeout) {
    nxp_nfc_mifareraw_timeout = timeout;
    return NFCSTATUS_SUCCESS;
}

int phLibNfc_GetMifareRawTimeout() {
    return nxp_nfc_mifareraw_timeout;
}

/**
*    Initialize the phLibNfc interface.
*/

NFCSTATUS phLibNfc_Mgt_Initialize(void                *pDriverHandle,
                                 pphLibNfc_RspCb_t    pInitCb,
                                 void                 *pContext)
{
     NFCSTATUS Status = NFCSTATUS_SUCCESS;     
     if((NULL == pDriverHandle)||(NULL == pInitCb))
     {
        Status = NFCSTATUS_INVALID_PARAMETER;
     }
     else if(NULL == gpphLibContext)
     {
        /* Initialize the Lib context */
        gpphLibContext=(pphLibNfc_LibContext_t)phOsalNfc_GetMemory(
                                        (uint32_t)sizeof(phLibNfc_LibContext_t));
        if(NULL == gpphLibContext)
        {
            Status=NFCSTATUS_INSUFFICIENT_RESOURCES;
        }
        else
        {
            (void)memset((void *)gpphLibContext,0,(
                                    (uint32_t)sizeof(phLibNfc_LibContext_t)));

            /* Store the Callback and context in LibContext structure*/
            gpphLibContext->CBInfo.pClientInitCb=pInitCb;
            gpphLibContext->CBInfo.pClientInitCntx=pContext;
            /* Initialize the HwReferece structure */
            gpphLibContext->psHwReference=(phHal_sHwReference_t *)
                                    phOsalNfc_GetMemory((uint32_t)sizeof(phHal_sHwReference_t));
            (void)memset((void *)gpphLibContext->psHwReference,0,
                                        ((uint32_t)sizeof(phHal_sHwReference_t)));
            /* Allocate the Memory for the Transceive info */
            if( gpphLibContext->psHwReference!=NULL)
            {
                gpphLibContext->psHwReference->p_board_driver = pDriverHandle;
                Status = phLibNfc_UpdateNextState(gpphLibContext,
                                            eLibNfcHalStateInitandIdle);
                if(Status==NFCSTATUS_SUCCESS)
                {
                    Status=phHal4Nfc_Open(
                                    gpphLibContext->psHwReference,
                                    eInitDefault,
                                    phLibNfc_InitCb,
                                    (void *)gpphLibContext);
                }
            }
            else
            {
                Status = NFCSTATUS_INSUFFICIENT_RESOURCES;
            }
            phLibNfc_Ndef_Init();
        }
    }
    else if(gpphLibContext->LibNfcState.next_state==eLibNfcHalStateShutdown)
    {
        Status = NFCSTATUS_SHUTDOWN;
    }
    else
    {
        Status=NFCSTATUS_ALREADY_INITIALISED;
    }
   return Status;
}

/*
 * This function called by the HAL4 when the initialization seq is completed.
 */
STATIC void phLibNfc_InitCb(void *pContext,NFCSTATUS status)
{
    pphLibNfc_LibContext_t   pLibContext=NULL;
    pphLibNfc_RspCb_t          pClientCb=NULL;
    void                        *pUpperLayerContext=NULL;


    /* Initialize the local variable */
    pLibContext  = (pphLibNfc_LibContext_t)pContext;

    pClientCb =pLibContext->CBInfo.pClientInitCb;
    pUpperLayerContext=pLibContext->CBInfo.pClientInitCntx;
    if(status == NFCSTATUS_SUCCESS)
    {
        /* Get the Lib context */
        pLibContext=(pphLibNfc_LibContext_t)gpphLibContext;
        gpphLibContext->sSeContext.eActivatedMode = phLibNfc_SE_ActModeOff;
        if(pLibContext->psHwReference->uicc_connected==TRUE)
        {
            /* populate state of the secured element */
            gpphLibContext->sSeContext.eActivatedMode = phLibNfc_SE_ActModeDefault;
            sSecuredElementInfo[LIBNFC_SE_UICC_INDEX].eSE_CurrentState=phLibNfc_SE_Active;
            pLibContext->sSeContext.uUiccActivate=TRUE;
        }		
        if(pLibContext->psHwReference->smx_connected==TRUE)
        {
            /* populate state of the secured element */
            gpphLibContext->sSeContext.eActivatedMode = phLibNfc_SE_ActModeDefault;
            sSecuredElementInfo[LIBNFC_SE_SMARTMX_INDEX].eSE_CurrentState=phLibNfc_SE_Inactive; 
            pLibContext->sSeContext.uSmxActivate =FALSE;
        }

        phLibNfc_UpdateCurState(status,pLibContext);
        (void)phHal4Nfc_RegisterNotification(                                            
                                pLibContext->psHwReference,
                                eRegisterDefault,
                                phLibNfc_DefaultHandler,
                                (void*)pLibContext
                                ); 
        /* call the upper layer register function */
        (*pClientCb)(pUpperLayerContext,status);

    }
    else
    {
        /*Change the status code failed*/
        status = NFCSTATUS_FAILED;
        /* Get the Lib context */
        pLibContext=(pphLibNfc_LibContext_t)gpphLibContext;

        phLibNfc_UpdateCurState(status,pLibContext);



        /* Allocate the Memory for the Transceive info */
        if(pLibContext->psHwReference!= NULL)
        {
            phOsalNfc_FreeMemory(pLibContext->psHwReference);
            pLibContext->psHwReference = NULL;
        }
        (*pClientCb)(pUpperLayerContext, status);

        phOsalNfc_FreeMemory(pLibContext);
        pLibContext= NULL;
        gpphLibContext = NULL;
        
    }
    return;
}

/**Default notification handler registered with lower layer immediately after 
   successful initialization*/
STATIC void phLibNfc_DefaultHandler(
                                void                        *context,                                 
                                phHal_eNotificationType_t    type,
                                phHal4Nfc_NotificationInfo_t info,
                                NFCSTATUS                    status
                                )
{
    if(context != (void *)gpphLibContext)
    {
        phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1);
    }
    else
    {
        info = info;
        if((NFC_EVENT_NOTIFICATION == type) &&
            (NFCSTATUS_BOARD_COMMUNICATION_ERROR == status))
        {
            phLibNfc_UpdateCurState(NFCSTATUS_FAILED,gpphLibContext);
            phOsalNfc_RaiseException(phOsalNfc_e_UnrecovFirmwareErr,1);
        }
    }
    return;
}
/**
* De-Initialize the LIB NFC.
*/
NFCSTATUS phLibNfc_Mgt_DeInitialize(void *                      pDriverHandle,
                                   pphLibNfc_RspCb_t            pDeInitCb,
                                   void*                        pContext
                                   )
{
    NFCSTATUS Status = NFCSTATUS_SUCCESS;
    pphLibNfc_LibContext_t pLibContext = gpphLibContext;
    if(NULL==pDriverHandle)
    {
        /*Check for valid parameters */
        Status = NFCSTATUS_INVALID_PARAMETER;
    }
    else if((pLibContext==NULL)
        || (pLibContext->LibNfcState.cur_state
            == eLibNfcHalStateShutdown))
    {   /*Lib Nfc not initlized*/
        Status = NFCSTATUS_NOT_INITIALISED;
    }
    else
    {
        if(pDeInitCb==NULL)
        {
            phHal4Nfc_Hal4Reset(pLibContext->psHwReference,(void *)pLibContext);
            if(pLibContext->psHwReference!=NULL)
            {
                phOsalNfc_FreeMemory(pLibContext->psHwReference);
                pLibContext->psHwReference = NULL;
            }
            /*Free the memory allocated during NDEF read,write
              and NDEF formatting*/
            phLibNfc_Ndef_DeInit();
            phOsalNfc_FreeMemory(pLibContext);
            gpphLibContext=NULL;
            pLibContext= NULL;
        }
        else
        {
            if (NULL!= pLibContext->CBInfo.pClientShutdownCb)
            {
                /* Previous callback pending */
                Status = NFCSTATUS_BUSY;
            }
          Status = NFCSTATUS_PENDING;
          if(TRUE != pLibContext->status.GenCb_pending_status)
          {
              Status = phHal4Nfc_Close(pLibContext->psHwReference,
                                  phLibNfc_ShutdownCb,
                                  (void *)pLibContext);
          }
          if(Status== NFCSTATUS_PENDING)
          {
              pLibContext->CBInfo.pClientShutdownCb = pDeInitCb;
              pLibContext->CBInfo.pClientShtdwnCntx = pContext;
              pLibContext->status.GenCb_pending_status=TRUE;
              pLibContext->LibNfcState.next_state= eLibNfcHalStateShutdown;
          }
          else
          {
              Status =NFCSTATUS_FAILED;
          }
        }       
    }
    return Status;
}
/* shutdown callback -
  Free the allocated memory here */
STATIC void phLibNfc_ShutdownCb(void *pContext,NFCSTATUS status)
{
    pphLibNfc_RspCb_t           pClientCb=NULL;
    void                        *pUpperLayerContext=NULL;
    pphLibNfc_LibContext_t      pLibContext=NULL;

    PHNFC_UNUSED_VARIABLE(pContext);
    /* Get the Lib context */
    pLibContext=(pphLibNfc_LibContext_t)gpphLibContext;

    if(pLibContext == NULL)
    {
        status = NFCSTATUS_FAILED;
    }
    else
    {
        /* Initialize the local variable */
        pClientCb =pLibContext->CBInfo.pClientShutdownCb;
        pUpperLayerContext=pLibContext->CBInfo.pClientShtdwnCntx;
        if(status == NFCSTATUS_SUCCESS)
        {
            pLibContext->LibNfcState.cur_state = eLibNfcHalStateShutdown;
            phLibNfc_UpdateCurState(status,pLibContext);

            pLibContext->status.GenCb_pending_status=FALSE;
            
            /* Allocate the Memory for the Transceive info */
            if(pClientCb!=NULL)
            {
                (*pClientCb)(pUpperLayerContext, status);
            }
            if(pLibContext->psHwReference!=NULL)
            {
                phOsalNfc_FreeMemory(pLibContext->psHwReference);
                pLibContext->psHwReference = NULL;
            }
            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 = NULL;
            }
            /*Free the memory allocated during NDEF read,write
              and NDEF formatting*/
            phLibNfc_Ndef_DeInit();        
                phOsalNfc_FreeMemory(pLibContext);
                gpphLibContext=NULL;
                pLibContext= NULL;
       
        }
        else
        {
            /* shutdown sequence failed by HAL 4 */
            status= NFCSTATUS_FAILED;
            pLibContext=(pphLibNfc_LibContext_t)gpphLibContext;
            phLibNfc_UpdateCurState(status,pLibContext);
            pLibContext->status.GenCb_pending_status=FALSE;
            if(pClientCb!=NULL)
            {
                (*pClientCb)(pUpperLayerContext,status);
            }
        }
    }
}
/**
*    Pending shutdown call.
*/


void phLibNfc_Pending_Shutdown(void)
{
    NFCSTATUS RetStatus = NFCSTATUS_SUCCESS ;
    gpphLibContext->status.GenCb_pending_status = FALSE;
    RetStatus = phHal4Nfc_Close(
                        gpphLibContext->psHwReference,
                        phLibNfc_ShutdownCb,
                        (void *)gpphLibContext);
    PHNFC_UNUSED_VARIABLE(RetStatus);
    return;
}


/**
* Reset the LIB NFC.
*/
NFCSTATUS phLibNfc_Mgt_Reset(void  *pContext)
{
    NFCSTATUS Status = NFCSTATUS_SUCCESS;
    phLibNfc_LibContext_t   *pLibNfc_Ctxt = (phLibNfc_LibContext_t *)pContext;

    if((pLibNfc_Ctxt == NULL)
        || (gpphLibContext->LibNfcState.cur_state
            == eLibNfcHalStateShutdown))
    {   /*Lib Nfc not initlized*/
        Status = NFCSTATUS_NOT_INITIALISED;
    }  
    else if(NULL == pContext) 
    {
        Status = NFCSTATUS_INVALID_PARAMETER;
    }
    /* Check for valid state,If De initialize is called then
    return NFCSTATUS_SHUTDOWN */
    else if(gpphLibContext->LibNfcState.next_state
                            == eLibNfcHalStateShutdown)
    {
        Status = NFCSTATUS_SHUTDOWN;
    }
    else
    {                     
        /*Reset all callback status*/
        (void) memset(&(gpphLibContext->RegNtfType),0,
                        sizeof(phLibNfc_Registry_Info_t));
        (void) memset(&(gpphLibContext->sADDconfig),0,
                        sizeof(phLibNfc_sADD_Cfg_t));
        (void) memset(&(gpphLibContext->ndef_cntx),0,
                        sizeof(phLibNfc_NdefInfo_t));
        (void) memset(&(gpphLibContext->sNfcIp_Context),0,
                        sizeof(phLibNfc_NfcIpInfo_t));
        (void) memset(&(gpphLibContext->sCardEmulCfg),0,
                        sizeof(phHal_sEmulationCfg_t));
        (void) memset(&(gpphLibContext->Discov_handle),0,
                        MAX_REMOTE_DEVICES);

        /*Free memory allocated for NDEF records*/
        if(NULL != gpphLibContext->psBufferedAuth)
        {
            if(NULL != gpphLibContext->psBufferedAuth->sRecvData.buffer)
            {
                phOsalNfc_FreeMemory(
                    gpphLibContext->psBufferedAuth->sRecvData.buffer);
                gpphLibContext->psBufferedAuth->sRecvData.buffer = NULL;
            }
            if(NULL != gpphLibContext->psBufferedAuth->sSendData.buffer)
            {
                phOsalNfc_FreeMemory(
                    gpphLibContext->psBufferedAuth->sSendData.buffer);
                gpphLibContext->psBufferedAuth->sSendData.buffer = NULL;
            }
            phOsalNfc_FreeMemory(gpphLibContext->psBufferedAuth);
            gpphLibContext->psBufferedAuth = NULL;
        }
        if(NULL != gpphLibContext->psTransInfo)
        {
            phOsalNfc_FreeMemory(gpphLibContext->psTransInfo);
            gpphLibContext->psTransInfo = NULL;
        }
        if(NULL != gpphLibContext->ndef_cntx.psNdefMap)
        {
            if(NULL != gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf)
            {
                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->psOverHalCtxt)
        {
            phOsalNfc_FreeMemory(gpphLibContext->psOverHalCtxt);
            gpphLibContext->psTransInfo = NULL;
        }
        if(NULL != gpphLibContext->psDevInputParam)
        {
            phOsalNfc_FreeMemory(gpphLibContext->psDevInputParam);
            gpphLibContext->psDevInputParam = NULL;
        }
        if(NULL != gpphLibContext->ndef_cntx.ndef_fmt)
        {
            phOsalNfc_FreeMemory(gpphLibContext->ndef_cntx.ndef_fmt);
            gpphLibContext->ndef_cntx.ndef_fmt = NULL;
        }
        if(NULL != pNdefRecord) 
        {
            if(NULL != pNdefRecord->Id)
            {
                phOsalNfc_FreeMemory(pNdefRecord->Id);
                pNdefRecord->Id = NULL;
            }
            if(NULL != pNdefRecord->Type)
            {
                phOsalNfc_FreeMemory(pNdefRecord->Type);
                pNdefRecord->Type = NULL;
            }
            if(NULL != pNdefRecord->PayloadData)
            {
                phOsalNfc_FreeMemory(pNdefRecord->PayloadData);
                pNdefRecord->PayloadData = NULL;
            }
        }
        if(NULL != NdefInfo.pNdefRecord)
        {
            phOsalNfc_FreeMemory(NdefInfo.pNdefRecord);
            NdefInfo.pNdefRecord = NULL;
        }          
        if(NULL != gpphLibContext->phLib_NdefRecCntx.NdefCb)
        {
            phOsalNfc_FreeMemory(gpphLibContext->phLib_NdefRecCntx.NdefCb);
            gpphLibContext->phLib_NdefRecCntx.NdefCb = NULL;
        }
        if(NULL != gpphLibContext->phLib_NdefRecCntx.ndef_message.buffer)
        {
            phOsalNfc_FreeMemory(gpphLibContext->phLib_NdefRecCntx.ndef_message.buffer);
            gpphLibContext->phLib_NdefRecCntx.ndef_message.buffer = NULL;
        }
        /* No device is connected */
        gpphLibContext->Connected_handle = 0x00;       
        gpphLibContext->Prev_Connected_handle = 0x00;
        gpphLibContext->ReleaseType = NFC_INVALID_RELEASE_TYPE;        
        gpphLibContext->eLibNfcCfgMode = NFC_DISCOVERY_STOP;
        /*Lib Nfc Stack is initilized and in idle state*/
        gpphLibContext->LibNfcState.cur_state = eLibNfcHalStateInitandIdle;

        /* Reset all callback status */
        gpphLibContext->CBInfo.pClientCkNdefCb = NULL;
        gpphLibContext->CBInfo.pClientCkNdefCntx = NULL;
        gpphLibContext->CBInfo.pClientConCntx = NULL;
        gpphLibContext->CBInfo.pClientConnectCb = NULL;
        gpphLibContext->CBInfo.pClientDConCntx = NULL;
        gpphLibContext->CBInfo.pClientDisCfgCntx = NULL;
        gpphLibContext->CBInfo.pClientDisConfigCb = NULL;
        gpphLibContext->CBInfo.pClientInitCb = NULL;
        gpphLibContext->CBInfo.pClientInitCntx = gpphLibContext;
        gpphLibContext->CBInfo.pClientNdefNtfRespCb = NULL;
        gpphLibContext->CBInfo.pClientNdefNtfRespCntx = NULL;
        gpphLibContext->CBInfo.pClientNtfRegRespCB = NULL;
        gpphLibContext->CBInfo.pClientNtfRegRespCntx = NULL;
        gpphLibContext->CBInfo.pClientPresChkCb = NULL;
        gpphLibContext->CBInfo.pClientPresChkCntx = NULL;
        gpphLibContext->CBInfo.pClientRdNdefCb = NULL;
        gpphLibContext->CBInfo.pClientRdNdefCntx = NULL;
        gpphLibContext->CBInfo.pClientShtdwnCntx = NULL;
        gpphLibContext->CBInfo.pClientShutdownCb = NULL;
        gpphLibContext->CBInfo.pClientTransceiveCb = NULL;
        gpphLibContext->CBInfo.pClientTranseCntx = NULL;
        gpphLibContext->CBInfo.pClientWrNdefCb = NULL;
        gpphLibContext->CBInfo.pClientWrNdefCntx = NULL;
        gpphLibContext->sNfcIp_Context.pClientNfcIpCfgCb = NULL;
        gpphLibContext->sNfcIp_Context.pClientNfcIpCfgCntx = NULL;
        gpphLibContext->sNfcIp_Context.pClientNfcIpRxCb = NULL;
        gpphLibContext->sNfcIp_Context.pClientNfcIpRxCntx = NULL;
        gpphLibContext->sNfcIp_Context.pClientNfcIpTxCb = NULL;
        gpphLibContext->sNfcIp_Context.pClientNfcIpTxCntx = NULL;
        gpphLibContext->sSeContext.sSeCallabackInfo.pSeListenerNtfCb = NULL;
        gpphLibContext->sSeContext.sSeCallabackInfo.pSeListenerCtxt = NULL;
        gpphLibContext->sSeContext.sSeCallabackInfo.pSEsetModeCb = NULL;
        gpphLibContext->sSeContext.sSeCallabackInfo.pSEsetModeCtxt = NULL;
        /*No callback is pending*/
        gpphLibContext->status.GenCb_pending_status = FALSE;        
                    
    }
    return Status;
}
/**
*    LibNfc state machine next state update.
*/

NFCSTATUS
phLibNfc_UpdateNextState(
                         pphLibNfc_LibContext_t   pLibContext,
                         phLibNfc_State_t        next_state
                         )
{
    NFCSTATUS       status = NFCSTATUS_INVALID_STATE;
    switch(pLibContext->LibNfcState.cur_state)
    {
    case eLibNfcHalStateShutdown:
        {
            switch(next_state)
            {
            case eLibNfcHalStateShutdown:
            case eLibNfcHalStateInitandIdle:
                status = NFCSTATUS_SUCCESS;
                break;
            default:
                break;
            }
        }
        break;
    case eLibNfcHalStateConfigReady:
        {
            switch(next_state)
            {
            case eLibNfcHalStateShutdown:
            case eLibNfcHalStateConfigReady:
            case eLibNfcHalStateInitandIdle:
            case eLibNfcHalStateConnect:
                status = NFCSTATUS_SUCCESS;
                break;
            default:
                break;
            }
        }
        break;
    case eLibNfcHalStateConnect:
        {
            switch(next_state)
            {
            case eLibNfcHalStateShutdown:
            case eLibNfcHalStateRelease:
            case eLibNfcHalStateTransaction:
            case eLibNfcHalStatePresenceChk:
                status = NFCSTATUS_SUCCESS;
                break;
            default:
                break;
            }
        }
        break;
    case eLibNfcHalStatePresenceChk:
        {
            switch(next_state)
            {
            case eLibNfcHalStateShutdown:
            case eLibNfcHalStateConfigReady:
            case eLibNfcHalStateRelease:
            case eLibNfcHalStateTransaction:
            case eLibNfcHalStatePresenceChk:
                status = NFCSTATUS_SUCCESS;
                break;
            default:
                break;
            }
        }
        break;
    case eLibNfcHalStateInitandIdle:
        {
            switch(next_state)
            {
            case eLibNfcHalStateShutdown:
            case eLibNfcHalStateConfigReady:
                status = NFCSTATUS_SUCCESS;
                break;
            default:
                break;
            }
        }
        break;
    default:
        break;
    }
    pLibContext->LibNfcState.next_state = 
        (uint8_t)((NFCSTATUS_SUCCESS == status)?next_state:pLibContext->LibNfcState.next_state);

    return status;
}

/**
*    LibNfc state machine current state update.
*/

void
phLibNfc_UpdateCurState(
                        NFCSTATUS      status,
                        pphLibNfc_LibContext_t psLibContext
                        )
{
    switch(psLibContext->LibNfcState.next_state)
    {
    case eLibNfcHalStateTransaction:
        psLibContext->LibNfcState.cur_state = (uint8_t)eLibNfcHalStateConnect;
        break;
    case eLibNfcHalStateRelease:
        psLibContext->LibNfcState.cur_state
            = (uint8_t)(psLibContext->status.DiscEnbl_status == TRUE?
              eLibNfcHalStateInitandIdle:eLibNfcHalStateConfigReady);
        break;
    case eLibNfcHalStateInvalid:
        break;
    default:
        psLibContext->LibNfcState.cur_state
            = (uint8_t)((NFCSTATUS_SUCCESS == status)?
            psLibContext->LibNfcState.next_state:
        psLibContext->LibNfcState.cur_state);
    }
    psLibContext->LibNfcState.next_state = (uint8_t)eLibNfcHalStateInvalid;
    return;
}
/* Interface to stack capabilities */

NFCSTATUS phLibNfc_Mgt_GetstackCapabilities(
                    phLibNfc_StackCapabilities_t *phLibNfc_StackCapabilities,
                    void                         *pContext)
{
    NFCSTATUS RetVal = NFCSTATUS_FAILED;
    /*Check Lib Nfc stack is initilized*/
    if((NULL == gpphLibContext)|| 
        (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateShutdown))
    {
        RetVal = NFCSTATUS_NOT_INITIALISED;
    }   
    /*Check application has sent the valid parameters*/
    else if((NULL == phLibNfc_StackCapabilities)
        || (NULL == pContext))
    {
        RetVal= NFCSTATUS_INVALID_PARAMETER;
    }   
    else if(gpphLibContext->LibNfcState.next_state == eLibNfcHalStateShutdown)
    {
        RetVal = NFCSTATUS_SHUTDOWN;
    }
    else if(TRUE == gpphLibContext->status.GenCb_pending_status)       
    {
        /*Previous operation is pending  */
        RetVal = NFCSTATUS_BUSY;
    }    
    else
    {
        /* Tag Format Capabilities*/
        phLibNfc_StackCapabilities->psFormatCapabilities.Desfire = TRUE;
        phLibNfc_StackCapabilities->psFormatCapabilities.MifareStd = TRUE;
        phLibNfc_StackCapabilities->psFormatCapabilities.MifareUL = TRUE;
        phLibNfc_StackCapabilities->psFormatCapabilities.FeliCa = FALSE;
        phLibNfc_StackCapabilities->psFormatCapabilities.Jewel = FALSE;
        phLibNfc_StackCapabilities->psFormatCapabilities.ISO14443_4A = FALSE;
        phLibNfc_StackCapabilities->psFormatCapabilities.ISO14443_4B = FALSE;
        phLibNfc_StackCapabilities->psFormatCapabilities.MifareULC = TRUE;
         phLibNfc_StackCapabilities->psFormatCapabilities.ISO15693 = FALSE;

        /* Tag Mapping Capabilities */
        phLibNfc_StackCapabilities->psMappingCapabilities.FeliCa = TRUE;
        phLibNfc_StackCapabilities->psMappingCapabilities.Desfire = TRUE;
        phLibNfc_StackCapabilities->psMappingCapabilities.ISO14443_4A = TRUE;
        phLibNfc_StackCapabilities->psMappingCapabilities.ISO14443_4B = TRUE;
        phLibNfc_StackCapabilities->psMappingCapabilities.MifareStd = TRUE;
        phLibNfc_StackCapabilities->psMappingCapabilities.MifareUL = TRUE;
        phLibNfc_StackCapabilities->psMappingCapabilities.MifareULC = TRUE;     
        phLibNfc_StackCapabilities->psMappingCapabilities.Jewel = TRUE;
        phLibNfc_StackCapabilities->psMappingCapabilities.ISO15693 = FALSE;
        
        /*Call Hal4 Get Dev Capabilities to get info about protocols supported
          by Lib Nfc*/
        PHDBG_INFO("LibNfc:Get Stack capabilities ");
        RetVal= phHal4Nfc_GetDeviceCapabilities(                                          
                        gpphLibContext->psHwReference,                            
                        &(phLibNfc_StackCapabilities->psDevCapabilities),
                        (void *)gpphLibContext); 

        LIB_NFC_VERSION_SET(phLibNfc_StackCapabilities->psDevCapabilities.hal_version,
                            PH_HAL4NFC_VERSION,
                            PH_HAL4NFC_REVISION,
                            PH_HAL4NFC_PATCH,
                            PH_HAL4NFC_BUILD);
                
        phLibNfc_StackCapabilities->psDevCapabilities.fw_version=
            gpphLibContext->psHwReference->device_info.fw_version;
        phLibNfc_StackCapabilities->psDevCapabilities.hci_version=
            gpphLibContext->psHwReference->device_info.hci_version;
        phLibNfc_StackCapabilities->psDevCapabilities.hw_version=
            gpphLibContext->psHwReference->device_info.hw_version;
        phLibNfc_StackCapabilities->psDevCapabilities.model_id=
            gpphLibContext->psHwReference->device_info.model_id;        
        (void)memcpy(phLibNfc_StackCapabilities->psDevCapabilities.full_version,
            gpphLibContext->psHwReference->device_info.full_version,NXP_FULL_VERSION_LEN);
        /* Check the firmware version */
        if (nxp_nfc_full_version == NULL) {
            // Couldn't load firmware, just pretend we're up to date.
            ALOGW("Firmware image not available: this device might be running old NFC firmware!");
            phLibNfc_StackCapabilities->psDevCapabilities.firmware_update_info = 0;
        } else {
            phLibNfc_StackCapabilities->psDevCapabilities.firmware_update_info = memcmp(phLibNfc_StackCapabilities->psDevCapabilities.full_version, nxp_nfc_full_version,
                       NXP_FULL_VERSION_LEN);
        }

        if(NFCSTATUS_SUCCESS != RetVal)
        {       
            RetVal = NFCSTATUS_FAILED;
        }
    }
    return RetVal;
}






NFCSTATUS phLibNfc_Mgt_ConfigureTestMode(void   *pDriverHandle,
                                 pphLibNfc_RspCb_t   pTestModeCb,
                                 phLibNfc_Cfg_Testmode_t eTstmode,
                                 void                *pContext)
{
     NFCSTATUS Status = NFCSTATUS_SUCCESS;  
     phHal4Nfc_InitType_t eInitType=eInitDefault;
     
     if((NULL == pDriverHandle)||(NULL == pTestModeCb))
     {
        Status = NFCSTATUS_INVALID_PARAMETER;
     }
     else if((NULL != gpphLibContext) && \
         (gpphLibContext->LibNfcState.next_state==eLibNfcHalStateShutdown))
     { 
        Status = NFCSTATUS_SHUTDOWN;
     } 
     else if( (eTstmode == phLibNfc_TstMode_On) && (NULL != gpphLibContext))
     {
        Status=NFCSTATUS_ALREADY_INITIALISED;
     }
     else if( (eTstmode == phLibNfc_TstMode_Off) && (NULL == gpphLibContext))
     {
        Status = NFCSTATUS_NOT_INITIALISED;
     }
     else if( (eTstmode == phLibNfc_TstMode_Off) && (NULL != gpphLibContext))
     {          
        if (NULL!= gpphLibContext->CBInfo.pClientShutdownCb)
        {   /* Previous callback pending */
            Status = NFCSTATUS_BUSY;
        }
        else
        {
            Status = NFCSTATUS_PENDING;
            if(TRUE != gpphLibContext->status.GenCb_pending_status)
            {
                Status = phHal4Nfc_Close(gpphLibContext->psHwReference,
                                    phLibNfc_ShutdownCb,
                                    (void *)gpphLibContext);
            }
            if(Status== NFCSTATUS_PENDING)
            {
                gpphLibContext->CBInfo.pClientShutdownCb = pTestModeCb;
                gpphLibContext->CBInfo.pClientShtdwnCntx = pContext;
                gpphLibContext->status.GenCb_pending_status=TRUE;
                gpphLibContext->LibNfcState.next_state= eLibNfcHalStateShutdown;
            }
            else
            {
                Status =NFCSTATUS_FAILED;
            }
        }       
     }
     else 
     {
            /* Initialize the Lib context */
        gpphLibContext=(pphLibNfc_LibContext_t)phOsalNfc_GetMemory(
                                        (uint32_t)sizeof(phLibNfc_LibContext_t));
        if(NULL == gpphLibContext)
        {
            Status=NFCSTATUS_INSUFFICIENT_RESOURCES;
        }
        else
        {
            (void)memset((void *)gpphLibContext,0,(
                                    (uint32_t)sizeof(phLibNfc_LibContext_t)));

            /* Store the Callback and context in LibContext structure*/
            gpphLibContext->CBInfo.pClientInitCb=pTestModeCb;
            gpphLibContext->CBInfo.pClientInitCntx=pContext;
            /* Initialize the HwReferece structure */
            gpphLibContext->psHwReference=(phHal_sHwReference_t *)
                                    phOsalNfc_GetMemory((uint32_t)sizeof(phHal_sHwReference_t));
            (void)memset((void *)gpphLibContext->psHwReference,0,
                                        ((uint32_t)sizeof(phHal_sHwReference_t)));
            /* Allocate the Memory for the Transceive info */
            if( gpphLibContext->psHwReference!=NULL)
            {
                gpphLibContext->psHwReference->p_board_driver = pDriverHandle;
                Status = phLibNfc_UpdateNextState(gpphLibContext,
                                            eLibNfcHalStateInitandIdle);
                if(Status==NFCSTATUS_SUCCESS)
                {
                    if(eTstmode == phLibNfc_TstMode_On)
                        eInitType = eInitTestModeOn;
                    if(eTstmode == phLibNfc_TstMode_Off)
                        eInitType = eInitDefault;
                    Status=phHal4Nfc_Open(
                                    gpphLibContext->psHwReference,
                                    eInitType,
                                    phLibNfc_InitCb,
                                    (void *)gpphLibContext);
                }
            }
            else
            {
                Status = NFCSTATUS_INSUFFICIENT_RESOURCES;
            }
            phLibNfc_Ndef_Init();
        }
    }
    
   return Status;
}