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

 * Project: NFC FRI 1.1
 *
 * $Date: Fri Apr 23 14:34:08 2010 $
 * $Author: ing07385 $
 * $Revision: 1.53 $
 * $Aliases: NFC_FRI1.1_WK1014_SDK,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1019_SDK,NFC_FRI1.1_WK1024_SDK $
 *
 */

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

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


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

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

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

#define PN544_IO_TIMEOUT_RESPONSE 0x89

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

/* Target discvovery notification callback */
STATIC void phLibNfc_NotificationRegister_Resp_Cb ( 
                                void                             *context,
                                phHal_eNotificationType_t        type,
                                phHal4Nfc_NotificationInfo_t     info,
                                NFCSTATUS                        status
                                );

/*Remote device connect response callback*/
STATIC void phLibNfc_RemoteDev_Connect_Cb(
                           void        *pContext,                           
                           phHal_sRemoteDevInformation_t *pRmtdev_info,
                           NFCSTATUS    status
                           );

#ifdef RECONNECT_SUPPORT
STATIC 
void 
phLibNfc_config_discovery_con_failure_cb (
    void                *context,
    NFCSTATUS           status);
#endif /* #ifdef RECONNECT_SUPPORT */

/*Remote device disconnect response callback*/
STATIC void phLibNfc_RemoteDev_Disconnect_cb(                        
                                void                          *context,
                                phHal_sRemoteDevInformation_t *reg_handle,
                                NFCSTATUS                      status
                                );
/*Remote device Transceive response callback*/
STATIC void phLibNfc_RemoteDev_Transceive_Cb(void *context,
                                phHal_sRemoteDevInformation_t *pRmtdev_info,
                                phNfc_sData_t *response,
                                NFCSTATUS status
                                );
/*Set P2P config paramater response callback*/
STATIC void phLibNfc_Mgt_SetP2P_ConfigParams_Cb(
                                void                             *context,
                                NFCSTATUS                        status
                                );


/*
*************************** Function Definitions ******************************
*/

/**
* Response to target discovery.
*/
STATIC
void phLibNfc_NotificationRegister_Resp_Cb ( 
                                void                            *context,
                                phHal_eNotificationType_t       type,
                                phHal4Nfc_NotificationInfo_t    info,
                                NFCSTATUS                       status
                                )
{
    NFCSTATUS RetVal = NFCSTATUS_SUCCESS,
              Status = NFCSTATUS_SUCCESS;
    uint16_t DeviceIndx, DeviceIndx1;
    uint8_t sak_byte=0;
    uint8_t tag_disc_flg = 0;
    phLibNfc_NtfRegister_RspCb_t pClientCb=NULL;
    pClientCb =gpphLibContext->CBInfo.pClientNtfRegRespCB;
	PHNFC_UNUSED_VARIABLE(context);
    

    if(( type != NFC_DISCOVERY_NOTIFICATION )
        &&(PHNFCSTATUS(status)!=NFCSTATUS_DESELECTED))
    {
        Status = NFCSTATUS_FAILED;
    }
    else if (PHNFCSTATUS(status) == NFCSTATUS_DESELECTED)
    {
        return;
    }
	else
	{
		DeviceIndx=0;DeviceIndx1=0;
		while(DeviceIndx < info.psDiscoveryInfo->NumberOfDevices)
		{
			switch(info.psDiscoveryInfo->ppRemoteDevInfo[DeviceIndx]->RemDevType)
			{
				case  phHal_eMifare_PICC:
				{
					/*Mifare Tag discovered*/
					sak_byte =  info.psDiscoveryInfo->
								ppRemoteDevInfo[DeviceIndx]->RemoteDevInfo.Iso14443A_Info.Sak;
					if((TRUE == gpphLibContext->RegNtfType.MifareUL)&& (sak_byte==0x00))
					{
						/*Copy the tag related info*/
						gpphLibContext->psRemoteDevList[DeviceIndx1].psRemoteDevInfo=
							info.psDiscoveryInfo->ppRemoteDevInfo[DeviceIndx];
						gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev =
							(phLibNfc_Handle)gpphLibContext->psRemoteDevList[DeviceIndx].psRemoteDevInfo;
						gpphLibContext->Discov_handle[DeviceIndx1] = 
							gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev;
						DeviceIndx1++;
						tag_disc_flg++;
					}
                
					if((TRUE == gpphLibContext->RegNtfType.MifareStd)&& 
						(((sak_byte & 0x18)==0x08)||((sak_byte & 0x18)==0x18) ||
                                                (sak_byte == 0x01)))
					{
						/*Copy the tag related info*/
						gpphLibContext->psRemoteDevList[DeviceIndx1].psRemoteDevInfo=
							info.psDiscoveryInfo->ppRemoteDevInfo[DeviceIndx];
						gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev =
							(phLibNfc_Handle)gpphLibContext->psRemoteDevList[DeviceIndx].psRemoteDevInfo;
						gpphLibContext->Discov_handle[DeviceIndx1]= 
							gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev;
						DeviceIndx1++;
						tag_disc_flg++;
					}

				}break;
				case  phHal_eISO14443_A_PICC:
				{
					/*ISO 14443-A type tag discovered*/
					if(TRUE == gpphLibContext->RegNtfType.ISO14443_4A)
					{
						/*Copy the ISO type A tag info*/
						gpphLibContext->psRemoteDevList[DeviceIndx1].psRemoteDevInfo=
								info.psDiscoveryInfo->ppRemoteDevInfo[DeviceIndx];
						gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev =
								(phLibNfc_Handle)gpphLibContext->psRemoteDevList[DeviceIndx].psRemoteDevInfo;
						gpphLibContext->Discov_handle[DeviceIndx1] = 
							gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev;
						DeviceIndx1++;
						tag_disc_flg++;
					}
				}break;
				case  phHal_eISO14443_3A_PICC:
				{
					/*ISO 14443-A type tag discovered*/
					if(TRUE == gpphLibContext->RegNtfType.MifareUL)
					{
						/*Copy the ISO type A tag info*/
						gpphLibContext->psRemoteDevList[DeviceIndx1].psRemoteDevInfo=
								info.psDiscoveryInfo->ppRemoteDevInfo[DeviceIndx];
						gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev =
								(phLibNfc_Handle)gpphLibContext->psRemoteDevList[DeviceIndx].psRemoteDevInfo;
						gpphLibContext->Discov_handle[DeviceIndx1] = 
							gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev;
						DeviceIndx1++;
						tag_disc_flg++;
					}
				}break;
				case  phHal_eISO14443_B_PICC:
				{
					/*ISO 14443-B type tag Discovered */
					if(TRUE == gpphLibContext->RegNtfType.ISO14443_4B)
					{
						/*Copy the Type B tag info */
						gpphLibContext->psRemoteDevList[DeviceIndx1].psRemoteDevInfo=
								info.psDiscoveryInfo->ppRemoteDevInfo[DeviceIndx];
						gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev =
								(phLibNfc_Handle)gpphLibContext->psRemoteDevList[DeviceIndx].psRemoteDevInfo;
						gpphLibContext->Discov_handle[DeviceIndx1] = 
							gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev;
						DeviceIndx1++;
						tag_disc_flg++;
					}
				}break;
				case  phHal_eFelica_PICC:
				{
					/*Felica Type Tag Discovered */
					if(TRUE == gpphLibContext->RegNtfType.Felica)
					{
						/*Copy the Felica tag info */
						gpphLibContext->psRemoteDevList[DeviceIndx1].psRemoteDevInfo=
								info.psDiscoveryInfo->ppRemoteDevInfo[DeviceIndx];
						gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev =
								(phLibNfc_Handle)gpphLibContext->psRemoteDevList[DeviceIndx].psRemoteDevInfo;
						gpphLibContext->Discov_handle[DeviceIndx1] = 
							gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev;
						DeviceIndx1++;
						tag_disc_flg++;
					}
				}break;
				case  phHal_eJewel_PICC:
				{
					/*Jewel Type Tag Discovered */
					if(TRUE == gpphLibContext->RegNtfType.Jewel)
					{
						/*Copy the Felica tag info */
						gpphLibContext->psRemoteDevList[DeviceIndx1].psRemoteDevInfo=
								info.psDiscoveryInfo->ppRemoteDevInfo[DeviceIndx];
						gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev =
								(phLibNfc_Handle)gpphLibContext->psRemoteDevList[DeviceIndx].psRemoteDevInfo;
						gpphLibContext->Discov_handle[DeviceIndx1] = 
							gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev;
						DeviceIndx1++;
						tag_disc_flg++;
					}
				}
				break;
				case  phHal_eISO15693_PICC:
				{
					/*Jewel Type Tag Discovered */
					if(TRUE == gpphLibContext->RegNtfType.ISO15693)
					{
						/*Copy the Felica tag info */
						gpphLibContext->psRemoteDevList[DeviceIndx1].psRemoteDevInfo=
								info.psDiscoveryInfo->ppRemoteDevInfo[DeviceIndx];
						gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev =
								(phLibNfc_Handle)gpphLibContext->psRemoteDevList[DeviceIndx].psRemoteDevInfo;
						gpphLibContext->Discov_handle[DeviceIndx1] = 
							gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev;
						DeviceIndx1++;
						tag_disc_flg++;
					}
				}
				break;
				case  phHal_eNfcIP1_Target:
				{
					if(TRUE == gpphLibContext->RegNtfType.NFC)
					{
						gpphLibContext->psRemoteDevList[DeviceIndx1].psRemoteDevInfo=
								info.psDiscoveryInfo->ppRemoteDevInfo[DeviceIndx];
						gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev =
								(phLibNfc_Handle)gpphLibContext->psRemoteDevList[DeviceIndx].psRemoteDevInfo;
						gpphLibContext->Discov_handle[DeviceIndx1] = 
							gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev;
						DeviceIndx1++;
						tag_disc_flg++;
					}
				}
				break;
				case  phHal_eNfcIP1_Initiator:
				{
					if(TRUE == gpphLibContext->RegNtfType.NFC)
					{
						gpphLibContext->LibNfcState.cur_state=eLibNfcHalStateConnect;
						gpphLibContext->psRemoteDevList[DeviceIndx1].psRemoteDevInfo=
								info.psDiscoveryInfo->ppRemoteDevInfo[DeviceIndx];
						gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev =
								(phLibNfc_Handle)gpphLibContext->psRemoteDevList[DeviceIndx1].psRemoteDevInfo;
						gpphLibContext->sNfcIp_Context.Rem_Initiator_Handle=
								gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev;
						DeviceIndx1++;
						tag_disc_flg++;
					}
				}
				break;
				default :
				{
					break;
				}
			}
			DeviceIndx++;
		}
	}

    if((tag_disc_flg >0 )&&(status != NFCSTATUS_FAILED))
    {
        gpphLibContext->dev_cnt = tag_disc_flg;
        /* Check for if the discovered tags are multiple or
         Multiple protocol tag */
        if((gpphLibContext->dev_cnt > 1)&&(
            (status ==NFCSTATUS_MULTIPLE_PROTOCOLS) ||
            (status ==NFCSTATUS_MULTIPLE_TAGS)) )
        {
            status = status;
        }
        else
        {
            status =NFCSTATUS_SUCCESS;
        }
        /*Notify to upper layer the no of tag discovered and
          the protocol */
        if (NULL != pClientCb)
        {
            pClientCb(
					(void*)gpphLibContext->CBInfo.pClientNtfRegRespCntx,
                    gpphLibContext->psRemoteDevList,
                    gpphLibContext->dev_cnt,
					status
                    );
        }

    }
    else if(PHNFCSTATUS(status)==NFCSTATUS_DESELECTED)
    {
        info.psDiscoveryInfo->NumberOfDevices = 0;
        if (NULL != pClientCb)
        {
            gpphLibContext->LibNfcState.cur_state=eLibNfcHalStateRelease;
            pClientCb((void*)gpphLibContext->CBInfo.pClientNtfRegRespCntx,
                    NULL,
                    0,
                    status);
        }

    }
    else /*Reconfigure the discovery wheel*/
    {
        RetVal = phHal4Nfc_ConfigureDiscovery ( gpphLibContext->psHwReference,
                                            NFC_DISCOVERY_RESUME,
                                            &(gpphLibContext->sADDconfig),
                                            phLibNfc_config_discovery_cb,
                                            gpphLibContext);

        if((RetVal!=NFCSTATUS_SUCCESS) &&(RetVal!=NFCSTATUS_PENDING))
        {
            Status = NFCSTATUS_FAILED;
        }

    }
    if(Status == NFCSTATUS_FAILED)
    {
        if (NULL != pClientCb)
        {
            pClientCb(gpphLibContext->CBInfo.pClientNtfRegRespCntx,
                NULL,
                0,
                Status);
        }
    }
    return;
}

/**
* This interface registers notification handler for target discovery.
*/
NFCSTATUS   
phLibNfc_RemoteDev_NtfRegister( 
                        phLibNfc_Registry_Info_t*       pRegistryInfo,
                        phLibNfc_NtfRegister_RspCb_t    pNotificationHandler,
                        void                            *pContext
                        )
{
    NFCSTATUS RetVal = NFCSTATUS_SUCCESS;
    

    /*Check for valid parameters*/
    if((NULL == pNotificationHandler)
        || (NULL == pContext) 
        ||(NULL== pRegistryInfo))
    {
        RetVal= NFCSTATUS_INVALID_PARAMETER;
    }
    else if((NULL == gpphLibContext) ||
        (gpphLibContext->LibNfcState.cur_state
                            == eLibNfcHalStateShutdown))
    {
        RetVal = NFCSTATUS_NOT_INITIALISED;
    }
    else if(gpphLibContext->LibNfcState.next_state
                            == eLibNfcHalStateShutdown)
    {
        /*Next state is shutdown*/
        RetVal= NFCSTATUS_SHUTDOWN;
    }
    else
    {
        
        PHDBG_INFO("LibNfc:Registering Notification Handler");
                
      
        (void) memcpy(&(gpphLibContext->RegNtfType),pRegistryInfo,
                        sizeof(phLibNfc_Registry_Info_t));
        /* Register Discovery Notification Handler*/     
       
		/*Register for NFCIP1 target type*/        
		RetVal = phHal4Nfc_RegisterNotification(
                                gpphLibContext->psHwReference,
                                eRegisterP2PDiscovery,
                                phLibNfc_NotificationRegister_Resp_Cb,
                                (void*)gpphLibContext
                                );
        /*Register for Tag discovery*/        
		RetVal = phHal4Nfc_RegisterNotification(
                            gpphLibContext->psHwReference,
                            eRegisterTagDiscovery,
                            phLibNfc_NotificationRegister_Resp_Cb,
                            (void*)gpphLibContext
                            );   
        gpphLibContext->CBInfo.pClientNtfRegRespCB = pNotificationHandler;
        gpphLibContext->CBInfo.pClientNtfRegRespCntx = pContext;
        /*Register notification handler with below layer*/
        
    }
    return RetVal;
}
/**
* This interface unregisters notification handler for target discovery.
*/
NFCSTATUS phLibNfc_RemoteDev_NtfUnregister(void)
{
    NFCSTATUS RetVal = NFCSTATUS_SUCCESS;
    if((NULL == gpphLibContext) ||
       (gpphLibContext->LibNfcState.cur_state
                            == eLibNfcHalStateShutdown))
    {
        /*Lib Nfc not Initialized*/
        RetVal = NFCSTATUS_NOT_INITIALISED;
    }
    else if(gpphLibContext->LibNfcState.next_state
                            == eLibNfcHalStateShutdown)
    {
        /*Lib Nfc Shutdown*/
        RetVal= NFCSTATUS_SHUTDOWN;
    }
    else
    {
        /*Unregister notification handler with lower layer */
        RetVal = phHal4Nfc_UnregisterNotification(
                                    gpphLibContext->psHwReference,
                                    eRegisterP2PDiscovery,
                                    gpphLibContext);

		RetVal = phHal4Nfc_UnregisterNotification(
                                    gpphLibContext->psHwReference,
                                    eRegisterTagDiscovery,
                                    gpphLibContext);

        gpphLibContext->CBInfo.pClientNtfRegRespCB = NULL;
        gpphLibContext->CBInfo.pClientNtfRegRespCntx =NULL;
        PHDBG_INFO("LibNfc:Unregister Notification Handler");
    }
    return RetVal;
}

#ifdef RECONNECT_SUPPORT

NFCSTATUS 
phLibNfc_RemoteDev_ReConnect (
    phLibNfc_Handle                 hRemoteDevice,
    pphLibNfc_ConnectCallback_t     pNotifyReConnect_RspCb,
    void                            *pContext)
{

    NFCSTATUS                           ret_val = NFCSTATUS_FAILED;
    phLibNfc_sRemoteDevInformation_t    *psRemoteDevInfo = NULL;

    if ((NULL == gpphLibContext) 
      || (eLibNfcHalStateShutdown == 
        gpphLibContext->LibNfcState.cur_state))
    {
         ret_val = NFCSTATUS_NOT_INITIALISED;        
    }
    else if ((NULL == pContext)
        || (NULL == pNotifyReConnect_RspCb)
        || (NULL == (void *)hRemoteDevice))
    {
        /* Check valid parameters */
        ret_val = NFCSTATUS_INVALID_PARAMETER;
    }   
    /* Check valid lib nfc State */
    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 ((gpphLibContext->Discov_handle[0] != hRemoteDevice)
		&& (gpphLibContext->Discov_handle[1] != hRemoteDevice)
		&& (gpphLibContext->Discov_handle[2] != hRemoteDevice)
		&& (gpphLibContext->Discov_handle[3] != hRemoteDevice)
		&& (gpphLibContext->Discov_handle[4] != hRemoteDevice)
		&& (gpphLibContext->Discov_handle[5] != hRemoteDevice)
		&& (gpphLibContext->Discov_handle[6] != hRemoteDevice)
		&& (gpphLibContext->Discov_handle[7] != hRemoteDevice)
		&& (gpphLibContext->Discov_handle[8] != hRemoteDevice)
		&& (gpphLibContext->Discov_handle[9] != hRemoteDevice))
    {
        ret_val = NFCSTATUS_INVALID_HANDLE;
    }
    else
    {
        psRemoteDevInfo = (phLibNfc_sRemoteDevInformation_t *)hRemoteDevice;
       
        /* Call the HAL connect*/
        ret_val = phHal4Nfc_Connect (gpphLibContext->psHwReference,
                               psRemoteDevInfo,
                               phLibNfc_RemoteDev_Connect_Cb,
                               (void *)gpphLibContext);

        if (NFCSTATUS_PENDING == ret_val)
        {
            /* If HAL Connect is pending update the LibNFC state machine 
                and store the CB pointer and Context,
                mark the General CB pending status is TRUE */
            gpphLibContext->CBInfo.pClientConnectCb = pNotifyReConnect_RspCb;
            gpphLibContext->CBInfo.pClientConCntx = pContext;
            gpphLibContext->status.GenCb_pending_status = TRUE;
			gpphLibContext->LibNfcState.next_state = eLibNfcHalStateConnect;            

            gpphLibContext->Prev_Connected_handle = gpphLibContext->Connected_handle;

			gpphLibContext->Connected_handle = hRemoteDevice;
         }
         else if (NFCSTATUS_INVALID_REMOTE_DEVICE == PHNFCSTATUS(ret_val))
         {
           /* The Handle given for connect is invalid*/
            ret_val = NFCSTATUS_TARGET_NOT_CONNECTED;
         }
         else
         {
            /* Lower layer returns internal error code return NFCSTATUS_FAILED*/
            ret_val = NFCSTATUS_FAILED;
         }        
    }

    return ret_val;
}
#endif /* #ifdef RECONNECT_SUPPORT */


/**
* Connect to a single Remote Device 
*/
NFCSTATUS phLibNfc_RemoteDev_Connect(
                    phLibNfc_Handle             hRemoteDevice,
                    pphLibNfc_ConnectCallback_t pNotifyConnect_RspCb,
                    void                        *pContext
                    )
{

    NFCSTATUS RetVal = NFCSTATUS_FAILED;
    phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo;
    
    if((NULL == gpphLibContext) ||
      (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateShutdown))   
    {
         RetVal = NFCSTATUS_NOT_INITIALISED;        
    }/* Check valid parameters*/
    else if((NULL == pContext)
        || (NULL == pNotifyConnect_RspCb)
        || (NULL == (void*)hRemoteDevice))
    {
       RetVal= NFCSTATUS_INVALID_PARAMETER;
    }   
    /* Check valid lib nfc State*/
    else if(gpphLibContext->LibNfcState.next_state
                            == eLibNfcHalStateShutdown)
    {
        RetVal= NFCSTATUS_SHUTDOWN;
    }
    else if((gpphLibContext->Discov_handle[0] != hRemoteDevice)&&
		(gpphLibContext->Discov_handle[1] != hRemoteDevice)&&
		(gpphLibContext->Discov_handle[2] != hRemoteDevice)&&
		(gpphLibContext->Discov_handle[3] != hRemoteDevice)&&
		(gpphLibContext->Discov_handle[4] != hRemoteDevice)&&
		(gpphLibContext->Discov_handle[5] != hRemoteDevice)&&
		(gpphLibContext->Discov_handle[6] != hRemoteDevice)&&
		(gpphLibContext->Discov_handle[7] != hRemoteDevice)&&
		(gpphLibContext->Discov_handle[8] != hRemoteDevice)&&
		(gpphLibContext->Discov_handle[9] != hRemoteDevice))
    {
        RetVal= NFCSTATUS_INVALID_HANDLE;
    }
    else if ((hRemoteDevice != gpphLibContext->Connected_handle) 
        && (0 != gpphLibContext->Connected_handle))
    {
        RetVal = NFCSTATUS_FAILED;
    }
    else
    {
        psRemoteDevInfo = (phLibNfc_sRemoteDevInformation_t*)hRemoteDevice;
       
        /* Call the HAL connect*/
        RetVal = phHal4Nfc_Connect(gpphLibContext->psHwReference,
                               psRemoteDevInfo,
                               phLibNfc_RemoteDev_Connect_Cb,
                               (void* )gpphLibContext);
        if(RetVal== NFCSTATUS_PENDING)
        {
            /* If HAL Connect is pending update the LibNFC state machine 
                and store the CB pointer and Context,
                mark the General CB pending status is TRUE*/
            gpphLibContext->CBInfo.pClientConnectCb = pNotifyConnect_RspCb;
            gpphLibContext->CBInfo.pClientConCntx = pContext;
            gpphLibContext->status.GenCb_pending_status=TRUE;
			gpphLibContext->LibNfcState.next_state = eLibNfcHalStateConnect;            
            gpphLibContext->Prev_Connected_handle = gpphLibContext->Connected_handle;
			gpphLibContext->Connected_handle = hRemoteDevice;
         }
         else if(PHNFCSTATUS(RetVal) == NFCSTATUS_INVALID_REMOTE_DEVICE)
         {
           /* The Handle given for connect is invalid*/
            RetVal= NFCSTATUS_TARGET_NOT_CONNECTED;
         }
         else
         {
            /* Lower layer returns internal error code return NFCSTATUS_FAILED*/
            RetVal = NFCSTATUS_FAILED;
         }        
    }
    return RetVal;
}

#ifdef RECONNECT_SUPPORT
STATIC 
void 
phLibNfc_config_discovery_con_failure_cb (
    void                *context,
    NFCSTATUS           status)
{
    if((phLibNfc_LibContext_t *)context == gpphLibContext)      
    {   /*check for same context*/
        pphLibNfc_ConnectCallback_t    ps_client_con_cb = 
                                    gpphLibContext->CBInfo.pClientConnectCb;

        if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state)
        {
            /*If shutdown called in between allow shutdown to happen*/
            phLibNfc_Pending_Shutdown();
            status = NFCSTATUS_SHUTDOWN;
        }
        else
        {
            gpphLibContext->status.GenCb_pending_status = FALSE;
            gpphLibContext->status.DiscEnbl_status = FALSE;
            status = NFCSTATUS_TARGET_LOST;

            phLibNfc_UpdateCurState (status,gpphLibContext);
#ifdef RESTART_CFG
            if(gpphLibContext->status.Discovery_pending_status == TRUE)
            {
                NFCSTATUS RetStatus = NFCSTATUS_FAILED;
                /* Application has called discovery before receiving this callback,
                so NO notification to the upper layer, instead lower layer
                discovery is called */
                gpphLibContext->status.Discovery_pending_status = FALSE;
                RetStatus =  phHal4Nfc_ConfigureDiscovery(
                        gpphLibContext->psHwReference,
                        gpphLibContext->eLibNfcCfgMode,
                        &gpphLibContext->sADDconfig,
                        (pphLibNfc_RspCb_t)
                        phLibNfc_config_discovery_cb,
                        (void *)gpphLibContext);
                if (NFCSTATUS_PENDING == RetStatus)
                {
                    (void)phLibNfc_UpdateNextState(gpphLibContext,
                                            eLibNfcHalStateConfigReady);
                    gpphLibContext->status.GenCb_pending_status = TRUE;
                    gpphLibContext->status.DiscEnbl_status = TRUE;
                }
            }

#endif /* #ifdef RESTART_CFG */
        }

        if (NULL != ps_client_con_cb)
        {
            gpphLibContext->CBInfo.pClientConnectCb = NULL;
            /* Call the upper layer callback*/      
            ps_client_con_cb (gpphLibContext->CBInfo.pClientConCntx,
                            0, NULL, status);
        }
    } /*End of if-context check*/
    else
    {   /*exception: wrong context pointer returned*/
        phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1);
        status = NFCSTATUS_FAILED;
    }

    
}
#endif /* #ifdef RECONNECT_SUPPORT */
/**
* Response callback for remote device connect
*/
STATIC void phLibNfc_RemoteDev_Connect_Cb(
                           void        *pContext,
                           phHal_sRemoteDevInformation_t *pRmtdev_info,
                           NFCSTATUS    status
                           )
{
    NFCSTATUS             Connect_status = NFCSTATUS_SUCCESS;
    /*Check valid lib nfc context is returned from lower layer*/
    if((phLibNfc_LibContext_t *)pContext == gpphLibContext)
    {
        gpphLibContext->LastTrancvSuccess = FALSE;

        /* Mark General Callback pending status as false*/
        gpphLibContext->status.GenCb_pending_status = FALSE;
        
        /* Check the shutdown is called during the lower layer Connect in process,
           If yes call shutdown call and return NFCSTATUS_SHUTDOWN */
        if((eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state))
        {   
            phLibNfc_Pending_Shutdown();
            Connect_status = NFCSTATUS_SHUTDOWN;    
    
        }
        else if(PHNFCSTATUS(status)==NFCSTATUS_SUCCESS)
        {
            /* Copy the Remote device address as connected handle*/
            gpphLibContext->Connected_handle = (uintptr_t)pRmtdev_info;
            /* Update the state to connected and return status as SUCCESS*/
            gpphLibContext->LibNfcState.next_state = eLibNfcHalStateConnect;
            Connect_status = NFCSTATUS_SUCCESS;
        }
        else 
        {  /* if(PHNFCSTATUS(status)==NFCSTATUS_INVALID_REMOTE_DEVICE) */
            /* If remote device is invalid return as TARGET LOST to upper layer*/
            /* If error code is other than SUCCESS return NFCSTATUS_TARGET_LOST */
            Connect_status = NFCSTATUS_TARGET_LOST;
            gpphLibContext->Connected_handle = gpphLibContext->Prev_Connected_handle ;
        }
        gpphLibContext->ndef_cntx.is_ndef = CHK_NDEF_NOT_DONE;
        /* Update the Current Sate*/
        phLibNfc_UpdateCurState(Connect_status,(phLibNfc_LibContext_t *)pContext);
        /* Call the upper layer callback*/      
        gpphLibContext->CBInfo.pClientConnectCb(
                    gpphLibContext->CBInfo.pClientConCntx,
                    (phLibNfc_Handle)pRmtdev_info,
                    (phLibNfc_sRemoteDevInformation_t*)pRmtdev_info,
                    Connect_status);
    }
    else
    {   /*exception: wrong context pointer returned*/
        phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1);
    }
    return;
}

/**
* Allows to disconnect from already connected target.
*/
NFCSTATUS phLibNfc_RemoteDev_Disconnect( phLibNfc_Handle                 hRemoteDevice,
                                        phLibNfc_eReleaseType_t          ReleaseType,
                                        pphLibNfc_DisconnectCallback_t   pDscntCallback,
                                        void*                            pContext
                                        )
{
    NFCSTATUS RetVal = NFCSTATUS_SUCCESS;
    phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo=NULL;

    /*Check for valid parameter*/
    if((NULL == gpphLibContext) ||
        (gpphLibContext->LibNfcState.cur_state
                            == eLibNfcHalStateShutdown))
    {
        RetVal = NFCSTATUS_NOT_INITIALISED;        
    }
    else if((NULL == pContext) ||
        (NULL == pDscntCallback)||(hRemoteDevice == 0))
    {
        RetVal= NFCSTATUS_INVALID_PARAMETER;
    }
    /* Check for valid state,If De initialize is called then
    return NFCSTATUS_SHUTDOWN */
    else if(gpphLibContext->LibNfcState.next_state
                            == eLibNfcHalStateShutdown)
    {
        RetVal= NFCSTATUS_SHUTDOWN;
    }
    else if(gpphLibContext->Connected_handle==0)
    {
        RetVal=NFCSTATUS_TARGET_NOT_CONNECTED;
    }
    /* The given handle is not the connected handle return NFCSTATUS_INVALID_HANDLE*/
    else if(hRemoteDevice != gpphLibContext->Connected_handle )
    {
        RetVal=NFCSTATUS_INVALID_HANDLE;
    }
    else
    {
        if((eLibNfcHalStateRelease == gpphLibContext->LibNfcState.next_state)
            ||((gpphLibContext->sSeContext.eActivatedMode == phLibNfc_SE_ActModeWired)&&
                    (ReleaseType != NFC_SMARTMX_RELEASE))
                    ||((gpphLibContext->sSeContext.eActivatedMode != phLibNfc_SE_ActModeWired)&&
                            (ReleaseType == NFC_SMARTMX_RELEASE)))
        {   /* Previous disconnect callback is pending */
            RetVal = NFCSTATUS_REJECTED;            
        }
#ifndef LLCP_CHANGES
        else if(eLibNfcHalStateTransaction == gpphLibContext->LibNfcState.next_state)
        {   /* Previous  Transaction is Pending*/
            RetVal = NFCSTATUS_BUSY;            
            PHDBG_INFO("LibNfc:Transaction is Pending");
        }
#endif /* #ifdef LLCP_CHANGES */
        else
        {           
            gpphLibContext->ReleaseType = ReleaseType;
            psRemoteDevInfo = (phLibNfc_sRemoteDevInformation_t*)hRemoteDevice;
            RetVal = phHal4Nfc_Disconnect(gpphLibContext->psHwReference,
                                (phHal_sRemoteDevInformation_t*)psRemoteDevInfo,
                                gpphLibContext->ReleaseType,
                                (pphHal4Nfc_DiscntCallback_t)
                                phLibNfc_RemoteDev_Disconnect_cb,
                                (void *)gpphLibContext);
            if( NFCSTATUS_PENDING == PHNFCSTATUS(RetVal))
            {
                /*Copy the upper layer Callback pointer and context*/
                gpphLibContext->CBInfo.pClientDisConnectCb = pDscntCallback;
                gpphLibContext->CBInfo.pClientDConCntx = pContext;
                /* Mark general callback pending status as TRUE and update the state*/
                gpphLibContext->status.GenCb_pending_status=TRUE;
				gpphLibContext->LibNfcState.next_state = eLibNfcHalStateRelease; 
                
            }
            else
            {
                /*If lower layer returns other than pending 
                (internal error codes) return NFCSTATUS_FAILED */
                RetVal = NFCSTATUS_FAILED;
            }    
        }
    }
    return RetVal;
}
/**
* Response callback for Remote device Disconnect.
*/
STATIC void phLibNfc_RemoteDev_Disconnect_cb(
                                void                          *context,
                                phHal_sRemoteDevInformation_t *reg_handle,
                                NFCSTATUS                      status
                                )
{
    NFCSTATUS             DisCnct_status = NFCSTATUS_SUCCESS;
    pphLibNfc_DisconnectCallback_t pUpper_NtfCb = NULL;
        void  *pUpper_Context = NULL;
    
    /* Copy the upper layer Callback and context*/
    pUpper_NtfCb = gpphLibContext->CBInfo.pClientDisConnectCb;
    pUpper_Context = gpphLibContext->CBInfo.pClientDConCntx;

    /* Check valid context is returned or not */
    if((phLibNfc_LibContext_t *)context != gpphLibContext)
    {
        /*exception: wrong context pointer returned*/
        phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1);
    }
    else
    {
        /* Mark the General callback pending status FALSE   */
        gpphLibContext->status.GenCb_pending_status = FALSE;        
        gpphLibContext->CBInfo.pClientDisConnectCb = NULL;
        gpphLibContext->CBInfo.pClientDConCntx = NULL;
        
        gpphLibContext->ndef_cntx.is_ndef = CHK_NDEF_NOT_DONE;
        gpphLibContext->LastTrancvSuccess = FALSE;
        /*Reset Connected handle */
        gpphLibContext->Connected_handle=0x0000;
        /*Reset previous Connected handle */
        gpphLibContext->Prev_Connected_handle = 0x0000;

        if(gpphLibContext->sSeContext.eActivatedMode == phLibNfc_SE_ActModeWired)
        {
          gpphLibContext->sSeContext.eActivatedMode = phLibNfc_SE_ActModeDefault;
        }
        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;
        }
    }   
    /* Check DeInit is called or not */
    if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state)
    {
        /*call shutdown and return  status as NFCSTATUS_SHUTDOWN */ 
        phLibNfc_Pending_Shutdown();
        DisCnct_status = NFCSTATUS_SHUTDOWN;    
    }
    else if(NFCSTATUS_SUCCESS == status)
    {
        DisCnct_status = NFCSTATUS_SUCCESS;     
		gpphLibContext->LibNfcState.next_state = eLibNfcHalStateRelease;         
    }
    else
    {           
        DisCnct_status = NFCSTATUS_FAILED;
        phLibNfc_UpdateCurState(DisCnct_status,(phLibNfc_LibContext_t *)context);
    }
    /* Call the upper layer Callback */
    (*pUpper_NtfCb)(pUpper_Context,
                    (phLibNfc_Handle)reg_handle,
                    DisCnct_status);
    return;
}

/**
* This interface allows to perform Read/write operation on remote device.
*/
NFCSTATUS
phLibNfc_RemoteDev_Transceive(phLibNfc_Handle                   hRemoteDevice,
                              phLibNfc_sTransceiveInfo_t*       psTransceiveInfo,
                              pphLibNfc_TransceiveCallback_t    pTransceive_RspCb,
                              void*                             pContext
                              )
{
    NFCSTATUS RetVal = NFCSTATUS_SUCCESS;
    
    /*Check for valid parameter */
    
    if((NULL == gpphLibContext) ||
        (gpphLibContext->LibNfcState.cur_state
                            == eLibNfcHalStateShutdown))
    {
        RetVal = NFCSTATUS_NOT_INITIALISED;
    }
    else if((NULL == psTransceiveInfo)
        || (NULL == pTransceive_RspCb)
        || (NULL == (void *)hRemoteDevice)
        || (NULL == psTransceiveInfo->sRecvData.buffer)
        || (NULL == psTransceiveInfo->sSendData.buffer)
        || (NULL == pContext))
    {
        RetVal= NFCSTATUS_INVALID_PARAMETER;        
    }
    /* Check the state for DeInit is called or not,if yes return NFCSTATUS_SHUTDOWN*/
    else if(gpphLibContext->LibNfcState.next_state
                            == eLibNfcHalStateShutdown)
    {       
        RetVal= NFCSTATUS_SHUTDOWN;
    }/* If there is no handle connected return NFCSTATUS_TARGET_NOT_CONNECTED*/
    else if(gpphLibContext->Connected_handle==0)
    {
        RetVal=NFCSTATUS_TARGET_NOT_CONNECTED;
    }/* If the given handle is not the connected handle return NFCSTATUS_INVALID_HANDLE */
	else if(gpphLibContext->Connected_handle!= hRemoteDevice )
    {
        RetVal=NFCSTATUS_INVALID_HANDLE;
    } /*If the transceive is called before finishing the previous transceive function
      return NFCSTATUS_REJECTED  */
    else if((eLibNfcHalStateTransaction ==
        gpphLibContext->LibNfcState.next_state)
        ||(phHal_eNfcIP1_Initiator==
        ((phHal_sRemoteDevInformation_t*)hRemoteDevice)->RemDevType))
    {
        RetVal = NFCSTATUS_REJECTED;
    }         
#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->ndef_cntx.eLast_Call = RawTrans;
        (void)memcpy((void *)(gpphLibContext->psTransInfo), 
                    (void *)psTransceiveInfo, 
                    sizeof(phLibNfc_sTransceiveInfo_t));
        /* Check the given Mifare command is supported or not , 
                            If not return NFCSTATUS_COMMAND_NOT_SUPPORTED */
        if( (((phHal_sRemoteDevInformation_t*)hRemoteDevice)->RemDevType == 
               phHal_eMifare_PICC)&&
            ( gpphLibContext->psTransInfo->cmd.MfCmd != phHal_eMifareRaw ) &&
            ( gpphLibContext->psTransInfo->cmd.MfCmd != phHal_eMifareAuthentA ) &&
            ( gpphLibContext->psTransInfo->cmd.MfCmd != phHal_eMifareAuthentB ) &&
            ( gpphLibContext->psTransInfo->cmd.MfCmd != phHal_eMifareRead16 ) &&
            ( gpphLibContext->psTransInfo->cmd.MfCmd != phHal_eMifareRead ) &&
            ( gpphLibContext->psTransInfo->cmd.MfCmd != phHal_eMifareWrite16 ) &&
            ( gpphLibContext->psTransInfo->cmd.MfCmd != phHal_eMifareWrite4 ) &&
            ( gpphLibContext->psTransInfo->cmd.MfCmd != phHal_eMifareDec ) &&
            ( gpphLibContext->psTransInfo->cmd.MfCmd != phHal_eMifareTransfer ) &&
            ( gpphLibContext->psTransInfo->cmd.MfCmd != phHal_eMifareRestore ) &&
            ( gpphLibContext->psTransInfo->cmd.MfCmd != phHal_eMifareReadSector ) &&
            ( gpphLibContext->psTransInfo->cmd.MfCmd != phHal_eMifareWriteSector ))
        {
            RetVal = NFCSTATUS_COMMAND_NOT_SUPPORTED;
        }           
        if(eLibNfcHalStatePresenceChk !=
                     gpphLibContext->LibNfcState.next_state)
        {
            PHDBG_INFO("LibNfc:Transceive In Progress");
            if((((phHal_sRemoteDevInformation_t*)hRemoteDevice)->RemDevType == 
               phHal_eMifare_PICC) && (((phHal_sRemoteDevInformation_t*)
               hRemoteDevice)->RemoteDevInfo.Iso14443A_Info.Sak != 0)&&
               (phHal_eMifareAuthentA == gpphLibContext->psTransInfo->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 = psTransceiveInfo->addr;
                gpphLibContext->psBufferedAuth->cmd = psTransceiveInfo->cmd;
                gpphLibContext->psBufferedAuth->sSendData.length 
                    = psTransceiveInfo->sSendData.length;
                gpphLibContext->psBufferedAuth->sRecvData.length 
                    = psTransceiveInfo->sRecvData.length;                
                gpphLibContext->psBufferedAuth->sSendData.buffer
                  = (uint8_t *)
                      phOsalNfc_GetMemory(
                      gpphLibContext->psTransInfo->sSendData.length);
                
                (void)memcpy((void *)
                        (gpphLibContext->psBufferedAuth->sSendData.buffer), 
                        (void *)psTransceiveInfo->sSendData.buffer, 
                        psTransceiveInfo->sSendData.length);
               
                gpphLibContext->psBufferedAuth->sRecvData.buffer
                  = (uint8_t *)
                      phOsalNfc_GetMemory(
                        gpphLibContext->psTransInfo->sRecvData.length);             
            }
            /*Call the lower layer Transceive function */
            RetVal = phHal4Nfc_Transceive( gpphLibContext->psHwReference,
                                        (phHal_sTransceiveInfo_t*)gpphLibContext->psTransInfo,
                                        (phLibNfc_sRemoteDevInformation_t*)hRemoteDevice,
                                        (pphHal4Nfc_TransceiveCallback_t)
                                        phLibNfc_RemoteDev_Transceive_Cb,
                                        (void* )gpphLibContext);
            if(PHNFCSTATUS(RetVal) == NFCSTATUS_PENDING)
            {
                /* Copy the upper layer callback pointer and context */
                gpphLibContext->CBInfo.pClientTransceiveCb = pTransceive_RspCb;
                gpphLibContext->CBInfo.pClientTranseCntx = pContext;
                /* Mark the General callback pending status is TRUE */
                gpphLibContext->status.GenCb_pending_status = TRUE;
                /*Transceive is in Progress-Used in Release API*/

                /*Update the state machine*/
                gpphLibContext->LibNfcState.next_state = eLibNfcHalStateTransaction;
            }
        }       
        else
        {
            gpphLibContext->status.GenCb_pending_status = FALSE;
            RetVal = NFCSTATUS_FAILED;
        }       
    }
    return RetVal;
}
/**
* Response for Remote device transceive.
*/
STATIC 
void phLibNfc_RemoteDev_Transceive_Cb(void *context,
                                    phHal_sRemoteDevInformation_t *pRmtdev_info,
                                    phNfc_sData_t *response,
                                    NFCSTATUS status
                                    )
{
    NFCSTATUS             trans_status = NFCSTATUS_SUCCESS;
    phNfc_sData_t         *trans_resp= NULL;
    void                  *pUpper_Context = NULL;
    pphLibNfc_TransceiveCallback_t pUpper_TagNtfCb =
                            gpphLibContext->CBInfo.pClientTransceiveCb;

    /*Check valid context is returned or not */
    if((phLibNfc_LibContext_t *)context == gpphLibContext)
    {
        trans_resp = &gpphLibContext->psTransInfo->sRecvData;

        pUpper_Context = gpphLibContext->CBInfo.pClientTranseCntx;
        gpphLibContext->status.GenCb_pending_status = FALSE;

        /*If DeInit is called during the transceive,
           call the shutdown and return NFCSTATUS_SHUTDOWN*/
        if(gpphLibContext->LibNfcState.next_state
                            == eLibNfcHalStateShutdown)
        {
            phLibNfc_Pending_Shutdown();
            trans_status = NFCSTATUS_SHUTDOWN;
        }
         /* If Disconnect is called return NFCSTATUS_ABORTED */
        else if(eLibNfcHalStateRelease == 
                gpphLibContext->LibNfcState.next_state)
        {
            trans_status = NFCSTATUS_ABORTED;
        }
        /* If the received lower layer status is not SUCCESS return NFCSTATUS_FAILED */
        else if( NFCSTATUS_SUCCESS == status)
        {
            trans_status = NFCSTATUS_SUCCESS;
        }        
        else if((PHNFCSTATUS(status) != NFCSTATUS_SUCCESS) &&
                (phHal_eMifare_PICC == pRmtdev_info->RemDevType) && 
                (0x00 != pRmtdev_info->RemoteDevInfo.Iso14443A_Info.Sak))
        {
            gpphLibContext->LastTrancvSuccess = FALSE;
            trans_status = NFCSTATUS_FAILED;
            /* card type is mifare 1k/4k, then reconnect */
            trans_status = phHal4Nfc_Connect(gpphLibContext->psHwReference,  
                        pRmtdev_info,
                        (pphHal4Nfc_ConnectCallback_t)
                        phLibNfc_Reconnect_Mifare_Cb,
                        (void *)gpphLibContext);
        }
        else if ((PHNFCSTATUS(status) == PN544_IO_TIMEOUT_RESPONSE) ||
                 (PHNFCSTATUS(status) == NFCSTATUS_RF_TIMEOUT))
        {
            // 0x89, 0x09 HCI response values from PN544 indicate timeout
            trans_status = NFCSTATUS_TARGET_LOST;
        }
        else
        {
            // PN544 did get some reply from tag, just not valid
            trans_status = NFCSTATUS_FAILED;
        }
        /*Update the state machine */
        phLibNfc_UpdateCurState(status,gpphLibContext);
        gpphLibContext->LibNfcState.next_state = eLibNfcHalStateConnect;
        if(NFCSTATUS_PENDING != trans_status)  
        {
            /* Tranceive over */              
            PHDBG_INFO("LibNfc:TXRX Callback-Update the Transceive responce");
            if (NULL != pUpper_TagNtfCb)
            {
                if(trans_status == NFCSTATUS_SUCCESS)
                {
                    gpphLibContext->LastTrancvSuccess = TRUE;
                    pUpper_Context = gpphLibContext->CBInfo.pClientTranseCntx;
                    trans_resp->buffer = response->buffer;
                    trans_resp->length = response->length;                  
                            /* Notify the upper layer */
                    PHDBG_INFO("LibNfc:Transceive Complete");
                    /* Notify the Transceive Completion to upper layer */
                    gpphLibContext->CBInfo.pClientTransceiveCb(pUpper_Context,
                                (phLibNfc_Handle)pRmtdev_info,
                                trans_resp,
                                trans_status);
                }
                else
                {
                    gpphLibContext->LastTrancvSuccess = FALSE;
                    pUpper_Context = gpphLibContext->CBInfo.pClientTranseCntx;                  
                    trans_resp->length = 0;                     
                            /* Notify the upper layer */
                    PHDBG_INFO("LibNfc:Transceive Complete");
                    /* Notify the Transceive Completion to upper layer */
                    gpphLibContext->CBInfo.pClientTransceiveCb(pUpper_Context,
                                (phLibNfc_Handle)pRmtdev_info,
                                trans_resp,
                                trans_status);
                }
            }
       }
       
    }
    else
    {    /*exception: wrong context pointer returned*/
        phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1);
    }

    return;
}
/**
* Interface to configure P2P configurations.
*/
NFCSTATUS 
phLibNfc_Mgt_SetP2P_ConfigParams(phLibNfc_sNfcIPCfg_t*		pConfigInfo,
                                pphLibNfc_RspCb_t			pConfigRspCb,
                                void*						pContext
                                )
{
    NFCSTATUS RetVal = NFCSTATUS_FAILED;
    /* LibNfc Initialized or not */
    if((NULL == gpphLibContext)|| 
        (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateShutdown))
    {
        RetVal = NFCSTATUS_NOT_INITIALISED;
    }/* Check for valid parameters */
    else if((NULL == pConfigInfo) || (NULL == pConfigRspCb)
        || (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 callback is pending */
        RetVal = NFCSTATUS_BUSY;
    }
    else
    {
        if(eLibNfcHalStatePresenceChk !=
                gpphLibContext->LibNfcState.next_state)
        {
            phHal_uConfig_t uConfig;  
            /* copy General bytes of Max length = 48 bytes */
            (void)memcpy((void *)&(uConfig.nfcIPConfig.generalBytes),
                    (void *)pConfigInfo->generalBytes,
                    pConfigInfo->generalBytesLength);
            /* also copy the General Bytes length*/
            uConfig.nfcIPConfig.generalBytesLength = pConfigInfo->generalBytesLength;

            RetVal = phHal4Nfc_ConfigParameters(                                    
                                gpphLibContext->psHwReference,
                                NFC_P2P_CONFIG,
                                &uConfig,
                                phLibNfc_Mgt_SetP2P_ConfigParams_Cb,
                                (void *)gpphLibContext
                                );          
        }
        else
        {
             gpphLibContext->sNfcIp_Context.pClientNfcIpCfgCb= NULL;
             RetVal = NFCSTATUS_PENDING;
        }
        if(NFCSTATUS_PENDING == RetVal)
        {
            /* save the context and callback for later use */
            gpphLibContext->sNfcIp_Context.pClientNfcIpCfgCb = pConfigRspCb;
            gpphLibContext->sNfcIp_Context.pClientNfcIpCfgCntx = pContext;
            gpphLibContext->status.GenCb_pending_status=TRUE;
            /* Next state is configured */
            gpphLibContext->LibNfcState.next_state =eLibNfcHalStateConfigReady;            
        }       
        else
        {
            RetVal = NFCSTATUS_FAILED;
        }
    }
    return RetVal;
}
/**
* Response callback for P2P configurations.
*/
STATIC void phLibNfc_Mgt_SetP2P_ConfigParams_Cb(void     *context,
                                        NFCSTATUS status)
{
        pphLibNfc_RspCb_t       pClientCb=NULL;    
    void                    *pUpperLayerContext=NULL;
     /* Check for the context returned by below layer */
    if((phLibNfc_LibContext_t *)context != gpphLibContext)
    {   /*wrong context returned*/
        phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1);
    }
    else
    {
        if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state)
        {   /*shutdown called before completion of this api allow
            shutdown to happen */
            phLibNfc_Pending_Shutdown();
            status = NFCSTATUS_SHUTDOWN;    
        }
        else
        {
            gpphLibContext->status.GenCb_pending_status = FALSE;
            if(NFCSTATUS_SUCCESS != status)
            {   
                status = NFCSTATUS_FAILED;
            }
            else
            {
                status = NFCSTATUS_SUCCESS;
            }
        }
        /*update the current state */
        phLibNfc_UpdateCurState(status,gpphLibContext);

        pClientCb = gpphLibContext->sNfcIp_Context.pClientNfcIpCfgCb;
        pUpperLayerContext = gpphLibContext->sNfcIp_Context.pClientNfcIpCfgCntx;

        gpphLibContext->sNfcIp_Context.pClientNfcIpCfgCb = NULL;
        gpphLibContext->sNfcIp_Context.pClientNfcIpCfgCntx = NULL;
        if (NULL != pClientCb)
        {
            /* Notify to upper layer status of configure operation */
            pClientCb(pUpperLayerContext, status);
        }
    }   
    return;
}