/*
* 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_discovery.c
* Project: NFC FRI 1.1
*
* $Date: Mon Mar 1 19:02:41 2010 $
* $Author: ing07385 $
* $Revision: 1.36 $
* $Aliases: NFC_FRI1.1_WK1008_SDK,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1007_SDK,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_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 **********************************
*/
/*
*************************** Static Function Declaration ***********************
*/
/*Remote device Presence check callback*/
STATIC void phLibNfc_RemoteDev_CheckPresence_Cb(void *context,
NFCSTATUS status);
/**Used for presence chk incase of mifare std tags*/
STATIC void phLibNfc_ChkPresence_Trcv_Cb(
void *context,
phHal_sRemoteDevInformation_t *psRemoteDevInfo,
phNfc_sData_t *response,
NFCSTATUS status
);
/*
*************************** Function Definitions ******************************
*/
void phLibNfc_config_discovery_cb(void *context,
NFCSTATUS status)
{
if((phLibNfc_LibContext_t *)context == gpphLibContext)
{ /*check for same context*/
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;
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;
}
else
{
status = NFCSTATUS_FAILED;
}
}
#endif /* #ifdef RESTART_CFG */
}
} /*End of if-context check*/
else
{ /*exception: wrong context pointer returned*/
phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1);
status = NFCSTATUS_FAILED;
}
if(gpphLibContext->CBInfo.pClientDisConfigCb!=NULL)
{
gpphLibContext->CBInfo.pClientDisConfigCb(gpphLibContext->CBInfo.pClientDisCfgCntx,status);
gpphLibContext->CBInfo.pClientDisConfigCb=NULL;
}
return;
}
/**
* Configure Discovery Modes.
* This function is used to configure ,start and stop the discovery wheel.
*/
NFCSTATUS phLibNfc_Mgt_ConfigureDiscovery (
phLibNfc_eDiscoveryConfigMode_t DiscoveryMode,
phLibNfc_sADD_Cfg_t sADDSetup,
pphLibNfc_RspCb_t pConfigDiscovery_RspCb,
void* pContext
)
{
NFCSTATUS RetVal = NFCSTATUS_FAILED;
phHal_sADD_Cfg_t *psADDConfig;
psADDConfig = (phHal_sADD_Cfg_t *)&(sADDSetup);
if((NULL == gpphLibContext) ||
(gpphLibContext->LibNfcState.cur_state
== eLibNfcHalStateShutdown))
{
/*Lib Nfc not initialized*/
RetVal = NFCSTATUS_NOT_INITIALISED;
}
/* Check for Valid parameters*/
else if((NULL == pContext) || (NULL == pConfigDiscovery_RspCb))
{
RetVal= NFCSTATUS_INVALID_PARAMETER;
}
else if(gpphLibContext->LibNfcState.next_state
== eLibNfcHalStateShutdown)
{
RetVal= NFCSTATUS_SHUTDOWN;
}
else
{
gpphLibContext->eLibNfcCfgMode =DiscoveryMode;
gpphLibContext->sADDconfig = sADDSetup;
if(gpphLibContext->status.DiscEnbl_status != TRUE)
{
/* call lower layer config API for the discovery
configuration sent by the application */
RetVal = phHal4Nfc_ConfigureDiscovery ( gpphLibContext->psHwReference,
DiscoveryMode,
psADDConfig,
(pphLibNfc_RspCb_t)
phLibNfc_config_discovery_cb,
(void*)gpphLibContext);
if(PHNFCSTATUS(RetVal) == NFCSTATUS_PENDING)
{
gpphLibContext->status.DiscEnbl_status = TRUE;
/* Copy discovery callback and its context */
gpphLibContext->CBInfo.pClientDisConfigCb = pConfigDiscovery_RspCb;
gpphLibContext->CBInfo.pClientDisCfgCntx = pContext;
gpphLibContext->status.GenCb_pending_status = TRUE;
gpphLibContext->LibNfcState.next_state = eLibNfcHalStateConfigReady;
}
else
{
RetVal=NFCSTATUS_FAILED;
}
}
else
{
RetVal=NFCSTATUS_BUSY;
}
}
return RetVal;
}
/**
* Check for target presence.
* Checks given target is present in RF filed or not
*/
NFCSTATUS phLibNfc_RemoteDev_CheckPresence( phLibNfc_Handle hTargetDev,
pphLibNfc_RspCb_t pPresenceChk_RspCb,
void* pRspCbCtx
)
{
NFCSTATUS RetVal = NFCSTATUS_FAILED;
phHal_sRemoteDevInformation_t *ps_rem_dev_info = NULL;
/* Check for valid sate */
if((NULL == gpphLibContext) ||
(gpphLibContext->LibNfcState.cur_state
== eLibNfcHalStateShutdown))
{
RetVal = NFCSTATUS_NOT_INITIALISED;
}
/* Check for valid parameters*/
else if((NULL == pRspCbCtx) || (NULL == pPresenceChk_RspCb)
|| (hTargetDev == 0) )
{
RetVal= NFCSTATUS_INVALID_PARAMETER;
}
/* Check for DeInit call*/
else if(gpphLibContext->LibNfcState.next_state
== eLibNfcHalStateShutdown)
{
RetVal = NFCSTATUS_SHUTDOWN;
}
/* Check target is connected or not */
else if( gpphLibContext->Connected_handle == 0)
{
RetVal = NFCSTATUS_TARGET_NOT_CONNECTED;
}
/* Check given handle is valid or not*/
else if(hTargetDev != 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
{
ps_rem_dev_info = (phHal_sRemoteDevInformation_t *)
gpphLibContext->Connected_handle;
if((phHal_eMifare_PICC == ps_rem_dev_info->RemDevType)
&&(0 != ps_rem_dev_info->RemoteDevInfo.Iso14443A_Info.Sak)
&&(TRUE == gpphLibContext->LastTrancvSuccess))
{
/* Call HAL4 API */
RetVal = phHal4Nfc_Transceive(
gpphLibContext->psHwReference,
gpphLibContext->psBufferedAuth,
(phHal_sRemoteDevInformation_t *)
gpphLibContext->Connected_handle,
(pphHal4Nfc_TransceiveCallback_t )
phLibNfc_ChkPresence_Trcv_Cb,
(void *)gpphLibContext
);
}
else
{
/* Call lower layer PresenceCheck function */
RetVal = phHal4Nfc_PresenceCheck(gpphLibContext->psHwReference,
phLibNfc_RemoteDev_CheckPresence_Cb,
(void *)gpphLibContext);
}
if( NFCSTATUS_PENDING == PHNFCSTATUS(RetVal))
{
gpphLibContext->CBInfo.pClientPresChkCb = pPresenceChk_RspCb;
gpphLibContext->CBInfo.pClientPresChkCntx = pRspCbCtx;
/* Mark General callback pending status as TRUE*/
gpphLibContext->status.GenCb_pending_status = TRUE;
/* Update the state machine*/
gpphLibContext->LibNfcState.next_state = eLibNfcHalStatePresenceChk;
}
else /* If return value is internal error(other than pending ) return NFCSTATUS_FAILED*/
{
RetVal = NFCSTATUS_FAILED;
}
}
return RetVal;
}
/**
* Response Callback for Remote device Presence Check.
*/
STATIC
void phLibNfc_RemoteDev_CheckPresence_Cb(void *context,
NFCSTATUS status)
{
void *pUpperLayerContext=NULL;
pphLibNfc_RspCb_t pClientCb=NULL;
/*check valid context is returned or not*/
if((phLibNfc_LibContext_t *)context != gpphLibContext)
{
/*exception: wrong context pointer returned*/
phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1);
}
/* Mark general callback pending status as FALSE*/
gpphLibContext->status.GenCb_pending_status = FALSE;
pClientCb =gpphLibContext->CBInfo.pClientPresChkCb ;
pUpperLayerContext = gpphLibContext->CBInfo.pClientPresChkCntx;
gpphLibContext->CBInfo.pClientPresChkCntx = NULL;
gpphLibContext->CBInfo.pClientPresChkCb =NULL;
/* Check DeInit call is called, if yes call pending
shutdown and return NFCSTATUS_SHUTDOWN */
if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state)
{
phLibNfc_Pending_Shutdown();
status = NFCSTATUS_SHUTDOWN;
}
else
{
if (status != NFCSTATUS_SUCCESS)
{
/*If status is other than SUCCESS (Internal error) return
NFCSTATUS_TARGET_LOST */
status= NFCSTATUS_TARGET_LOST;
}
else
{
status = NFCSTATUS_SUCCESS;
}
}
/* Update the current state */
phLibNfc_UpdateCurState(status,gpphLibContext);
if(NULL != pClientCb)
{
/* call the upper layer callback */
pClientCb(pUpperLayerContext,status);
}
return;
}
/**Used for presence chk incase of mifare std tags*/
STATIC void phLibNfc_ChkPresence_Trcv_Cb(
void *context,
phHal_sRemoteDevInformation_t *psRemoteDevInfo,
phNfc_sData_t *response,
NFCSTATUS status
)
{
PHNFC_UNUSED_VARIABLE(psRemoteDevInfo);
PHNFC_UNUSED_VARIABLE(response);
phLibNfc_RemoteDev_CheckPresence_Cb(context,status);
return;
}