/* * 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_Target.c * Project: NFC FRI 1.1 * * $Date: Thu Oct 15 15:24:43 2009 $ * $Author: ing07299 $ * $Revision: 1.12 $ * $Aliases: NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK944_SDK,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK949_SDK_INT,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK1003_SDK,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,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 //#undef STATIC #define STATIC #endif /* *************************** Global Variables ********************************** */ /* *************************** Static Function Declaration *********************** */ /* Remote device receive callback */ STATIC void phLibNfc_RemoteDev_Receive_Cb( void *context, phNfc_sData_t *rec_rsp_data, NFCSTATUS status ); /* Remote device Send callback */ STATIC void phLibNfc_RemoteDev_Send_Cb( void *Context, NFCSTATUS status ); /* *************************** Function Definitions ****************************** */ /** * Interface used to receive data from initiator at target side during P2P * communication. */ NFCSTATUS phLibNfc_RemoteDev_Receive(phLibNfc_Handle hRemoteDevice, pphLibNfc_Receive_RspCb_t pReceiveRspCb, void *pContext ) { NFCSTATUS RetVal = NFCSTATUS_FAILED; /*Check Lib Nfc is initialized*/ if((NULL == gpphLibContext)|| (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateShutdown)) { RetVal = NFCSTATUS_NOT_INITIALISED; }/*Check application has sent valid parameters*/ else if (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateRelease) { RetVal = NFCSTATUS_DESELECTED; } else if((NULL == pReceiveRspCb) || (NULL == pContext) || (0 == hRemoteDevice)) { RetVal= NFCSTATUS_INVALID_PARAMETER; } else if(gpphLibContext->LibNfcState.next_state == eLibNfcHalStateShutdown) { RetVal = NFCSTATUS_SHUTDOWN; } else if((TRUE == gpphLibContext->status.GenCb_pending_status) ||(NULL!=gpphLibContext->sNfcIp_Context.pClientNfcIpRxCb) ||(phHal_eNfcIP1_Target== ((phHal_sRemoteDevInformation_t*)hRemoteDevice)->RemDevType)) { /*Previous callback is pending or if initiator uses this api */ RetVal = NFCSTATUS_REJECTED; }/*check for Discovered initiator handle and handle sent by application */ else if(gpphLibContext->sNfcIp_Context.Rem_Initiator_Handle != hRemoteDevice) { RetVal= NFCSTATUS_INVALID_DEVICE; } #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 { if(eLibNfcHalStatePresenceChk == gpphLibContext->LibNfcState.next_state) { gpphLibContext->sNfcIp_Context.pClientNfcIpRxCb = NULL; RetVal = NFCSTATUS_PENDING; } else { /*Call below layer receive and register the callback with it*/ PHDBG_INFO("LibNfc:P2P Receive In Progress"); RetVal =phHal4Nfc_Receive( gpphLibContext->psHwReference, (phHal4Nfc_TransactInfo_t*)gpphLibContext->psTransInfo, (pphLibNfc_Receive_RspCb_t) phLibNfc_RemoteDev_Receive_Cb, (void *)gpphLibContext ); } if(NFCSTATUS_PENDING == RetVal) { /*Update the Next state as Transaction*/ gpphLibContext->sNfcIp_Context.pClientNfcIpRxCb= pReceiveRspCb; gpphLibContext->sNfcIp_Context.pClientNfcIpRxCntx = pContext; gpphLibContext->status.GenCb_pending_status=TRUE; gpphLibContext->LibNfcState.next_state = eLibNfcHalStateTransaction; } else { RetVal = NFCSTATUS_FAILED; } } return RetVal; } /** * Response callback for Remote Device Receive. */ STATIC void phLibNfc_RemoteDev_Receive_Cb( void *context, phNfc_sData_t *rec_rsp_data, NFCSTATUS status ) { pphLibNfc_Receive_RspCb_t pClientCb=NULL; phLibNfc_LibContext_t *pLibNfc_Ctxt = (phLibNfc_LibContext_t *)context; void *pUpperLayerContext=NULL; /* Check for the context returned by below layer */ if(pLibNfc_Ctxt != gpphLibContext) { /*wrong context returned*/ phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1); } else { pClientCb = gpphLibContext->sNfcIp_Context.pClientNfcIpRxCb; pUpperLayerContext = gpphLibContext->sNfcIp_Context.pClientNfcIpRxCntx; gpphLibContext->sNfcIp_Context.pClientNfcIpRxCb = NULL; gpphLibContext->sNfcIp_Context.pClientNfcIpRxCntx = NULL; gpphLibContext->status.GenCb_pending_status = FALSE; if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state) { /*shutdown called before completion of P2P receive allow shutdown to happen */ phLibNfc_Pending_Shutdown(); status = NFCSTATUS_SHUTDOWN; } else if(eLibNfcHalStateRelease == gpphLibContext->LibNfcState.next_state) { status = NFCSTATUS_ABORTED; } else { if((NFCSTATUS_SUCCESS != status) && (PHNFCSTATUS(status) != NFCSTATUS_MORE_INFORMATION ) ) { /*During p2p receive operation initiator was removed from RF field of target*/ status = NFCSTATUS_DESELECTED; } else { status = NFCSTATUS_SUCCESS; } } /* Update current state */ phLibNfc_UpdateCurState(status,gpphLibContext); if (NULL != pClientCb) { /*Notify to upper layer status and No. of bytes actually received */ pClientCb(pUpperLayerContext, rec_rsp_data, status); } } return; } /** * Interface used to send data from target to initiator during P2P communication */ NFCSTATUS phLibNfc_RemoteDev_Send( phLibNfc_Handle hRemoteDevice, phNfc_sData_t * pTransferData, pphLibNfc_RspCb_t pSendRspCb, void *pContext ) { NFCSTATUS RetVal = NFCSTATUS_FAILED; /*Check Lib Nfc stack is initilized*/ if((NULL == gpphLibContext)|| (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateShutdown)) { RetVal = NFCSTATUS_NOT_INITIALISED; } else if (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateRelease) { RetVal = NFCSTATUS_DESELECTED; } /*Check application has sent the valid parameters*/ else if((NULL == pTransferData) || (NULL == pSendRspCb) || (NULL == pTransferData->buffer) || (0 == pTransferData->length) || (NULL == pContext) || (0 == hRemoteDevice)) { RetVal= NFCSTATUS_INVALID_PARAMETER; } else if(gpphLibContext->LibNfcState.next_state == eLibNfcHalStateShutdown) { RetVal = NFCSTATUS_SHUTDOWN; } else if((TRUE == gpphLibContext->status.GenCb_pending_status) ||(NULL!=gpphLibContext->sNfcIp_Context.pClientNfcIpRxCb) ||(phHal_eNfcIP1_Target== ((phHal_sRemoteDevInformation_t*)hRemoteDevice)->RemDevType)) { /*Previous callback is pending or local device is Initiator then don't allow */ RetVal = NFCSTATUS_REJECTED; }/*Check for Discovered initiator handle and handle sent by application */ else if(gpphLibContext->sNfcIp_Context.Rem_Initiator_Handle != hRemoteDevice) { RetVal= NFCSTATUS_INVALID_DEVICE; } else if((NULL!=gpphLibContext->sNfcIp_Context.pClientNfcIpTxCb)) { RetVal =NFCSTATUS_BUSY ; } #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 { if(eLibNfcHalStatePresenceChk == gpphLibContext->LibNfcState.next_state) { gpphLibContext->sNfcIp_Context.pClientNfcIpTxCb = NULL; RetVal = NFCSTATUS_PENDING; } else { if(gpphLibContext->psTransInfo!=NULL) { (void)memset(gpphLibContext->psTransInfo, 0, sizeof(phLibNfc_sTransceiveInfo_t)); gpphLibContext->psTransInfo->addr =UNKNOWN_BLOCK_ADDRESS; /*pointer to send data */ gpphLibContext->psTransInfo->sSendData.buffer = pTransferData->buffer; /*size of send data*/ gpphLibContext->psTransInfo->sSendData.length = pTransferData->length; /* Copy remote device type */ gpphLibContext->sNfcIp_Context.TransactInfoRole.remotePCDType = ((phHal_sRemoteDevInformation_t*)hRemoteDevice)->RemDevType; /*Call Hal4 Send API and register callback with it*/ PHDBG_INFO("LibNfc:P2P send In Progress"); RetVal= phHal4Nfc_Send( gpphLibContext->psHwReference, &(gpphLibContext->sNfcIp_Context.TransactInfoRole), gpphLibContext->psTransInfo->sSendData, (pphLibNfc_RspCb_t) phLibNfc_RemoteDev_Send_Cb, (void *)gpphLibContext ); } } if(NFCSTATUS_PENDING == RetVal) { /* Update next state to transaction */ gpphLibContext->sNfcIp_Context.pClientNfcIpTxCb= pSendRspCb; gpphLibContext->sNfcIp_Context.pClientNfcIpTxCntx = pContext; gpphLibContext->status.GenCb_pending_status=TRUE; gpphLibContext->LibNfcState.next_state = eLibNfcHalStateTransaction; } else { RetVal = NFCSTATUS_FAILED; } } return RetVal; } /* * Response callback for Remote Device Send. */ STATIC void phLibNfc_RemoteDev_Send_Cb( void *Context, NFCSTATUS status ) { pphLibNfc_RspCb_t pClientCb=NULL; phLibNfc_LibContext_t *pLibNfc_Ctxt = (phLibNfc_LibContext_t *)Context; void *pUpperLayerContext=NULL; /* Check for the context returned by below layer */ if(pLibNfc_Ctxt != gpphLibContext) { /*wrong context returned*/ phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1); } else { if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state) { /*shutdown called before completion p2p send allow shutdown to happen */ phLibNfc_Pending_Shutdown(); status = NFCSTATUS_SHUTDOWN; } else if(eLibNfcHalStateRelease == gpphLibContext->LibNfcState.next_state) { status = NFCSTATUS_ABORTED; } else { gpphLibContext->status.GenCb_pending_status = FALSE; if((NFCSTATUS_SUCCESS != status) && (PHNFCSTATUS(status) != NFCSTATUS_MORE_INFORMATION ) ) { /*During p2p send operation initator was not present in RF field of target*/ status = NFCSTATUS_DESELECTED; } else { status = NFCSTATUS_SUCCESS; } } /* Update current state */ phLibNfc_UpdateCurState(status,gpphLibContext); pClientCb = gpphLibContext->sNfcIp_Context.pClientNfcIpTxCb; pUpperLayerContext = gpphLibContext->sNfcIp_Context.pClientNfcIpTxCntx; gpphLibContext->sNfcIp_Context.pClientNfcIpTxCb = NULL; gpphLibContext->sNfcIp_Context.pClientNfcIpTxCntx = NULL; if (NULL != pClientCb) { /* Notify to upper layer status and No. of bytes actually written or send to initiator */ pClientCb(pUpperLayerContext, status); } } return; }