/* * Copyright (C) 2010 NXP Semiconductors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /*! * \file phLibNfc_ndef_raw.c * Project: NFC FRI 1.1 * * $Date: Thu Apr 22 13:59:50 2010 $ * $Author: ing07385 $ * $Revision: 1.70 $ * $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 #include #include #include #include #include #include #include #include /* *************************** Macro's **************************************** */ #ifndef STATIC_DISABLE #define STATIC static #else //#undef STATIC #define STATIC #endif #define TOPAZ_NDEF_BITMASK 0x10U #define TOPAZ_LEN_BITMASK 0x02U #define TOPAZ_DYNAMIC_LEN 460U #define TOPAZ_STATIC_CARD_LEN 128U #define MIFARE_STD_BLOCK_SIZE 0x10U /* *************************** Global Variables ********************************** */ phLibNfc_Ndef_Info_t NdefInfo; phFriNfc_NdefRecord_t *pNdefRecord=NULL; /* *************************** Static Function Declaration *********************** */ /* Response callback for Check Ndef */ STATIC void phLibNfc_Ndef_CheckNdef_Cb(void *pContext, NFCSTATUS status); /* Response callback for Ndef Write */ STATIC void phLibNfc_Ndef_Write_Cb(void* Context,NFCSTATUS status); /* Response callback for Ndef Read*/ STATIC void phLibNfc_Ndef_Read_Cb(void* Context,NFCSTATUS status); /* Response callback forNdef Format*/ STATIC void phLibNfc_Ndef_format_Cb(void *Context,NFCSTATUS status); /* Response callback for Search Ndef Content */ STATIC void phLibNfc_Ndef_SrchNdefCnt_Cb(void *context, NFCSTATUS status); /* Response callback for Ndef Record Type Discovery */ STATIC void phLibNfc_Ndef_Rtd_Cb( void *CallBackParam); /* Response callback for Check Ndef timer callback */ STATIC void CheckNdef_timer_cb(uint32_t timer_id, void *pContext); /*Callback for Presence check call from Chk Ndef*/ STATIC void phLibNfc_Ndef_ChkNdef_Pchk_Cb(void *pContext, NFCSTATUS status ); /* *************************** Function Definitions ****************************** */ /** * This function reads an NDEF message from already connected tag. * the NDEF message is read starting after the position of the * last read operation of the same tag during current session. */ NFCSTATUS phLibNfc_Ndef_Read( phLibNfc_Handle hRemoteDevice, phNfc_sData_t *psRd, phLibNfc_Ndef_EOffset_t Offset, pphLibNfc_RspCb_t pNdefRead_RspCb, void* pContext ) { NFCSTATUS RetVal = NFCSTATUS_FAILED; if((NULL == gpphLibContext)|| (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateShutdown)) { RetVal = NFCSTATUS_NOT_INITIALISED; } else if((NULL == psRd) || (NULL == pNdefRead_RspCb) || (NULL == psRd->buffer) || (0 == psRd->length) || (NULL == pContext) || (0 == hRemoteDevice)) { RetVal= NFCSTATUS_INVALID_PARAMETER; } else if(gpphLibContext->LibNfcState.next_state == eLibNfcHalStateShutdown) { RetVal = NFCSTATUS_SHUTDOWN; } else if(0 == gpphLibContext->Connected_handle) { /*presently no target or tag is connected*/ RetVal=NFCSTATUS_TARGET_NOT_CONNECTED; } else if(hRemoteDevice != gpphLibContext->Connected_handle) { /*This handle of the device sent by application is not connected */ RetVal=NFCSTATUS_INVALID_HANDLE; } else if((TRUE == gpphLibContext->status.GenCb_pending_status) ||(NULL!=gpphLibContext->CBInfo.pClientRdNdefCb) ||(CHK_NDEF_NOT_DONE == gpphLibContext->ndef_cntx.is_ndef)) { /*Previous callback is pending*/ RetVal = NFCSTATUS_REJECTED; } else if(gpphLibContext->ndef_cntx.is_ndef == FALSE) { /*no Ndef Support in tag*/ RetVal = NFCSTATUS_NON_NDEF_COMPLIANT; } else if((gpphLibContext->ndef_cntx.is_ndef == TRUE) &&(0 == gpphLibContext->ndef_cntx.NdefActualSize)) { /*Card is empty- So Returning length as zero*/ psRd->length = 0; RetVal = NFCSTATUS_SUCCESS; } else { gpphLibContext->psRemoteDevList->psRemoteDevInfo->SessionOpened = SESSION_OPEN; gpphLibContext->ndef_cntx.eLast_Call = NdefRd; if((((phHal_sRemoteDevInformation_t*)hRemoteDevice)->RemDevType == phHal_eMifare_PICC) && (((phHal_sRemoteDevInformation_t*) hRemoteDevice)->RemoteDevInfo.Iso14443A_Info.Sak != 0)&& ((NULL == gpphLibContext->psBufferedAuth) ||(phHal_eMifareAuthentA == gpphLibContext->psBufferedAuth->cmd.MfCmd)) ) { if(NULL != gpphLibContext->psBufferedAuth) { if(NULL != gpphLibContext->psBufferedAuth->sRecvData.buffer) { phOsalNfc_FreeMemory( gpphLibContext->psBufferedAuth->sRecvData.buffer); } if(NULL != gpphLibContext->psBufferedAuth->sSendData.buffer) { phOsalNfc_FreeMemory( gpphLibContext->psBufferedAuth->sSendData.buffer); } phOsalNfc_FreeMemory(gpphLibContext->psBufferedAuth); } gpphLibContext->psBufferedAuth =(phLibNfc_sTransceiveInfo_t *) phOsalNfc_GetMemory(sizeof(phLibNfc_sTransceiveInfo_t)); gpphLibContext->psBufferedAuth->addr = (uint8_t)gpphLibContext->ndef_cntx.psNdefMap ->StdMifareContainer.currentBlock; gpphLibContext->psBufferedAuth->cmd.MfCmd = phHal_eMifareRead16; gpphLibContext->psBufferedAuth->sSendData.length = 0; gpphLibContext->psBufferedAuth->sRecvData.length = MIFARE_STD_BLOCK_SIZE; gpphLibContext->psBufferedAuth->sRecvData.buffer = (uint8_t *)phOsalNfc_GetMemory(MIFARE_STD_BLOCK_SIZE); gpphLibContext->psBufferedAuth->sSendData.buffer = (uint8_t *)phOsalNfc_GetMemory(MIFARE_STD_BLOCK_SIZE); } if(eLibNfcHalStatePresenceChk != gpphLibContext->LibNfcState.next_state) { uint8_t cr_index = 0; gpphLibContext->ndef_cntx.psUpperNdefMsg = psRd; for (cr_index = 0; cr_index < PH_FRINFC_NDEFMAP_CR; cr_index++) { RetVal= phFriNfc_NdefMap_SetCompletionRoutine( gpphLibContext->ndef_cntx.psNdefMap, cr_index, phLibNfc_Ndef_Read_Cb, (void *)gpphLibContext); } gpphLibContext->ndef_cntx.NdefContinueRead =(uint8_t) ((phLibNfc_Ndef_EBegin==Offset) ? PH_FRINFC_NDEFMAP_SEEK_BEGIN : PH_FRINFC_NDEFMAP_SEEK_CUR); /* call below layer Ndef Read*/ RetVal = phFriNfc_NdefMap_RdNdef(gpphLibContext->ndef_cntx.psNdefMap, gpphLibContext->ndef_cntx.psUpperNdefMsg->buffer, (uint32_t*)&gpphLibContext->ndef_cntx.psUpperNdefMsg->length, gpphLibContext->ndef_cntx.NdefContinueRead); RetVal = PHNFCSTATUS(RetVal); if(NFCSTATUS_INSUFFICIENT_STORAGE == RetVal) { gpphLibContext->ndef_cntx.psUpperNdefMsg->length = 0; RetVal = NFCSTATUS_SUCCESS; } } else { gpphLibContext->CBInfo.pClientRdNdefCb= NULL; RetVal = NFCSTATUS_PENDING; } if(NFCSTATUS_PENDING == RetVal) { gpphLibContext->CBInfo.pClientRdNdefCb = pNdefRead_RspCb; gpphLibContext->CBInfo.pClientRdNdefCntx = pContext; gpphLibContext->status.GenCb_pending_status=TRUE; gpphLibContext->LibNfcState.next_state = eLibNfcHalStateTransaction; } else if (NFCSTATUS_SUCCESS == RetVal) { RetVal= NFCSTATUS_SUCCESS; } else { /*Ndef read failed*/ RetVal = NFCSTATUS_FAILED; } } return RetVal; } /* Response callback for phLibNfc_Ndef_Read */ STATIC void phLibNfc_Ndef_Read_Cb(void* Context,NFCSTATUS status) { NFCSTATUS RetStatus = NFCSTATUS_SUCCESS; pphLibNfc_RspCb_t pClientCb=NULL; phLibNfc_LibContext_t *pLibNfc_Ctxt = (phLibNfc_LibContext_t *)Context; void *pUpperLayerContext=NULL; phHal_sRemoteDevInformation_t *ps_rem_dev_info = NULL; if(pLibNfc_Ctxt != gpphLibContext) { /*wrong context returned*/ phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1); } else { if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state) { /*shutdown called before completion of Ndef read allow shutdown to happen */ phLibNfc_Pending_Shutdown(); RetStatus = NFCSTATUS_SHUTDOWN; } else if(eLibNfcHalStateRelease == gpphLibContext->LibNfcState.next_state) { RetStatus = NFCSTATUS_ABORTED; } else { gpphLibContext->status.GenCb_pending_status = FALSE; if (gpphLibContext->psBufferedAuth != NULL && gpphLibContext->ndef_cntx.psNdefMap != NULL) { gpphLibContext->psBufferedAuth->addr = (uint8_t) gpphLibContext->ndef_cntx.psNdefMap->StdMifareContainer.currentBlock; } if(NFCSTATUS_FAILED == status ) { /*During Ndef read operation tag was not present in RF field of reader*/ RetStatus = NFCSTATUS_FAILED; gpphLibContext->LastTrancvSuccess = FALSE; gpphLibContext->ndef_cntx.is_ndef = FALSE; ps_rem_dev_info = (phHal_sRemoteDevInformation_t *) gpphLibContext->Connected_handle; if ((phHal_eMifare_PICC == ps_rem_dev_info->RemDevType) && (0x08 == (ps_rem_dev_info->RemoteDevInfo.Iso14443A_Info.Sak & 0x08))) { /* card type is mifare 1k/4k, then reconnect */ RetStatus = phHal4Nfc_Connect(gpphLibContext->psHwReference, ps_rem_dev_info, (pphHal4Nfc_ConnectCallback_t) phLibNfc_Reconnect_Mifare_Cb, (void *)gpphLibContext); } } else if(status == NFCSTATUS_SUCCESS) { gpphLibContext->LastTrancvSuccess = TRUE; RetStatus = NFCSTATUS_SUCCESS; } else { gpphLibContext->LastTrancvSuccess = FALSE; RetStatus = NFCSTATUS_FAILED; } } /*update the current state as connected*/ phLibNfc_UpdateCurState(status,gpphLibContext); pClientCb = gpphLibContext->CBInfo.pClientRdNdefCb; pUpperLayerContext = gpphLibContext->CBInfo.pClientRdNdefCntx; gpphLibContext->CBInfo.pClientRdNdefCb = NULL; gpphLibContext->CBInfo.pClientRdNdefCntx = NULL; if(NFCSTATUS_PENDING != RetStatus) { if (NULL != pClientCb) { /*Notify to upper layer status and read bytes*/ pClientCb(pUpperLayerContext,RetStatus); } } } return; } /** * Write NDEF to a tag. * * This function allows the user to write a NDEF data to already connected NFC * tag.Function writes a complete NDEF message to a tag. If a NDEF message * already exists in the tag, it will be overwritten. When the transaction is * complete,a notification callback is notified. */ NFCSTATUS phLibNfc_Ndef_Write( phLibNfc_Handle hRemoteDevice, phNfc_sData_t *psWr, pphLibNfc_RspCb_t pNdefWrite_RspCb, void* pContext ) { NFCSTATUS RetVal = NFCSTATUS_FAILED; uint8_t NdefWriteType=0xFF; /*LibNfc is initilized or not */ if((NULL == gpphLibContext)|| (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateShutdown)) { RetVal = NFCSTATUS_NOT_INITIALISED; }/*Check for application has sent the valid parameters*/ else if((NULL == psWr) || (NULL == pNdefWrite_RspCb) || (NULL == psWr->buffer) || (NULL == pContext) || (0 ==hRemoteDevice)) { RetVal= NFCSTATUS_INVALID_PARAMETER; } else if(gpphLibContext->LibNfcState.next_state == eLibNfcHalStateShutdown) { /* Lib Nfc Shutdown*/ RetVal= NFCSTATUS_SHUTDOWN; } else if(0 == gpphLibContext->Connected_handle) { RetVal=NFCSTATUS_TARGET_NOT_CONNECTED; } else if(hRemoteDevice != gpphLibContext->Connected_handle) { RetVal=NFCSTATUS_INVALID_HANDLE; } else if((TRUE == gpphLibContext->status.GenCb_pending_status)|| (gpphLibContext->ndef_cntx.is_ndef == CHK_NDEF_NOT_DONE)) { /* Previous callback is pending or Tag is not NDEF tag*/ RetVal = NFCSTATUS_REJECTED; PHDBG_INFO("LIbNfc:Previous Callback is Pending"); } else if(FALSE == gpphLibContext->ndef_cntx.is_ndef) { RetVal = NFCSTATUS_NON_NDEF_COMPLIANT; } else if(psWr->length > gpphLibContext->ndef_cntx.NdefLength) { RetVal = NFCSTATUS_NOT_ENOUGH_MEMORY; } else { uint8_t cr_index = 0; gpphLibContext->ndef_cntx.psUpperNdefMsg = psWr; gpphLibContext->ndef_cntx.AppWrLength= psWr->length; gpphLibContext->ndef_cntx.eLast_Call = NdefWr; gpphLibContext->psRemoteDevList->psRemoteDevInfo->SessionOpened = SESSION_OPEN; if((((phHal_sRemoteDevInformation_t*)hRemoteDevice)->RemDevType == phHal_eMifare_PICC) && (((phHal_sRemoteDevInformation_t*) hRemoteDevice)->RemoteDevInfo.Iso14443A_Info.Sak != 0)&& ((NULL == gpphLibContext->psBufferedAuth) ||(phHal_eMifareAuthentA == gpphLibContext->psBufferedAuth->cmd.MfCmd)) ) { if(NULL != gpphLibContext->psBufferedAuth) { if(NULL != gpphLibContext->psBufferedAuth->sRecvData.buffer) { phOsalNfc_FreeMemory( gpphLibContext->psBufferedAuth->sRecvData.buffer); } if(NULL != gpphLibContext->psBufferedAuth->sSendData.buffer) { phOsalNfc_FreeMemory( gpphLibContext->psBufferedAuth->sSendData.buffer); } phOsalNfc_FreeMemory(gpphLibContext->psBufferedAuth); } gpphLibContext->psBufferedAuth =(phLibNfc_sTransceiveInfo_t *) phOsalNfc_GetMemory(sizeof(phLibNfc_sTransceiveInfo_t)); gpphLibContext->psBufferedAuth->addr = (uint8_t)gpphLibContext->ndef_cntx.psNdefMap ->StdMifareContainer.currentBlock; gpphLibContext->psBufferedAuth->cmd.MfCmd = phHal_eMifareRead16; gpphLibContext->psBufferedAuth->sSendData.length = 0; gpphLibContext->psBufferedAuth->sRecvData.length = MIFARE_STD_BLOCK_SIZE; gpphLibContext->psBufferedAuth->sRecvData.buffer = (uint8_t *)phOsalNfc_GetMemory(MIFARE_STD_BLOCK_SIZE); gpphLibContext->psBufferedAuth->sSendData.buffer = (uint8_t *)phOsalNfc_GetMemory(MIFARE_STD_BLOCK_SIZE); } if(eLibNfcHalStatePresenceChk == gpphLibContext->LibNfcState.next_state) { gpphLibContext->CBInfo.pClientWrNdefCb = NULL; RetVal = NFCSTATUS_PENDING; } else { for (cr_index = 0; cr_index < PH_FRINFC_NDEFMAP_CR; cr_index++) { /* Registering the Completion Routine.*/ RetVal= phFriNfc_NdefMap_SetCompletionRoutine( gpphLibContext->ndef_cntx.psNdefMap, cr_index, phLibNfc_Ndef_Write_Cb, (void *)gpphLibContext); } if(0 == psWr->length) { /* Length of bytes to be written Zero- Erase the Tag */ RetVal = phFriNfc_NdefMap_EraseNdef(gpphLibContext->ndef_cntx.psNdefMap); } else { /*Write from beginning or current location*/ NdefWriteType = PH_FRINFC_NDEFMAP_SEEK_BEGIN; /*Call FRI Ndef Write*/ RetVal=phFriNfc_NdefMap_WrNdef(gpphLibContext->ndef_cntx.psNdefMap, gpphLibContext->ndef_cntx.psUpperNdefMsg->buffer, (uint32_t*)&gpphLibContext->ndef_cntx.psUpperNdefMsg->length, NdefWriteType); } if(NFCSTATUS_PENDING == RetVal) { gpphLibContext->CBInfo.pClientWrNdefCb = pNdefWrite_RspCb; gpphLibContext->CBInfo.pClientWrNdefCntx = pContext; gpphLibContext->status.GenCb_pending_status=TRUE; gpphLibContext->LibNfcState.next_state = eLibNfcHalStateTransaction; } else { RetVal = NFCSTATUS_FAILED; } } } return RetVal; } /* Response callback for phLibNfc_Ndef_Write */ STATIC void phLibNfc_Ndef_Write_Cb(void* Context,NFCSTATUS status) { pphLibNfc_RspCb_t pClientCb=NULL; phLibNfc_LibContext_t *pLibNfc_Ctxt = (phLibNfc_LibContext_t *)Context; void *pUpperLayerContext=NULL; phHal_sRemoteDevInformation_t *ps_rem_dev_info = NULL; if(pLibNfc_Ctxt != gpphLibContext) { /*wrong context returned*/ phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1); } else { if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state) { /*shutdown called before completion of Ndef write allow shutdown to happen */ phLibNfc_Pending_Shutdown(); status = NFCSTATUS_SHUTDOWN; } else if(eLibNfcHalStateRelease == gpphLibContext->LibNfcState.next_state) { status = NFCSTATUS_ABORTED; } else { gpphLibContext->status.GenCb_pending_status = FALSE; if (gpphLibContext->psBufferedAuth != NULL && gpphLibContext->ndef_cntx.psNdefMap != NULL) { gpphLibContext->psBufferedAuth->addr = (uint8_t) gpphLibContext->ndef_cntx.psNdefMap->TLVStruct.NdefTLVBlock; } if(status == NFCSTATUS_FAILED ) { status = NFCSTATUS_FAILED; gpphLibContext->LastTrancvSuccess = FALSE; /*During Ndef write operation tag was not present in RF field of reader*/ ps_rem_dev_info = (phHal_sRemoteDevInformation_t *) gpphLibContext->Connected_handle; if ((phHal_eMifare_PICC == ps_rem_dev_info->RemDevType) && (0x08 == (ps_rem_dev_info->RemoteDevInfo.Iso14443A_Info.Sak & 0x08))) { /* card type is mifare 1k/4k, then reconnect */ status = phHal4Nfc_Connect(gpphLibContext->psHwReference, ps_rem_dev_info, (pphHal4Nfc_ConnectCallback_t) phLibNfc_Reconnect_Mifare_Cb, (void *)gpphLibContext); } } else if( status== NFCSTATUS_SUCCESS) { gpphLibContext->LastTrancvSuccess = TRUE; status = NFCSTATUS_SUCCESS; if(gpphLibContext->ndef_cntx.AppWrLength > gpphLibContext->ndef_cntx.NdefLength) { status = NFCSTATUS_NOT_ENOUGH_MEMORY; } } else { gpphLibContext->LastTrancvSuccess = FALSE; status = NFCSTATUS_FAILED;; } } phLibNfc_UpdateCurState(status,gpphLibContext); pClientCb = gpphLibContext->CBInfo.pClientWrNdefCb; pUpperLayerContext = gpphLibContext->CBInfo.pClientWrNdefCntx; gpphLibContext->CBInfo.pClientWrNdefCb = NULL; gpphLibContext->CBInfo.pClientWrNdefCntx = NULL; if(NFCSTATUS_PENDING !=status) { if (NULL != pClientCb) { /*Notify to upper layer status and No. of bytes actually written */ pClientCb(pUpperLayerContext, status); } } } return; } /** * Initialize structures needed for the Ndef * related operation such as Check Ndef, read, write * and Ndef foramt.only once allocation */ void phLibNfc_Ndef_Init(void) { if(gpphLibContext->psTransInfo==NULL) { /*Allocate memory for Transceiveinformation Structure*/ gpphLibContext->psTransInfo = (phLibNfc_sTransceiveInfo_t *) phOsalNfc_GetMemory(sizeof(phLibNfc_sTransceiveInfo_t)); } if(gpphLibContext->psTransInfo==NULL) { /*exception: Not enough memory*/ phOsalNfc_RaiseException(phOsalNfc_e_NoMemory,1); } if(NULL == gpphLibContext->ndef_cntx.psNdefMap) { /*Allocate memory for NDEF Mapping Component Context Structure*/ gpphLibContext->ndef_cntx.psNdefMap = (phFriNfc_NdefMap_t *) phOsalNfc_GetMemory(sizeof(phFriNfc_NdefMap_t)); } if(NULL != gpphLibContext->ndef_cntx.psNdefMap) { /*Allocation successful*/ (void)memset(gpphLibContext->ndef_cntx.psNdefMap,0,sizeof(phFriNfc_NdefMap_t)); gpphLibContext->ndef_cntx.NdefSendRecvLen = NDEF_SENDRCV_BUF_LEN; gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf = (uint8_t*) phOsalNfc_GetMemory(gpphLibContext-> ndef_cntx.NdefSendRecvLen); if(NULL != gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf) { (void)memset(gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf, 0, gpphLibContext->ndef_cntx.NdefSendRecvLen); gpphLibContext->psOverHalCtxt =(phFriNfc_OvrHal_t *) phOsalNfc_GetMemory(sizeof(phFriNfc_OvrHal_t)); } } if(NULL == gpphLibContext->psOverHalCtxt) { /*exception: Not enough memory*/ phOsalNfc_RaiseException(phOsalNfc_e_NoMemory,1); } else { (void)memset(gpphLibContext->psOverHalCtxt,0, sizeof(phFriNfc_OvrHal_t)); /* Initialize the Overlapped hal structure*/ gpphLibContext->psOverHalCtxt->psHwReference = gpphLibContext->psHwReference; if(NULL == gpphLibContext->psDevInputParam ) { gpphLibContext->psDevInputParam = (phHal_sDevInputParam_t *) phOsalNfc_GetMemory(sizeof(phHal_sDevInputParam_t)); } gpphLibContext->ndef_cntx.is_ndef = CHK_NDEF_NOT_DONE; } if(NULL == gpphLibContext->ndef_cntx.ndef_fmt) { /*Allocate memory for Ndef format structure*/ gpphLibContext->ndef_cntx.ndef_fmt = (phFriNfc_sNdefSmtCrdFmt_t *) phOsalNfc_GetMemory(sizeof(phFriNfc_sNdefSmtCrdFmt_t)); } if(NULL != gpphLibContext->ndef_cntx.ndef_fmt) { (void)memset(gpphLibContext->ndef_cntx.ndef_fmt, 0, sizeof(phFriNfc_sNdefSmtCrdFmt_t)); } else { /*exception: Not enough memory*/ phOsalNfc_RaiseException(phOsalNfc_e_NoMemory,1); } return; } /** * Free the allocated memory used for Ndef operations */ void phLibNfc_Ndef_DeInit(void) { /* If only allocated then only free the memory*/ if(gpphLibContext->ndef_cntx.psNdefMap !=NULL) { if(gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf !=NULL) { phOsalNfc_FreeMemory(gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf); gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf=NULL; } phOsalNfc_FreeMemory(gpphLibContext->ndef_cntx.psNdefMap); gpphLibContext->ndef_cntx.psNdefMap =NULL; } if(NULL != gpphLibContext->ndef_cntx.ndef_fmt) { phOsalNfc_FreeMemory(gpphLibContext->ndef_cntx.ndef_fmt); gpphLibContext->ndef_cntx.ndef_fmt = NULL; } if(gpphLibContext->psOverHalCtxt !=NULL) { phOsalNfc_FreeMemory(gpphLibContext->psOverHalCtxt); gpphLibContext->psOverHalCtxt =NULL; } if(gpphLibContext->psDevInputParam !=NULL) { phOsalNfc_FreeMemory(gpphLibContext->psDevInputParam); gpphLibContext->psDevInputParam = NULL; } if(gpphLibContext->psTransInfo!=NULL) { phOsalNfc_FreeMemory(gpphLibContext->psTransInfo); gpphLibContext->psTransInfo= NULL; } } /** * This function allows the user to check whether a particular Remote Device * is NDEF compliant or not */ NFCSTATUS phLibNfc_Ndef_CheckNdef(phLibNfc_Handle hRemoteDevice, pphLibNfc_ChkNdefRspCb_t pCheckNdef_RspCb, void* pContext) { NFCSTATUS RetVal = NFCSTATUS_FAILED; if((NULL == gpphLibContext)|| (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateShutdown)) { /*Lib Nfc not initialized*/ RetVal = NFCSTATUS_NOT_INITIALISED; } else if((NULL == pCheckNdef_RspCb)|| (NULL==pContext)|| (hRemoteDevice == 0)) { /*parameter sent by upper layer are not valid */ RetVal= NFCSTATUS_INVALID_PARAMETER; } else if(gpphLibContext->LibNfcState.next_state == eLibNfcHalStateShutdown) { RetVal = NFCSTATUS_SHUTDOWN; } else if(0 == gpphLibContext->Connected_handle) { RetVal=NFCSTATUS_TARGET_NOT_CONNECTED; } else if(hRemoteDevice != gpphLibContext->Connected_handle) { RetVal=NFCSTATUS_INVALID_HANDLE; } else { uint8_t cr_index = 0; static uint16_t data_cnt = 0; /* Allocate memory for the ndef related structure */ gpphLibContext->ndef_cntx.NdefSendRecvLen=300; gpphLibContext->ndef_cntx.eLast_Call = ChkNdef; /* Resets the component instance */ RetVal = phFriNfc_NdefMap_Reset( gpphLibContext->ndef_cntx.psNdefMap, gpphLibContext->psOverHalCtxt, (phLibNfc_sRemoteDevInformation_t*)hRemoteDevice, gpphLibContext->psDevInputParam, gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf, gpphLibContext->ndef_cntx.NdefSendRecvLen, gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf, &(gpphLibContext->ndef_cntx.NdefSendRecvLen), &(data_cnt)); for (cr_index = 0; cr_index < PH_FRINFC_NDEFMAP_CR; cr_index++) { /* Register the callback for the check ndef */ RetVal = phFriNfc_NdefMap_SetCompletionRoutine( gpphLibContext->ndef_cntx.psNdefMap, cr_index, phLibNfc_Ndef_CheckNdef_Cb, (void *)gpphLibContext); } /*call below layer check Ndef function*/ RetVal = phFriNfc_NdefMap_ChkNdef(gpphLibContext->ndef_cntx.psNdefMap); RetVal =PHNFCSTATUS(RetVal); if(RetVal== NFCSTATUS_PENDING) { RetVal = NFCSTATUS_PENDING; } else if((RetVal == NFCSTATUS_FAILED) || (RetVal ==(PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_REMOTE_DEVICE)))) { RetVal= NFCSTATUS_FAILED; } else { if((0x00 == gpphLibContext->ndef_cntx.Chk_Ndef_Timer_Id)|| (PH_OSALNFC_INVALID_TIMER_ID == gpphLibContext->ndef_cntx.Chk_Ndef_Timer_Id)) { gpphLibContext->ndef_cntx.Chk_Ndef_Timer_Id = phOsalNfc_Timer_Create(); } if((0x00 == gpphLibContext->ndef_cntx.Chk_Ndef_Timer_Id)|| (PH_OSALNFC_INVALID_TIMER_ID == gpphLibContext->ndef_cntx.Chk_Ndef_Timer_Id)) { RetVal = NFCSTATUS_FAILED; } else { phOsalNfc_Timer_Start(gpphLibContext->ndef_cntx.Chk_Ndef_Timer_Id, CHK_NDEF_TIMER_TIMEOUT,CheckNdef_timer_cb,NULL); RetVal = NFCSTATUS_PENDING; } } if(RetVal== NFCSTATUS_PENDING) { gpphLibContext->CBInfo.pClientCkNdefCb = pCheckNdef_RspCb; gpphLibContext->CBInfo.pClientCkNdefCntx = pContext; gpphLibContext->status.GenCb_pending_status=TRUE; gpphLibContext->LibNfcState.next_state = eLibNfcHalStateTransaction; } } return RetVal; } /* Response callback for phLibNfc_Ndef_CheckNdef */ STATIC void phLibNfc_Ndef_CheckNdef_Cb(void *pContext,NFCSTATUS status) { phLibNfc_ChkNdef_Info_t Ndef_Info; NFCSTATUS RetStatus = NFCSTATUS_SUCCESS; pphLibNfc_ChkNdefRspCb_t pClientCb=NULL; phLibNfc_LibContext_t *pLibNfc_Ctxt = (phLibNfc_LibContext_t *)pContext; void *pUpperLayerContext=NULL; phHal_sRemoteDevInformation_t *ps_rem_dev_info = NULL; Ndef_Info.ActualNdefMsgLength = 0; Ndef_Info.MaxNdefMsgLength = 0; if(pLibNfc_Ctxt != gpphLibContext) { /*wrong context returned from below layer*/ phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1); } else { ps_rem_dev_info = (phHal_sRemoteDevInformation_t *) gpphLibContext->Connected_handle; if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state) { /*shutdown called before completion of check Ndef, allow shutdown to happen */ phLibNfc_Pending_Shutdown(); RetStatus = NFCSTATUS_SHUTDOWN; } else if(eLibNfcHalStateRelease == gpphLibContext->LibNfcState.next_state) { RetStatus = NFCSTATUS_ABORTED; } else { if(status == NFCSTATUS_SUCCESS) { /*Tag is Ndef tag*/ gpphLibContext->ndef_cntx.is_ndef = TRUE; (void)phFriNfc_NdefMap_GetContainerSize( pLibNfc_Ctxt->ndef_cntx.psNdefMap, &(pLibNfc_Ctxt->ndef_cntx.NdefLength), &(pLibNfc_Ctxt->ndef_cntx.NdefActualSize)); /*Get the data size support by particular ndef card */ Ndef_Info.ActualNdefMsgLength = pLibNfc_Ctxt->ndef_cntx.NdefActualSize; Ndef_Info.MaxNdefMsgLength = pLibNfc_Ctxt->ndef_cntx.NdefLength; gpphLibContext->LastTrancvSuccess = TRUE; RetStatus =NFCSTATUS_SUCCESS; } else if (PHNFCSTATUS(status) != NFCSTATUS_MORE_INFORMATION ) { /*Ndef check Failed.Issue a PresenceChk to ascertain if tag is still in the field*/ RetStatus = phHal4Nfc_PresenceCheck( gpphLibContext->psHwReference, phLibNfc_Ndef_ChkNdef_Pchk_Cb, (void *)gpphLibContext ); } else { RetStatus = NFCSTATUS_FAILED; gpphLibContext->LastTrancvSuccess = FALSE; gpphLibContext->ndef_cntx.is_ndef = FALSE; if ((phHal_eMifare_PICC == ps_rem_dev_info->RemDevType) && (0x08 == (ps_rem_dev_info->RemoteDevInfo.Iso14443A_Info.Sak & 0x08))) { /* card type is mifare 1k/4k, then reconnect */ RetStatus = phHal4Nfc_Connect(gpphLibContext->psHwReference, ps_rem_dev_info, (pphHal4Nfc_ConnectCallback_t) phLibNfc_Reconnect_Mifare_Cb, (void *)gpphLibContext); } else { if((phHal_eJewel_PICC == ps_rem_dev_info->RemDevType) &&(TOPAZ_NDEF_BITMASK & ps_rem_dev_info->RemoteDevInfo.Jewel_Info.HeaderRom0)) { gpphLibContext->ndef_cntx.is_ndef = TRUE; RetStatus = phFriNfc_NdefMap_GetContainerSize( pLibNfc_Ctxt->ndef_cntx.psNdefMap, &(pLibNfc_Ctxt->ndef_cntx.NdefLength), &(pLibNfc_Ctxt->ndef_cntx.NdefActualSize)); /*Get the data size support by particular ndef card */ Ndef_Info.ActualNdefMsgLength = pLibNfc_Ctxt->ndef_cntx.NdefActualSize; Ndef_Info.MaxNdefMsgLength = pLibNfc_Ctxt->ndef_cntx.NdefLength = (TOPAZ_LEN_BITMASK & ps_rem_dev_info->RemoteDevInfo.Jewel_Info.HeaderRom0? TOPAZ_DYNAMIC_LEN:TOPAZ_STATIC_CARD_LEN); RetStatus = NFCSTATUS_SUCCESS; } } } gpphLibContext->LibNfcState.cur_state=eLibNfcHalStateConnect; } gpphLibContext->status.GenCb_pending_status = FALSE; /* Update the current state */ phLibNfc_UpdateCurState(RetStatus,gpphLibContext); if(NFCSTATUS_PENDING != RetStatus) { if(((ps_rem_dev_info->RemDevType == phHal_eMifare_PICC) && (ps_rem_dev_info->RemoteDevInfo.Iso14443A_Info.Sak != 0)&& ((NULL == gpphLibContext->psBufferedAuth) ||(phHal_eMifareAuthentA == gpphLibContext->psBufferedAuth->cmd.MfCmd))) ) { if(NULL != gpphLibContext->psBufferedAuth) { if(NULL != gpphLibContext->psBufferedAuth->sRecvData.buffer) { phOsalNfc_FreeMemory( gpphLibContext->psBufferedAuth->sRecvData.buffer); } if(NULL != gpphLibContext->psBufferedAuth->sSendData.buffer) { phOsalNfc_FreeMemory( gpphLibContext->psBufferedAuth->sSendData.buffer); } phOsalNfc_FreeMemory(gpphLibContext->psBufferedAuth); } gpphLibContext->psBufferedAuth =(phLibNfc_sTransceiveInfo_t *) phOsalNfc_GetMemory(sizeof(phLibNfc_sTransceiveInfo_t)); gpphLibContext->psBufferedAuth->addr = (uint8_t)gpphLibContext->ndef_cntx.psNdefMap ->StdMifareContainer.currentBlock; gpphLibContext->psBufferedAuth->cmd.MfCmd = phHal_eMifareRead16; gpphLibContext->psBufferedAuth->sSendData.length = 0; gpphLibContext->psBufferedAuth->sRecvData.length = MIFARE_STD_BLOCK_SIZE; gpphLibContext->psBufferedAuth->sRecvData.buffer = (uint8_t *)phOsalNfc_GetMemory(MIFARE_STD_BLOCK_SIZE); gpphLibContext->psBufferedAuth->sSendData.buffer = (uint8_t *)phOsalNfc_GetMemory(MIFARE_STD_BLOCK_SIZE); } pClientCb = gpphLibContext->CBInfo.pClientCkNdefCb; pUpperLayerContext = gpphLibContext->CBInfo.pClientCkNdefCntx; gpphLibContext->CBInfo.pClientCkNdefCb = NULL; gpphLibContext->CBInfo.pClientCkNdefCntx = NULL; if(NULL != pClientCb) { /* call the upper check ndef callback */ pClientCb(pUpperLayerContext,Ndef_Info,RetStatus); } } } return; } /*Callback for Presence check call from Chk Ndef*/ STATIC void phLibNfc_Ndef_ChkNdef_Pchk_Cb(void *pContext, NFCSTATUS status ) { phLibNfc_ChkNdef_Info_t Ndef_Info = {0,0}; NFCSTATUS RetStatus = NFCSTATUS_SUCCESS; pphLibNfc_ChkNdefRspCb_t pClientCb=NULL; phLibNfc_LibContext_t *pLibNfc_Ctxt = (phLibNfc_LibContext_t *)pContext; void *pUpperLayerContext=NULL; phHal_sRemoteDevInformation_t *ps_rem_dev_info = NULL; if(NFCSTATUS_SUCCESS == status) { RetStatus = NFCSTATUS_FAILED; gpphLibContext->ndef_cntx.is_ndef = FALSE; } else { RetStatus = NFCSTATUS_TARGET_LOST; } if(pLibNfc_Ctxt != gpphLibContext) { /*wrong context returned from below layer*/ phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1); } else { ps_rem_dev_info = (phHal_sRemoteDevInformation_t *) gpphLibContext->Connected_handle; if(((ps_rem_dev_info->RemDevType == phHal_eMifare_PICC) && (ps_rem_dev_info->RemoteDevInfo.Iso14443A_Info.Sak != 0)&& ((NULL == gpphLibContext->psBufferedAuth) ||(phHal_eMifareAuthentA == gpphLibContext->psBufferedAuth->cmd.MfCmd))) ) { if(NULL != gpphLibContext->psBufferedAuth) { if(NULL != gpphLibContext->psBufferedAuth->sRecvData.buffer) { phOsalNfc_FreeMemory( gpphLibContext->psBufferedAuth->sRecvData.buffer); } if(NULL != gpphLibContext->psBufferedAuth->sSendData.buffer) { phOsalNfc_FreeMemory( gpphLibContext->psBufferedAuth->sSendData.buffer); } phOsalNfc_FreeMemory(gpphLibContext->psBufferedAuth); } gpphLibContext->psBufferedAuth =(phLibNfc_sTransceiveInfo_t *) phOsalNfc_GetMemory(sizeof(phLibNfc_sTransceiveInfo_t)); gpphLibContext->psBufferedAuth->addr = (uint8_t)gpphLibContext->ndef_cntx.psNdefMap ->StdMifareContainer.currentBlock; gpphLibContext->psBufferedAuth->cmd.MfCmd = phHal_eMifareRead16; gpphLibContext->psBufferedAuth->sSendData.length = 0; gpphLibContext->psBufferedAuth->sRecvData.length = MIFARE_STD_BLOCK_SIZE; gpphLibContext->psBufferedAuth->sRecvData.buffer = (uint8_t *)phOsalNfc_GetMemory(MIFARE_STD_BLOCK_SIZE); gpphLibContext->psBufferedAuth->sSendData.buffer = (uint8_t *)phOsalNfc_GetMemory(MIFARE_STD_BLOCK_SIZE); } pClientCb = gpphLibContext->CBInfo.pClientCkNdefCb; pUpperLayerContext = gpphLibContext->CBInfo.pClientCkNdefCntx; gpphLibContext->CBInfo.pClientCkNdefCb = NULL; gpphLibContext->CBInfo.pClientCkNdefCntx = NULL; if(NULL != pClientCb) { /* call the upper check ndef callback */ pClientCb(pUpperLayerContext,Ndef_Info,RetStatus); } } return; } /* Check Ndef Timer Callback*/ STATIC void CheckNdef_timer_cb(uint32_t timer_id, void *pContext) { PHNFC_UNUSED_VARIABLE(pContext); phOsalNfc_Timer_Stop(timer_id); phOsalNfc_Timer_Delete(gpphLibContext->ndef_cntx.Chk_Ndef_Timer_Id); gpphLibContext->ndef_cntx.Chk_Ndef_Timer_Id = 0x00; phLibNfc_Ndef_CheckNdef_Cb((void *)gpphLibContext,NFCSTATUS_MORE_INFORMATION); } void phLibNfc_Reconnect_Mifare_Cb ( void *pContext, phHal_sRemoteDevInformation_t *psRemoteDevInfo, NFCSTATUS status) { phLibNfc_ChkNdef_Info_t Ndef_Info; phLibNfc_LibContext_t *pLibNfc_Ctxt = (phLibNfc_LibContext_t *)pContext; void *pUpperLayerContext = NULL; switch(gpphLibContext->ndef_cntx.eLast_Call) { case ChkNdef: { pphLibNfc_ChkNdefRspCb_t pClientCb=NULL; pClientCb = pLibNfc_Ctxt->CBInfo.pClientCkNdefCb; pUpperLayerContext = pLibNfc_Ctxt->CBInfo.pClientCkNdefCntx; pLibNfc_Ctxt->CBInfo.pClientCkNdefCb = NULL; pLibNfc_Ctxt->CBInfo.pClientCkNdefCntx = NULL; if (NULL != pClientCb) { status = (NFCSTATUS_SUCCESS == status? NFCSTATUS_FAILED:NFCSTATUS_TARGET_LOST); Ndef_Info.ActualNdefMsgLength = 0; Ndef_Info.MaxNdefMsgLength = 0; /* call the upper check ndef callback */ pClientCb(pUpperLayerContext,Ndef_Info,status); } } break; case NdefRd: { pphLibNfc_RspCb_t pClientCb = pLibNfc_Ctxt->CBInfo.pClientRdNdefCb; pUpperLayerContext = pLibNfc_Ctxt->CBInfo.pClientRdNdefCntx; pLibNfc_Ctxt->CBInfo.pClientRdNdefCb = NULL; pLibNfc_Ctxt->CBInfo.pClientRdNdefCntx = NULL; if (NULL != pClientCb) { status = (NFCSTATUS_SUCCESS == status? NFCSTATUS_FAILED:NFCSTATUS_TARGET_LOST); /* call the upper ndef read callback */ pClientCb(pUpperLayerContext,status); } } break; case NdefWr: { pphLibNfc_RspCb_t pClientCb = pLibNfc_Ctxt->CBInfo.pClientWrNdefCb; pUpperLayerContext = pLibNfc_Ctxt->CBInfo.pClientWrNdefCntx; pLibNfc_Ctxt->CBInfo.pClientWrNdefCb = NULL; pLibNfc_Ctxt->CBInfo.pClientWrNdefCntx = NULL; if (NULL != pClientCb) { status = (NFCSTATUS_SUCCESS == status? NFCSTATUS_FAILED:NFCSTATUS_TARGET_LOST); /* call the upper ndef write callback */ pClientCb(pUpperLayerContext,status); } } break; case NdefFmt: { pphLibNfc_RspCb_t pClientCb = pLibNfc_Ctxt->ndef_cntx.pClientNdefFmtCb; pUpperLayerContext= pLibNfc_Ctxt->ndef_cntx.pClientNdefFmtCntx; pLibNfc_Ctxt->ndef_cntx.pClientNdefFmtCb = NULL; pLibNfc_Ctxt->ndef_cntx.pClientNdefFmtCntx = NULL; if (NULL != pClientCb) { status = (NFCSTATUS_SUCCESS == status? NFCSTATUS_FAILED:NFCSTATUS_TARGET_LOST); /* call the upper ndef format callback */ pClientCb(pUpperLayerContext,status); } } break; case RawTrans: { phNfc_sData_t trans_resp; pphLibNfc_TransceiveCallback_t pClientCb = pLibNfc_Ctxt->CBInfo.pClientTransceiveCb; trans_resp.length = 0; pUpperLayerContext = pLibNfc_Ctxt->CBInfo.pClientTranseCntx; pLibNfc_Ctxt->CBInfo.pClientTranseCntx= NULL; pLibNfc_Ctxt->CBInfo.pClientTransceiveCb= NULL; if (NULL != pClientCb) { status = (NFCSTATUS_SUCCESS == status? NFCSTATUS_FAILED:NFCSTATUS_TARGET_LOST); /* call the upper transceive callback */ pClientCb(pUpperLayerContext, (uint32_t)psRemoteDevInfo, & trans_resp, status); } } break; default: { } break; } } /** * Target format to make it NDEF compliant */ NFCSTATUS phLibNfc_RemoteDev_FormatNdef(phLibNfc_Handle hRemoteDevice, phNfc_sData_t* pScrtKey, pphLibNfc_RspCb_t pNdefformat_RspCb, void* pContext ) { NFCSTATUS RetVal = NFCSTATUS_FAILED; static uint8_t mif_std_key[6] ={0}, Index = 0; if((NULL == gpphLibContext) ||(gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateShutdown)) { /*Lib Nfc not initialized*/ RetVal = NFCSTATUS_NOT_INITIALISED; } else if((NULL == pContext) || (NULL == pNdefformat_RspCb) ||(NULL == pScrtKey) ||(0 == hRemoteDevice)) { RetVal= NFCSTATUS_INVALID_PARAMETER; } else if(gpphLibContext->LibNfcState.next_state == eLibNfcHalStateShutdown) { RetVal= NFCSTATUS_SHUTDOWN; } else if(0 == gpphLibContext->Connected_handle) { RetVal=NFCSTATUS_TARGET_NOT_CONNECTED; } else if(hRemoteDevice != gpphLibContext->Connected_handle) { RetVal=NFCSTATUS_INVALID_HANDLE; } else if((TRUE == gpphLibContext->status.GenCb_pending_status)|| (NULL != gpphLibContext->ndef_cntx.pClientNdefFmtCb) ||(gpphLibContext->ndef_cntx.is_ndef == TRUE)) { /*Previous Callback is Pending*/ RetVal = NFCSTATUS_REJECTED; PHDBG_INFO("LIbNfc:Previous Callback is Pending"); } else { uint8_t fun_id; gpphLibContext->ndef_cntx.eLast_Call = NdefFmt; gpphLibContext->ndef_cntx.NdefSendRecvLen = NDEF_SENDRCV_BUF_LEN; /* Call ndef format reset, this will initialize the ndef format structure, and appropriate values are filled */ RetVal = phFriNfc_NdefSmtCrd_Reset(gpphLibContext->ndef_cntx.ndef_fmt, gpphLibContext->psOverHalCtxt, (phHal_sRemoteDevInformation_t*)hRemoteDevice, gpphLibContext->psDevInputParam, gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf, &(gpphLibContext->ndef_cntx.NdefSendRecvLen)); for(fun_id = 0; fun_id < PH_FRINFC_SMTCRDFMT_CR; fun_id++) { /* Register for all the callbacks */ RetVal = phFriNfc_NdefSmtCrd_SetCR(gpphLibContext->ndef_cntx.ndef_fmt, fun_id, phLibNfc_Ndef_format_Cb, gpphLibContext); } /* mif_std_key is required to format the mifare 1k/4k card */ for (Index =0 ;Index < (pScrtKey->length); Index++ ) { mif_std_key[Index] = *(pScrtKey->buffer++); } /* Start smart card formatting function */ RetVal = phFriNfc_NdefSmtCrd_Format(gpphLibContext->ndef_cntx.ndef_fmt, mif_std_key); RetVal = PHNFCSTATUS(RetVal); if(RetVal== NFCSTATUS_PENDING) { gpphLibContext->ndef_cntx.pClientNdefFmtCb = pNdefformat_RspCb; gpphLibContext->ndef_cntx.pClientNdefFmtCntx = pContext; gpphLibContext->status.GenCb_pending_status=TRUE; gpphLibContext->LibNfcState.next_state = eLibNfcHalStateTransaction; } else { RetVal = NFCSTATUS_FAILED; } } return RetVal; } /** * Response callback for NDEF format. */ STATIC void phLibNfc_Ndef_format_Cb(void *Context,NFCSTATUS status) { NFCSTATUS RetStatus = NFCSTATUS_SUCCESS; pphLibNfc_RspCb_t pClientCb=NULL; phLibNfc_LibContext_t *pLibNfc_Ctxt = (phLibNfc_LibContext_t *)Context; void *pUpperLayerContext=NULL; phHal_sRemoteDevInformation_t *ps_rem_dev_info = NULL; if(pLibNfc_Ctxt != gpphLibContext) { /*wrong context returned*/ phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1); } else { if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state) { /*shutdown is pending so issue shutdown*/ phLibNfc_Pending_Shutdown(); RetStatus = NFCSTATUS_SHUTDOWN; } else if(eLibNfcHalStateRelease == gpphLibContext->LibNfcState.next_state) { RetStatus = NFCSTATUS_ABORTED; } else { gpphLibContext->status.GenCb_pending_status = FALSE; if(NFCSTATUS_SUCCESS == status) { RetStatus = NFCSTATUS_SUCCESS; } else if(PHNFCSTATUS(status)==NFCSTATUS_FAILED) { RetStatus = NFCSTATUS_FAILED; ps_rem_dev_info = (phHal_sRemoteDevInformation_t *) gpphLibContext->Connected_handle; if ((phHal_eMifare_PICC == ps_rem_dev_info->RemDevType) && (0x08 == (ps_rem_dev_info->RemoteDevInfo.Iso14443A_Info.Sak & 0x08))) { /* card type is mifare 1k/4k, then reconnect */ RetStatus = phHal4Nfc_Connect(gpphLibContext->psHwReference, (phHal_sRemoteDevInformation_t *) gpphLibContext->Connected_handle, (pphHal4Nfc_ConnectCallback_t) phLibNfc_Reconnect_Mifare_Cb, (void *)gpphLibContext); } } else { /*Target was removed during transaction*/ RetStatus = NFCSTATUS_FAILED; } gpphLibContext->LibNfcState.cur_state =eLibNfcHalStateConnect; } phLibNfc_UpdateCurState(status,gpphLibContext); pClientCb = gpphLibContext->ndef_cntx.pClientNdefFmtCb; pUpperLayerContext= gpphLibContext->ndef_cntx.pClientNdefFmtCntx; gpphLibContext->ndef_cntx.pClientNdefFmtCb = NULL; gpphLibContext->ndef_cntx.pClientNdefFmtCntx = NULL; if(NFCSTATUS_PENDING != RetStatus) { if (NULL != pClientCb) { /* Call the tag format upper layer callback */ pClientCb(pUpperLayerContext,RetStatus); } } } return; } STATIC void phLibNfc_Ndef_SrchNdefCnt_Cb(void *context, NFCSTATUS status) { static NFCSTATUS RegPrSt=FALSE; uint8_t RegStatus=0; NFCSTATUS RetVal = NFCSTATUS_SUCCESS ; uint32_t Index=0; PHNFC_UNUSED_VARIABLE(context); if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state) { /*shutdown called before completion of Ndef read allow shutdown to happen */ phLibNfc_Pending_Shutdown(); RetVal = NFCSTATUS_SHUTDOWN; } else if(eLibNfcHalStateRelease == gpphLibContext->LibNfcState.next_state) { RetVal = NFCSTATUS_ABORTED; } else if(NFCSTATUS_SUCCESS != status) { RetVal = status; } else { /* This conditional branch is for QMORE fix */ } gpphLibContext->status.GenCb_pending_status = FALSE; phLibNfc_UpdateCurState(status,gpphLibContext); /* Read is not success send failed to upperlayer Call back*/ if( RetVal!= NFCSTATUS_SUCCESS ) { if((RetVal!=NFCSTATUS_SHUTDOWN)&& (RetVal!=NFCSTATUS_ABORTED)) { RetVal= NFCSTATUS_FAILED; } gpphLibContext->CBInfo.pClientNdefNtfRespCb( gpphLibContext->CBInfo.pClientNdefNtfRespCntx, NULL, gpphLibContext->Connected_handle, RetVal); gpphLibContext->CBInfo.pClientNdefNtfRespCb = NULL; gpphLibContext->CBInfo.pClientNdefNtfRespCntx = NULL; return; } /*Get the Number of records ( If Raw record parameter is null then API gives number of Records*/ RetVal = phFriNfc_NdefRecord_GetRecords( gpphLibContext->phLib_NdefRecCntx.ndef_message.buffer, gpphLibContext->phLib_NdefRecCntx.ndef_message.length, NULL, gpphLibContext->phLib_NdefRecCntx.IsChunked, &(gpphLibContext->phLib_NdefRecCntx.NumberOfRawRecords)); NdefInfo.pNdefMessage = gpphLibContext->phLib_NdefRecCntx.ndef_message.buffer; NdefInfo.NdefMessageLengthActual = gpphLibContext->ndef_cntx.NdefActualSize; NdefInfo.NdefMessageLengthMaximum = gpphLibContext->ndef_cntx.NdefLength; NdefInfo.NdefRecordCount =0; /*Allocate memory to hold the records Read*/ NdefInfo.pNdefRecord = phOsalNfc_GetMemory (sizeof(phFriNfc_NdefRecord_t)* gpphLibContext->phLib_NdefRecCntx.NumberOfRawRecords ); if(NULL==NdefInfo.pNdefRecord) { gpphLibContext->CBInfo.pClientNdefNtfRespCb( gpphLibContext->CBInfo.pClientNdefNtfRespCntx, NULL, gpphLibContext->Connected_handle, NFCSTATUS_FAILED); gpphLibContext->CBInfo.pClientNdefNtfRespCb = NULL; gpphLibContext->CBInfo.pClientNdefNtfRespCntx = NULL; return; } pNdefRecord=NdefInfo.pNdefRecord; /*If phLibNfc_Ndef_SearchNdefContent Reg type is NULL return all the Records*/ if(gpphLibContext->ndef_cntx.pNdef_NtfSrch_Type==NULL) { RetVal = phFriNfc_NdefRecord_GetRecords( gpphLibContext->phLib_NdefRecCntx.ndef_message.buffer, gpphLibContext->phLib_NdefRecCntx.ndef_message.length, gpphLibContext->phLib_NdefRecCntx.RawRecords, gpphLibContext->phLib_NdefRecCntx.IsChunked, &(gpphLibContext->phLib_NdefRecCntx.NumberOfRawRecords)); for (Index = 0; Index < gpphLibContext->phLib_NdefRecCntx.NumberOfRawRecords; Index++) { RetVal = phFriNfc_NdefRecord_Parse( pNdefRecord, gpphLibContext->phLib_NdefRecCntx.RawRecords[Index]); pNdefRecord++; NdefInfo.NdefRecordCount++; } } else { /* Look for registerd TNF */ RetVal = phFriNfc_NdefReg_DispatchPacket( &(gpphLibContext->phLib_NdefRecCntx.NdefReg), gpphLibContext->phLib_NdefRecCntx.ndef_message.buffer, (uint16_t)gpphLibContext->phLib_NdefRecCntx.ndef_message.length); if(NFCSTATUS_SUCCESS != RetVal) { /*phFriNfc_NdefReg_DispatchPacket is failed call upper layer*/ gpphLibContext->CBInfo.pClientNdefNtfRespCb(gpphLibContext->CBInfo.pClientNdefNtfRespCntx, NULL,gpphLibContext->Connected_handle,NFCSTATUS_FAILED); gpphLibContext->CBInfo.pClientNdefNtfRespCb = NULL; gpphLibContext->CBInfo.pClientNdefNtfRespCntx = NULL; return; } while(1 != RegStatus) { /* Process the NDEF records, If match FOUND we will get Call back*/ RegStatus = phFriNfc_NdefReg_Process( &(gpphLibContext->phLib_NdefRecCntx.NdefReg), &RegPrSt); if(RegPrSt == TRUE) { /* Processing Done */ break; } /*If match found the CbParam will be updated by lower layer, copy the record info*/ for(Index=0;IndexphLib_NdefRecCntx.CbParam.Count;Index++) { pNdefRecord->Tnf = gpphLibContext->phLib_NdefRecCntx.CbParam.Records[Index].Tnf; pNdefRecord->TypeLength = gpphLibContext->phLib_NdefRecCntx.CbParam.Records[Index].TypeLength; pNdefRecord->PayloadLength = gpphLibContext->phLib_NdefRecCntx.CbParam.Records[Index].PayloadLength; pNdefRecord->IdLength = gpphLibContext->phLib_NdefRecCntx.CbParam.Records[Index].IdLength; pNdefRecord->Flags = gpphLibContext->phLib_NdefRecCntx.CbParam.Records[Index].Flags; pNdefRecord->Id = phOsalNfc_GetMemory(pNdefRecord->IdLength); pNdefRecord->Type = phOsalNfc_GetMemory(pNdefRecord->TypeLength); pNdefRecord->PayloadData = phOsalNfc_GetMemory(pNdefRecord->PayloadLength); (void)memcpy(pNdefRecord->Id, gpphLibContext->phLib_NdefRecCntx.CbParam.Records[Index].Id, pNdefRecord->IdLength); (void)memcpy(pNdefRecord->PayloadData, gpphLibContext->phLib_NdefRecCntx.CbParam.Records[Index].PayloadData, pNdefRecord->PayloadLength); (void)memcpy(pNdefRecord->Type, gpphLibContext->phLib_NdefRecCntx.CbParam.Records[Index].Type, pNdefRecord->TypeLength); pNdefRecord++; NdefInfo.NdefRecordCount++; } } } /* If no record found call upper layer with failed status*/ if(pNdefRecord == NdefInfo.pNdefRecord) { NdefInfo.NdefRecordCount =0; gpphLibContext->CBInfo.pClientNdefNtfRespCb( gpphLibContext->CBInfo.pClientNdefNtfRespCntx, &NdefInfo,gpphLibContext->Connected_handle, NFCSTATUS_SUCCESS); } else { /*Call upperlayer Call back with match records*/ gpphLibContext->CBInfo.pClientNdefNtfRespCb( gpphLibContext->CBInfo.pClientNdefNtfRespCntx, &NdefInfo,gpphLibContext->Connected_handle, NFCSTATUS_SUCCESS); /*Remove entry from FRI*/ RetVal = phFriNfc_NdefReg_RmCb( &(gpphLibContext->phLib_NdefRecCntx.NdefReg), gpphLibContext->phLib_NdefRecCntx.NdefCb ); /*Free the memory*/ if(gpphLibContext->ndef_cntx.pNdef_NtfSrch_Type!=NULL) { pNdefRecord=NdefInfo.pNdefRecord; for(Index=0;IndexphLib_NdefRecCntx.CbParam.Count;Index++) { phOsalNfc_FreeMemory(pNdefRecord->Id); phOsalNfc_FreeMemory(pNdefRecord->PayloadData); phOsalNfc_FreeMemory(pNdefRecord->Type); pNdefRecord++; } } } gpphLibContext->CBInfo.pClientNdefNtfRespCb = NULL; gpphLibContext->CBInfo.pClientNdefNtfRespCntx = NULL; } STATIC void phLibNfc_Ndef_Rtd_Cb( void *CallBackParam) { /*There will be single call back given to all match It's processed in phLibNfc_Ndef_SrchNdefCnt_Cb*/ PHNFC_UNUSED_VARIABLE(CallBackParam); } NFCSTATUS phLibNfc_Ndef_SearchNdefContent( phLibNfc_Handle hRemoteDevice, phLibNfc_Ndef_SrchType_t* psSrchTypeList, uint8_t uNoSrchRecords, pphLibNfc_Ndef_Search_RspCb_t pNdefNtfRspCb, void * pContext ) { NFCSTATUS RetVal =NFCSTATUS_SUCCESS; uint32_t Index=0; uint8_t cr_index = 0; if((NULL == gpphLibContext) || (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateShutdown)) { RetVal = NFCSTATUS_NOT_INITIALISED; } /* Check the state for DeInit is called or not,if yes return NFCSTATUS_SHUTDOWN*/ else if(gpphLibContext->LibNfcState.next_state == eLibNfcHalStateShutdown) { RetVal= NFCSTATUS_SHUTDOWN; } else if( (NULL == pNdefNtfRspCb) || (NULL == pContext ) || (0 == hRemoteDevice)) { RetVal= NFCSTATUS_INVALID_PARAMETER; } else if( (NULL != psSrchTypeList) && (0==uNoSrchRecords)) { RetVal= NFCSTATUS_INVALID_PARAMETER; } else if(0 == gpphLibContext->Connected_handle) { /*presently no target or tag is connected*/ RetVal=NFCSTATUS_TARGET_NOT_CONNECTED; } else if(hRemoteDevice != gpphLibContext->Connected_handle) { /*This handle of the device sent by application is not connected */ RetVal=NFCSTATUS_INVALID_HANDLE; } else if((TRUE == gpphLibContext->status.GenCb_pending_status) ||(NULL!=gpphLibContext->CBInfo.pClientNdefNtfRespCb)) { /*Previous callback is pending*/ RetVal = NFCSTATUS_REJECTED; } else { gpphLibContext->ndef_cntx.pNdef_NtfSrch_Type = psSrchTypeList; if(psSrchTypeList!=NULL) { /*Maximum records supported*/ gpphLibContext->phLib_NdefRecCntx.NumberOfRecords = 255; /*Reset the FRI component to add the Reg type*/ RetVal = phFriNfc_NdefReg_Reset( &(gpphLibContext->phLib_NdefRecCntx.NdefReg), gpphLibContext->phLib_NdefRecCntx.NdefTypes_array, &(gpphLibContext->phLib_NdefRecCntx.RecordsExtracted), &(gpphLibContext->phLib_NdefRecCntx.CbParam), gpphLibContext->phLib_NdefRecCntx.ChunkedRecordsarray, gpphLibContext->phLib_NdefRecCntx.NumberOfRecords); gpphLibContext->phLib_NdefRecCntx.NdefCb = phOsalNfc_GetMemory(sizeof(phFriNfc_NdefReg_Cb_t)); if(gpphLibContext->phLib_NdefRecCntx.NdefCb==NULL) { /*exception: Not enough memory*/ phOsalNfc_RaiseException(phOsalNfc_e_NoMemory,1); } gpphLibContext->phLib_NdefRecCntx.NdefCb->NdefCallback = phLibNfc_Ndef_Rtd_Cb; /*Copy the TNF types to search in global structure*/ gpphLibContext->phLib_NdefRecCntx.NdefCb->NumberOfRTDs = uNoSrchRecords; for(Index=0;IndexphLib_NdefRecCntx.NdefCb->NdefType[Index] = psSrchTypeList->Type; gpphLibContext->phLib_NdefRecCntx.NdefCb->Tnf[Index] = psSrchTypeList->Tnf ; gpphLibContext->phLib_NdefRecCntx.NdefCb->NdeftypeLength[Index] = psSrchTypeList->TypeLength; psSrchTypeList++; } /* Add the TNF type to FRI component*/ RetVal = phFriNfc_NdefReg_AddCb(&(gpphLibContext->phLib_NdefRecCntx.NdefReg), gpphLibContext->phLib_NdefRecCntx.NdefCb ); } gpphLibContext->phLib_NdefRecCntx.ndef_message.buffer = phOsalNfc_GetMemory(gpphLibContext->ndef_cntx.NdefActualSize); gpphLibContext->phLib_NdefRecCntx.ndef_message.length = gpphLibContext->ndef_cntx.NdefActualSize; /*Set Complete routine for NDEF Read*/ for (cr_index = 0; cr_index < PH_FRINFC_NDEFMAP_CR; cr_index++) { RetVal= phFriNfc_NdefMap_SetCompletionRoutine( gpphLibContext->ndef_cntx.psNdefMap, cr_index, phLibNfc_Ndef_SrchNdefCnt_Cb, (void *)gpphLibContext); } gpphLibContext->ndef_cntx.NdefContinueRead = PH_FRINFC_NDEFMAP_SEEK_BEGIN; /* call below layer Ndef Read*/ RetVal = phFriNfc_NdefMap_RdNdef(gpphLibContext->ndef_cntx.psNdefMap, gpphLibContext->phLib_NdefRecCntx.ndef_message.buffer, (uint32_t*)&gpphLibContext->phLib_NdefRecCntx.ndef_message.length, PH_FRINFC_NDEFMAP_SEEK_BEGIN); if(NFCSTATUS_PENDING == RetVal) { gpphLibContext->CBInfo.pClientNdefNtfRespCb = pNdefNtfRspCb; gpphLibContext->CBInfo.pClientNdefNtfRespCntx = pContext; gpphLibContext->status.GenCb_pending_status=TRUE; gpphLibContext->LibNfcState.next_state = eLibNfcHalStateTransaction; } else if (NFCSTATUS_SUCCESS == RetVal) { RetVal= NFCSTATUS_SUCCESS; } else { /*Ndef read failed*/ RetVal = NFCSTATUS_FAILED; } } return RetVal; }