/*----------------------------------------------------------------------------*/ /* Copyright 2016-2023 NXP */ /* */ /* NXP Confidential. This software is owned or controlled by NXP and may only */ /* be used strictly in accordance with the applicable license terms. */ /* By expressly accepting such terms or by downloading, installing, */ /* activating and/or otherwise using the software, you are agreeing that you */ /* have read, and that you agree to comply with and are bound by, such */ /* license terms. If you do not agree to be bound by the applicable license */ /* terms, then you may not retain, install, activate or otherwise use the */ /* software. */ /*----------------------------------------------------------------------------*/ /** \file * Example Source for NfcrdlibEx3_NFCForum.c that uses the Discovery loop for polling and performs Tag Operations and SNEP PUT operation. * Discovery loop is configured for both POLL and LISTEN modes. This example displays detected tag information(like UID, SAK, Product Type) * and prints information when it detects NFC Forum Tags and gets activated as a target by an external initiator/reader. * Whenever multiple technologies are detected, example will select last detected technology to resolve. * Example will activate device at last index whenever multiple devices are detected. * * If a P2P device is detected then this example performs SNEP PUT operation if both SNEP client and server are enabled. * By default SNEP PUT of URI message (www.nxp.com) will be performed. * * If remote P2P device wants to perform SNEP PUT that should be received by this example then SNEP client should be disabled, in this case * phone acts as client and on screen (Touch to Beam) pops up, when user taps the screen then SNEP PUT will be done by the phone and this * application will receive this SNEP PUT message and displays on console only in Debug mode (Maximum SNEP PUT * message that can be received is 1024Bytes as per default SNEP server specification). * * Please refer Readme.txt file for hardware pin configuration, software configuration and steps to build and * execute the project. This file is present in the same project directory. * $Author: $ * $Revision: $ (v07.10.00) * $Date: $ * */ /** * Reader Library Headers */ #include /* Local headers */ #include #include "NfcrdlibEx3_NFCForum.h" /******************************************************************************* ** Definitions *******************************************************************************/ #if defined (NXPBUILD__PHHAL_HW_RC663) || defined (NXPBUILD__PHHAL_HW_PN7640) # warning "This example is not supported for RC663 and PN7640" int main() { DEBUG_PRINTF("This example is not supported for RC663 and PN7640."); while (1){ } return 0; } /* Actual main defined below has no purpose in this example and hence over-riding it. */ # define main dummy_main #endif /* NXPBUILD__PHHAL_HW_RC663 */ phacDiscLoop_Sw_DataParams_t * pDiscLoop; /* Discovery loop component */ #ifdef NXPBUILD__PHPAL_I18092MPI_SW void * ppalI18092mPI; #endif /* NXPBUILD__PHPAL_I18092MPI_SW */ #ifdef NXPBUILD__PHPAL_I18092MT_SW void * ppalI18092mT; #endif /* NXPBUILD__PHPAL_I18092MT_SW */ void * palTop; #ifdef SNEP_SERVER phnpSnep_Sw_DataParams_t snpSnepServer; /* SNEP component holder */ phlnLlcp_Transport_Socket_t ServerSocket; /* SNEP Server socket and buffers. */ uint8_t bServerRxBuffer[260]; /* SNEP Server socket application buffer to copy data from HAL Rx Buff. */ uint8_t baSnepAppBuffer[1033]; /* SNEP Server application buffer to store received PUT Message */ #endif /* SNEP_SERVER */ #ifdef SNEP_CLIENT phnpSnep_Sw_DataParams_t snpSnepClient; /* SNEP component holder */ phlnLlcp_Transport_Socket_t ClientSocket; /* SNEP Client socket */ uint8_t bClientRxBuffer[260]; /* SNEP Client socket application buffer to copy data from HAL Rx Buff. */ uint32_t dwClientRxBuffLength = sizeof(bClientRxBuffer); #endif /* SNEP_CLIENT */ #if ! defined(SNEP_SERVER) uint8_t baSnepAppBuffer[500]; /* Buffer used to store NDEF data (poll mode) */ #endif /* SNEP_SERVER */ uint32_t baSnepRxLen = 0; uint8_t bDid = 0; /* DID is not used by default. */ uint8_t bBst = 0x00; uint8_t bBrt = 0x00; uint8_t bTo = 8; /* Set TO (time out) value in ATR_RES which will be used to set FDT/FWT on P2P initiator. */ uint8_t bLrt = 3; /* Set LRT value to 3. AS LLCP mandates that LRT value to be 3. */ uint16_t wAtrResLength; /*The below variables are been initialized according to target mode requirements by this application */ uint8_t sens_res[2] = {0x04, 0x00}; /* ATQ bytes - needed for anti-collision */ uint8_t nfc_id1[3] = {0xA1, 0xA2, 0xA3}; /* user defined bytes of the UID (one is hardcoded) - needed for anti-collision */ uint8_t sel_res = 0x40; /* SAK (ISO18092mT) - needed for anti-collision */ uint8_t nfc_id3 = 0xFA; /* NFC3 byte - required for anti-collision */ uint8_t poll_res[18] = {0x01, 0xFE, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0x23, 0x45 }; /* felica - needed for anti-collision */ /* * Internal variables used in this application. */ uint8_t bSNEPServer; uint8_t bSNEPClient; /******************************************************************************* ** Extern Defines *******************************************************************************/ #if defined(NXPBUILD__PHPAL_I18092MPI_SW) || defined(NXPBUILD__PHPAL_I18092MT_SW) /* Defined in phApp_Init.c */ extern uint8_t aLLCPGeneralBytes[]; extern uint8_t bLLCPGBLength; #endif /* defined(NXPBUILD__PHPAL_I18092MPI_SW) || defined(NXPBUILD__PHPAL_I18092MT_SW) */ /* ATR response holder */ extern uint8_t aResponseHolder[64]; /******************************************************************************* ** Const Defines *******************************************************************************/ /* Timeout specification structure */ const phOsal_TimerPeriodObj_t abs_timeout= {OS_TIMER_UNIT_MSEC, 1000}; /******************************************************************************* ** Static Defines *******************************************************************************/ /* This is used to save and restore poll configuration if in case application * has updated/changed polling configuration to resolve a particular technology * when multiple technologies were detected */ static uint16_t bSavePollTechCfg = 0; #ifdef NXPBUILD__PHNP_SNEP_SW static uint32_t dwDataLen = sizeof(baSnepAppBuf); #endif /* NXPBUILD__PHNP_SNEP_SW */ /* Semaphore used in this example application to synchronize tasks to print the received SNEP message by SNEP server. */ #ifdef SNEP_SERVER phOsal_SemObj_t xTaskSema; #endif /* SNEP_SERVER */ #ifdef PHOSAL_FREERTOS_STATIC_MEM_ALLOCATION uint32_t RdLibTaskBuffer[RDLIB_TASK_STACK]; uint32_t SnepServerTaskBuffer[SNEP_SERVER_TASK_STACK]; uint32_t SnepClientTaskBuffer[SNEP_CLIENT_TASK_STACK]; #else /* PHOSAL_FREERTOS_STATIC_MEM_ALLOCATION */ #define RdLibTaskBuffer NULL #define SnepServerTaskBuffer NULL #define SnepClientTaskBuffer NULL #endif /* PHOSAL_FREERTOS_STATIC_MEM_ALLOCATION */ #ifdef PH_OSAL_FREERTOS const uint8_t bTaskNameMain[configMAX_TASK_NAME_LEN] = {"RdLib"}; const uint8_t bTaskNameServer[configMAX_TASK_NAME_LEN] = {"SnepServer"}; const uint8_t bTaskNameClient[configMAX_TASK_NAME_LEN] = {"SnepClient"}; #else const uint8_t bTaskNameMain[] = {"RdLib"}; const uint8_t bTaskNameServer[] = {"SnepServer"}; const uint8_t bTaskNameClient[] = {"SnepClient"}; #endif /* PH_OSAL_FREERTOS */ static volatile uint8_t bInfLoop = 1U; /******************************************************************************* ** Prototypes *******************************************************************************/ static void GetTagInfo(phacDiscLoop_Sw_DataParams_t *pDataParams, uint16_t wNumberOfTags, uint16_t wTagsDetected); static phStatus_t LoadDiscoveryConfiguration(void); /******************************************************************************* ** Extern function for RTOX ** This example will not need RTOX and the function implementation is empty. *******************************************************************************/ void pRtoxCallBck(void) { } /******************************************************************************* ** Code *******************************************************************************/ int main(void) { do { phStatus_t status = PH_ERR_INTERNAL_ERROR; phOsal_ThreadObj_t RdLib; phNfcLib_Status_t dwStatus; phNfcLib_AppContext_t AppContext = {0}; /* Perform Controller specific initialization. */ phApp_CPU_Init(); /* Perform OSAL Initialization. */ (void)phOsal_Init(); DEBUG_PRINTF("\n NFC Forum Example: \n"); #ifdef PH_PLATFORM_HAS_ICFRONTEND status = phbalReg_Init(&sBalParams, sizeof(phbalReg_Type_t)); CHECK_STATUS(status); AppContext.pBalDataparams = &sBalParams; #endif /* PH_PLATFORM_HAS_ICFRONTEND */ AppContext.pRtoxCallback = (void *)pRtoxCallBck; dwStatus = phNfcLib_SetContext(&AppContext); CHECK_NFCLIB_STATUS(dwStatus); /* Initialize library */ dwStatus = phNfcLib_Init(); CHECK_NFCLIB_STATUS(dwStatus); if(dwStatus != PH_NFCLIB_STATUS_SUCCESS) break; /* Set the generic pointer */ pHal = phNfcLib_GetDataParams(PH_COMP_HAL); #ifdef NXPBUILD__PHPAL_I18092MPI_SW ppalI18092mPI = phNfcLib_GetDataParams(PH_COMP_PAL_I18092MPI); #endif /* NXPBUILD__PHPAL_I18092MPI_SW */ #ifdef NXPBUILD__PHPAL_I18092MT_SW ppalI18092mT = phNfcLib_GetDataParams(PH_COMP_PAL_I18092MT); #endif /* NXPBUILD__PHPAL_I18092MT_SW */ palTop = phNfcLib_GetDataParams(PH_COMP_AL_TOP); pDiscLoop = phNfcLib_GetDataParams(PH_COMP_AC_DISCLOOP); /* Initialize other components that are not initialized by NFCLIB and configure Discovery Loop. */ status = phApp_Comp_Init(pDiscLoop); CHECK_STATUS(status); if(status != PH_ERR_SUCCESS) break; /* Perform Platform Init */ status = phApp_Configure_IRQ(); CHECK_STATUS(status); if(status != PH_ERR_SUCCESS) break; RdLib.pTaskName = (uint8_t *)bTaskNameMain; RdLib.pStackBuffer = RdLibTaskBuffer; RdLib.priority = RDLIB_TASK_PRIO; RdLib.stackSizeInNum = RDLIB_TASK_STACK; phOsal_ThreadCreate(&RdLib.ThreadHandle, &RdLib, &TReaderLibrary, pDiscLoop); #ifdef SNEP_SERVER phOsal_ThreadObj_t SnepServer; SnepServer.pTaskName = (uint8_t *)bTaskNameServer; SnepServer.pStackBuffer = SnepServerTaskBuffer; SnepServer.priority = SNEP_SERVER_TASK_PRIO; SnepServer.stackSizeInNum = SNEP_SERVER_TASK_STACK; phOsal_ThreadCreate(&SnepServer.ThreadHandle, &SnepServer, &TSNEPServer, &slnLlcp); #endif /* SNEP_SERVER */ #ifdef SNEP_CLIENT phOsal_ThreadObj_t SnepClient; SnepClient.pTaskName = (uint8_t *)bTaskNameClient; SnepClient.pStackBuffer = SnepClientTaskBuffer; SnepClient.priority = SNEP_CLIENT_TASK_PRIO; SnepClient.stackSizeInNum = SNEP_CLIENT_TASK_STACK; phOsal_ThreadCreate(&SnepClient.ThreadHandle, &SnepClient, &TSNEPClient, &slnLlcp); #endif /* SNEP_CLIENT */ phOsal_StartScheduler(); DEBUG_PRINTF("RTOS error : Scheduler exited. \n"); } while(0); while(bInfLoop); /* Comes here if initialization failure or scheduler exit due to error */ return 0; } /** * This Task demonstrates the usage of discovery loop. * It detects and reports the NFC technology type and performs read NDEF in case any NFC forum tags are detected. * If a P2P device is detected then LLCP activate will be called to perform Client/Server operation from another Task. * \param pDataParams The discovery loop data parameters * \note This Task will never return and Discovery loop run will be called in a infinite while loop. */ void TReaderLibrary(void *pDataParams) { phStatus_t status; #ifdef NXPBUILD__PHPAL_I18092MPI_SW phStatus_t statustmp; #endif /* NXPBUILD__PHPAL_I18092MPI_SW */ uint16_t wTagsDetected = 0; uint16_t wNumberOfTags = 0; uint16_t wEntryPoint; uint16_t wValue; #ifdef NXPBUILD__PHPAL_I18092MT_SW #ifdef NXPBUILD__PHAC_DISCLOOP_TARGET uint16_t wGeneralBytesLength; uint8_t * pGeneralBytes; #endif /* NXPBUILD__PHAC_DISCLOOP_TARGET */ #endif /* NXPBUILD__PHPAL_I18092MT_SW */ #ifdef NXPBUILD__PHPAL_I18092MPI_SW uint16_t wGtLength; uint8_t bGBLen = 0; #endif /* NXPBUILD__PHPAL_I18092MPI_SW */ uint8_t bIndex; #ifdef SNEP_SERVER uint32_t i = 0; #endif /* SNEP_SERVER */ /* This call shall allocate secure context before calling any secure function, * when FreeRtos trust zone is enabled. * */ phOsal_ThreadSecureStack( 512 ); /* Configure HAL target parameters */ status = phApp_HALConfigAutoColl(); CHECK_STATUS(status); /* Configure discover loop based on the enabled macros i.e. ACTIVE_MODE, PASSIVE_MODE, INITIATOR_MODE, TARGET_MODE. */ LoadDiscoveryConfiguration(); #ifdef NXPBUILD__PHPAL_I18092MPI_SW /* Set max retry count of 1 in PAL 18092 Initiator to allow only one MAC recovery cycle. */ status = phpalI18092mPI_SetConfig(ppalI18092mPI, PHPAL_I18092MPI_CONFIG_MAXRETRYCOUNT, 0x01); CHECK_STATUS(status); #endif /* NXPBUILD__PHPAL_I18092MPI_SW */ #if defined INITIATOR_MODE /* Start in poll mode */ wEntryPoint = PHAC_DISCLOOP_ENTRY_POINT_POLL; status = PHAC_DISCLOOP_LPCD_NO_TECH_DETECTED; #elif defined TARGET_MODE /* Start in listen mode */ wEntryPoint = PHAC_DISCLOOP_ENTRY_POINT_LISTEN; #endif while(bInfLoop) { #ifdef PH_EXAMPLE3_LPCD_ENABLE /* Configure LPCD */ if((status & PH_ERR_MASK) == PHAC_DISCLOOP_LPCD_NO_TECH_DETECTED) { status = phApp_ConfigureLPCD(); CHECK_STATUS(status); } /* Bool to enable LPCD feature. */ status = phacDiscLoop_SetConfig(pDataParams, PHAC_DISCLOOP_CONFIG_ENABLE_LPCD, PH_ON); CHECK_STATUS(status); #endif /* PH_EXAMPLE3_LPCD_ENABLE */ #ifdef NXPBUILD__PHPAL_I18092MPI_SW /* Reset local variables used. */ bGBLen = 0; #endif /* NXPBUILD__PHPAL_I18092MPI_SW */ /* Set Discovery poll state to detection */ status = phacDiscLoop_SetConfig(pDataParams, PHAC_DISCLOOP_CONFIG_NEXT_POLL_STATE, PHAC_DISCLOOP_POLL_STATE_DETECTION); CHECK_STATUS(status); /* Switch off RF field */ status = phhalHw_FieldOff(pHal); CHECK_STATUS(status); /* Wait for field-off time-out */ status = phhalHw_Wait(pHal, PHHAL_HW_TIME_MICROSECONDS, 5100); CHECK_STATUS(status); /* Start discovery loop */ status = phacDiscLoop_Run(pDataParams, wEntryPoint); if(wEntryPoint == PHAC_DISCLOOP_ENTRY_POINT_POLL) { if((status & PH_ERR_MASK) == PHAC_DISCLOOP_MULTI_TECH_DETECTED) { DEBUG_PRINTF (" \n Multiple technology detected: \n"); status = phacDiscLoop_GetConfig(pDataParams, PHAC_DISCLOOP_CONFIG_TECH_DETECTED, &wTagsDetected); CHECK_STATUS(status); if(PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_A)) { DEBUG_PRINTF (" \tType A detected... \n"); } if(PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_B)) { DEBUG_PRINTF (" \tType B detected... \n"); } if(PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_F212)) { DEBUG_PRINTF (" \tType F detected with baud rate 212... \n"); } if(PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_F424)) { DEBUG_PRINTF (" \tType F detected with baud rate 424... \n"); } if(PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_V)) { DEBUG_PRINTF(" \tType V / ISO 15693 / T5T detected... \n"); } /* Store user configured poll configuration. */ status = phacDiscLoop_GetConfig(pDataParams, PHAC_DISCLOOP_CONFIG_PAS_POLL_TECH_CFG, &bSavePollTechCfg); CHECK_STATUS(status); /* Select last detected technology to resolve. */ for(bIndex = 0; bIndex < PHAC_DISCLOOP_PASS_POLL_MAX_TECHS_SUPPORTED; bIndex++) { if(PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, (1 << bIndex))) { /* Configure for one of the detected technology. */ status = phacDiscLoop_SetConfig(pDataParams, PHAC_DISCLOOP_CONFIG_PAS_POLL_TECH_CFG, (1 << bIndex)); CHECK_STATUS(status); } } DEBUG_PRINTF ("\tResolving selected technology \n"); /* Set Discovery loop poll state to collision resolution. */ status = phacDiscLoop_SetConfig(pDataParams, PHAC_DISCLOOP_CONFIG_NEXT_POLL_STATE, PHAC_DISCLOOP_POLL_STATE_COLLISION_RESOLUTION); CHECK_STATUS(status); /* Start Discovery loop in pool mode from collision resolution phase */ status = phacDiscLoop_Run(pDataParams, wEntryPoint); if((status & PH_ERR_MASK) == PHAC_DISCLOOP_MULTI_DEVICES_RESOLVED) { /* Get detected technology type */ status = phacDiscLoop_GetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_TECH_DETECTED, &wTagsDetected); CHECK_STATUS(status); /* Get number of tags detected */ status = phacDiscLoop_GetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_NR_TAGS_FOUND, &wNumberOfTags); CHECK_STATUS(status); DEBUG_PRINTF (" \n Multiple cards resolved: %d cards \n",wNumberOfTags); GetTagInfo(pDataParams, wNumberOfTags, wTagsDetected); if(wNumberOfTags > 1) { /* Get 1st Detected Tag and Activate device at index 0*/ for(bIndex = 0; bIndex < PHAC_DISCLOOP_PASS_POLL_MAX_TECHS_SUPPORTED; bIndex++) { if(PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, (1 << bIndex))) { DEBUG_PRINTF("\t Activating one card...\n"); status = phacDiscLoop_ActivateCard(pDataParams, bIndex, 0); break; } } if(((status & PH_ERR_MASK) == PHAC_DISCLOOP_DEVICE_ACTIVATED) || ((status & PH_ERR_MASK) == PHAC_DISCLOOP_PASSIVE_TARGET_ACTIVATED)) { /* Get Activated Technology Type */ status = phacDiscLoop_GetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_TECH_DETECTED, &wTagsDetected); CHECK_STATUS(status); /* Print card details */ GetTagInfo(pDataParams, 0x01, wTagsDetected); DEBUG_PRINTF("\tActivation successful\n"); } else { DEBUG_PRINTF("\tCard activation failed\n"); } } } else if((status & PH_ERR_MASK) == PHAC_DISCLOOP_DEVICE_ACTIVATED) { DEBUG_PRINTF (" \tCard detected and activated successfully. \n"); /* Get activated technology type */ status = phacDiscLoop_GetConfig(pDataParams, PHAC_DISCLOOP_CONFIG_TECH_DETECTED, &wTagsDetected); CHECK_STATUS(status); /*Print card info*/ GetTagInfo(pDataParams, 0x01, wTagsDetected); } #ifdef NXPBUILD__PHLN_LLCP_SW else if ((status & PH_ERR_MASK) == PHAC_DISCLOOP_PASSIVE_TARGET_ACTIVATED) { DEBUG_PRINTF (" \nPassive P2P target detected and activated successfully after collision resolution: \n"); /* Assign the PAL 18092 initiator parameters once LLPC should be activated in initiator mode. */ slnLlcp.pPalI18092DataParams = ppalI18092mPI; /* Get the ATR_RES length. */ status = phacDiscLoop_GetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_TYPEF_P2P_ATR_RES_LEN, &wGtLength); CHECK_STATUS(status); bGBLen = (uint8_t)wGtLength; if (bGBLen >= PHLN_LLCP_ATR_RES_MIN_LEN + 3) { /* Activate LLCP with the received ATR_RES in initiator mode. */ status = phlnLlcp_Activate(&slnLlcp, &aResponseHolder[PHLN_LLCP_ATR_RES_MIN_LEN], (bGBLen - PHLN_LLCP_ATR_RES_MIN_LEN), PHLN_LLCP_INITIATOR ); phOsal_EventClear(&slnLlcp.LlcpEventObj.EventHandle, E_OS_EVENT_OPT_NONE, E_PH_OSAL_EVT_LLCP_ACTIVATED, NULL); if (!(((status & PH_ERR_MASK) == PH_ERR_LLCP_DEACTIVATED) || ((status & PH_ERR_MASK) == PH_ERR_PEER_DISCONNECTED))) { if ((status & PH_ERR_MASK) == PH_ERR_ABORTED) { PRINT_INFO("LLCP exited because of LTO timeout. \n"); } else if ((status & PH_ERR_MASK) == PH_ERR_RF_ERROR) { PRINT_INFO("LLCP exited because of RF error. \n"); } else { PRINT_INFO("\n LLCP exited unexpectedly:"); PrintErrorInfo(status); } } /* Perform LLCP DeInit procedure to release acquired resources. */ status = phlnLlcp_DeInit(&slnLlcp); CHECK_STATUS(status); if (bSNEPClient == SNEP_PUT) { DEBUG_PRINTF("\t SNEP Client : Performed SNEP PUT\n\t PUT data length is:%d\n\n", dwDataLen); } #ifdef SNEP_SERVER /* * Waits on SNEP server to receive SNEP message from a client. * If the server gives this semaphore, then it indicates that * the message has been received and gets printed. */ status = phOsal_SemPend(&xTaskSema.SemHandle, abs_timeout); if ((bSNEPServer == SNEP_RECEIVED_PUT) && (status == PH_ERR_SUCCESS)) { DEBUG_PRINTF("\t SNEP Server : Received PUT message of length %d bytes\n", baSnepRxLen); for(i = 0; i < baSnepRxLen; i++) { if((baSnepAppBuffer[i] < 0x20) || (baSnepAppBuffer[i] > 0x7e)) { baSnepAppBuffer[i] = '.'; } } baSnepAppBuffer[baSnepRxLen] = '\0'; DEBUG_PRINTF("\t PUT message : %s\n", baSnepAppBuffer); baSnepRxLen = 0; } #endif /* SNEP_SERVER */ bSNEPClient = 0; bSNEPServer = 0; } else { PRINT_INFO("Received ATR_RES length is wrong. \n"); } } #endif /* NXPBUILD__PHLN_LLCP_SW */ else { PRINT_INFO("\tFailed to resolve selected technology.\n"); } /* Re-Store user configured poll configuration. */ status = phacDiscLoop_SetConfig(pDataParams, PHAC_DISCLOOP_CONFIG_PAS_POLL_TECH_CFG, bSavePollTechCfg); CHECK_STATUS(status); /* Switch to LISTEN mode if supported after POLL mode */ }/* PHAC_DISCLOOP_MULTI_TECH_DETECTED - End */ else if (((status & PH_ERR_MASK) == PHAC_DISCLOOP_NO_TECH_DETECTED) || ((status & PH_ERR_MASK) == PHAC_DISCLOOP_NO_DEVICE_RESOLVED)) { /* Switch to LISTEN mode if supported after POLL mode */ } else if((status & PH_ERR_MASK) == PHAC_DISCLOOP_EXTERNAL_RFON) { /* * If external RF is detected during POLL, return back so that the application * can restart the loop in LISTEN mode if supported. */ } #ifdef NXPBUILD__PHPAL_I18092MPI_SW else if(((status & PH_ERR_MASK) == PHAC_DISCLOOP_PASSIVE_TARGET_ACTIVATED) ||((status & PH_ERR_MASK) == PHAC_DISCLOOP_ACTIVE_TARGET_ACTIVATED) ||((status & PH_ERR_MASK) == PHAC_DISCLOOP_MERGED_SEL_RES_FOUND)) { /* Get detected technology type */ statustmp = phacDiscLoop_GetConfig(pDataParams, PHAC_DISCLOOP_CONFIG_TECH_DETECTED, &wTagsDetected); CHECK_STATUS(statustmp); if ((status & PH_ERR_MASK) == PHAC_DISCLOOP_ACTIVE_TARGET_ACTIVATED) { if(PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_ACT_POS_BIT_MASK_106)) { DEBUG_PRINTF ("\nActive P2P target detected and activated successfully at 106kbps. \n"); /* Get the ATR_RES length. */ status = phacDiscLoop_GetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_TYPEA_P2P_ATR_RES_LEN, &wGtLength); CHECK_STATUS(status); } else if((PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_ACT_POS_BIT_MASK_212)) || (PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_ACT_POS_BIT_MASK_424))) { DEBUG_PRINTF ("\nActive P2P target detected and activated successfully at 212/424kbps. \n"); /* Get the ATR_RES length. */ status = phacDiscLoop_GetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_TYPEF_P2P_ATR_RES_LEN, &wGtLength); CHECK_STATUS(status); } else { DEBUG_PRINTF("\nUnknown Active P2P target detected. \n"); } /* Save the ATR_RES length. */ bGBLen = (uint8_t)wGtLength; } else if ((status & PH_ERR_MASK) == PHAC_DISCLOOP_MERGED_SEL_RES_FOUND) { DEBUG_PRINTF (" \n Merged SAK: Device having T4T and NFC-DEP support detected.\n"); /* Send ATR_REQ to activate device in P2P mode. */ status = phpalI18092mPI_Atr(ppalI18092mPI, pDiscLoop->sTypeATargetInfo.aTypeA_I3P3[0].aUid, 0x00, 0x03, 0x00, 0x00, aLLCPGeneralBytes, pDiscLoop->sTypeATargetInfo.sTypeA_P2P.bGiLength, aResponseHolder, &bGBLen ); CHECK_STATUS(status); } else { if(PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_A)) { DEBUG_PRINTF ("\nPassive P2P target detected and activated successfully at 106kbps. \n"); /* Get the ATR_RES Length. */ status = phacDiscLoop_GetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_TYPEA_P2P_ATR_RES_LEN, &wGtLength); CHECK_STATUS(status); } else if((PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_F212)) || (PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_F424))) { DEBUG_PRINTF ("\nPassive P2P target detected and activated successfully at 212/424kbps. \n"); /* Get the ATR_RES Length. */ status = phacDiscLoop_GetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_TYPEF_P2P_ATR_RES_LEN, &wGtLength); CHECK_STATUS(status); } else { DEBUG_PRINTF("\nUnknown passive P2P target detected. \n"); } /* Save the ATR_RES length. */ bGBLen = (uint8_t)wGtLength; } /* Assign the PAL 18092 Initiator Parameters once LLPC should be activated in Initiator Mode. */ slnLlcp.pPalI18092DataParams = ppalI18092mPI; if (bGBLen >= (PHLN_LLCP_ATR_RES_MIN_LEN + 3)) { /* Activate LLCP with the received ATR_RES in initiator mode. */ status = phlnLlcp_Activate(&slnLlcp, &aResponseHolder[PHLN_LLCP_ATR_RES_MIN_LEN], (bGBLen - PHLN_LLCP_ATR_RES_MIN_LEN), PHLN_LLCP_INITIATOR ); phOsal_EventClear(&slnLlcp.LlcpEventObj.EventHandle, E_OS_EVENT_OPT_NONE, E_PH_OSAL_EVT_LLCP_ACTIVATED, NULL); if (!(((status & PH_ERR_MASK) == PH_ERR_LLCP_DEACTIVATED) || ((status & PH_ERR_MASK) == PH_ERR_PEER_DISCONNECTED))) { if ((status & PH_ERR_MASK) == PH_ERR_ABORTED) { PRINT_INFO("LLCP exited because of LTO timeout. \n"); } else if ((status & PH_ERR_MASK) == PH_ERR_RF_ERROR) { PRINT_INFO("LLCP exited because of active RF error. \n"); } else { PRINT_INFO("\n LLCP exited unexpectedly:"); PrintErrorInfo(status); } } /* Perform LLCP DeInit procedure to release acquired resources. */ status = phlnLlcp_DeInit(&slnLlcp); CHECK_STATUS(status); if (bSNEPClient == SNEP_PUT) { DEBUG_PRINTF("\t SNEP Client : Performed SNEP PUT\n\t PUT data length is:%d\n\n", dwDataLen); } #ifdef SNEP_SERVER /* * Waits on SNEP server to receive SNEP message from a client. * If the server gives this semaphore, then it indicates that * the message has been received and gets printed. */ status = phOsal_SemPend(&xTaskSema.SemHandle, abs_timeout); if ((bSNEPServer == SNEP_RECEIVED_PUT) && (status == PH_ERR_SUCCESS)) { DEBUG_PRINTF("\t SNEP Server : Received PUT message of length %d bytes\n", baSnepRxLen); for(i = 0; i < baSnepRxLen; i++) { if((baSnepAppBuffer[i] < 0x20) || (baSnepAppBuffer[i] > 0x7e)) { baSnepAppBuffer[i] = '.'; } } baSnepAppBuffer[baSnepRxLen] = '\0'; DEBUG_PRINTF("\t PUT Message : %s\n", baSnepAppBuffer); baSnepRxLen = 0; } #endif /* SNEP_SERVER */ bSNEPClient = 0; bSNEPServer = 0; } else { PRINT_INFO("Received ATR_RES doesn't contain LLCP magic bytes. Raw P2P is possible. \n"); } /* Switch to LISTEN mode if supported after POLL mode */ } #endif /* NXPBUILD__PHPAL_I18092MPI_SW */ else if((status & PH_ERR_MASK) == PHAC_DISCLOOP_MULTI_DEVICES_RESOLVED) { /* * Multiple cards resolved. It enters here if DEVICE LIMIT > 1 and more than one devices are * detected and resolved. */ DEBUG_PRINTF (" \n Multiple cards resolved: \n"); /* Get detected technology type */ status = phacDiscLoop_GetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_TECH_DETECTED, &wTagsDetected); CHECK_STATUS(status); /* Get number of tags detected */ status = phacDiscLoop_GetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_NR_TAGS_FOUND, &wNumberOfTags); CHECK_STATUS(status); DEBUG_PRINTF ("\tNumber of tags: %d \n",wNumberOfTags); GetTagInfo(pDataParams, wNumberOfTags, wTagsDetected); if(wNumberOfTags > 1) { /* Get 1st detected tag and activate device at index 0 */ for(bIndex = 0; bIndex < PHAC_DISCLOOP_PASS_POLL_MAX_TECHS_SUPPORTED; bIndex++) { if(PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, (1 << bIndex))) { DEBUG_PRINTF("\t Activating device @ index 0\n"); status = phacDiscLoop_ActivateCard(pDataParams, bIndex, 0); break; } } if( ((status & PH_ERR_MASK) == PHAC_DISCLOOP_DEVICE_ACTIVATED) || ((status & PH_ERR_MASK) == PHAC_DISCLOOP_PASSIVE_TARGET_ACTIVATED)) { /* Get detected technology type */ status = phacDiscLoop_GetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_TECH_DETECTED, &wTagsDetected); CHECK_STATUS(status); GetTagInfo(pDataParams, 0x01, wTagsDetected); DEBUG_PRINTF("\t\t Activation successful\n"); } else { DEBUG_PRINTF("\t\tCard activation failed\n"); } } /* Switch to LISTEN mode if supported after POLL mode */ } else if((status & PH_ERR_MASK) == PHAC_DISCLOOP_DEVICE_ACTIVATED) { DEBUG_PRINTF (" \n Card detected and activated successfully \n"); status = phacDiscLoop_GetConfig(pDataParams, PHAC_DISCLOOP_CONFIG_NR_TAGS_FOUND, &wNumberOfTags); CHECK_STATUS(status); /* Get detected technology type */ status = phacDiscLoop_GetConfig(pDataParams, PHAC_DISCLOOP_CONFIG_TECH_DETECTED, &wTagsDetected); CHECK_STATUS(status); DEBUG_PRINTF ("\tNumber of tags: %d \n",wNumberOfTags); GetTagInfo(pDataParams, wNumberOfTags, wTagsDetected); /* Switch to LISTEN mode if supported after POLL mode */ } else { if((status & PH_ERR_MASK) == PHAC_DISCLOOP_FAILURE) { status = phacDiscLoop_GetConfig(pDataParams, PHAC_DISCLOOP_CONFIG_ADDITIONAL_INFO, &wValue); CHECK_STATUS(status); PRINT_INFO("\n Discovery loop:"); DEBUG_ERROR_PRINT(PrintErrorInfo(wValue)); } else { PRINT_INFO("\n Discovery loop:"); DEBUG_ERROR_PRINT(PrintErrorInfo(wValue)); } } #ifdef TARGET_MODE /* Start in listen mode */ wEntryPoint = PHAC_DISCLOOP_ENTRY_POINT_LISTEN; #endif /* TARGET_MODE */ } else { if((status & PH_ERR_MASK) == PHAC_DISCLOOP_EXTERNAL_RFOFF) { /* * Enters here if in the target/card mode and external RF is not available * Wait for LISTEN timeout till an external RF is detected. * Application may choose to go into standby at this point. */ status = phhalHw_EventConsume(pHal); CHECK_STATUS(status); status = phhalHw_SetConfig(pHal, PHHAL_HW_CONFIG_RFON_INTERRUPT, PH_ON); CHECK_STATUS(status); status = phhalHw_EventWait(pHal, LISTEN_PHASE_TIME_MS); if((status & PH_ERR_MASK) == PH_ERR_IO_TIMEOUT) { /* Switch to poll mode */ wEntryPoint = PHAC_DISCLOOP_ENTRY_POINT_POLL; } else { /* Switch to listen mode */ wEntryPoint = PHAC_DISCLOOP_ENTRY_POINT_LISTEN; } } #ifdef NXPBUILD__PHPAL_I18092MT_SW else if((status & PH_ERR_MASK) == PHAC_DISCLOOP_ACTIVATED_BY_PEER) { DEBUG_PRINTF ("\nDevice activated in listen mode. \n"); #ifdef NXPBUILD__PHAC_DISCLOOP_TARGET /* Assign the PAL 18092 target parameters once LLPC should be activated in listen mode. */ slnLlcp.pPalI18092DataParams = ppalI18092mT; memcpy(aResponseHolder, poll_res,10); #ifdef NXPBUILD__PHHAL_HW_PN7462AU aResponseHolder[8] = 0xC0; aResponseHolder[9] = 0xC1; #endif /* NXPBUILD__PHHAL_HW_PN7462AU*/ aResponseHolder[10] = bBst; aResponseHolder[11] = bBrt; aResponseHolder[12] = bTo; aResponseHolder[13] = bLrt << 4 | 0x02; /* Frame Size is 254 and ATR_RES contains General Bytes. */ memcpy(&aResponseHolder[14], aLLCPGeneralBytes, bLLCPGBLength); wAtrResLength = 14 + bLLCPGBLength; status = phpalI18092mT_Activate(ppalI18092mT, pDiscLoop->sTargetParams.pRxBuffer, pDiscLoop->sTargetParams.wRxBufferLen, aResponseHolder, wAtrResLength, &pGeneralBytes, &wGeneralBytesLength ); if((status & PH_ERR_MASK) == PH_ERR_SUCCESS) { /* Activate LLCP with the received ATR_REQ in target mode. */ status = phlnLlcp_Activate(&slnLlcp, pGeneralBytes, wGeneralBytesLength, PHLN_LLCP_TARGET ); phOsal_EventClear(&slnLlcp.LlcpEventObj.EventHandle, E_OS_EVENT_OPT_NONE, E_PH_OSAL_EVT_LLCP_ACTIVATED, NULL); if (!(((status & PH_ERR_MASK) == PH_ERR_LLCP_DEACTIVATED) || ((status & PH_ERR_MASK) == PH_ERR_PEER_DISCONNECTED))) { if ((status & PH_ERR_MASK) == PH_ERR_ABORTED) { PRINT_INFO("LLCP exited because of LTO timeout. \n"); } else if ((status & PH_ERR_MASK) == PH_ERR_EXT_RF_ERROR) { PRINT_INFO("LLCP exited because of external RF Off. \n"); } else if ((status & PH_ERR_MASK) == PH_ERR_RF_ERROR) { PRINT_INFO("LLCP exited because of active RF error. \n"); } else { PRINT_INFO("\n LLCP exited unexpectedly:"); PrintErrorInfo(status); } } if (bSNEPClient == SNEP_PUT) { DEBUG_PRINTF("\t SNEP Client : Performed SNEP PUT\n\t PUT data length is:%d\n\n", dwDataLen); } #ifdef SNEP_SERVER /* * Waits on SNEP server to receive SNEP message from a client. * If the server gives this semaphore, then it indicates that * the message has been received and gets printed. */ status = phOsal_SemPend(&xTaskSema.SemHandle, abs_timeout); if ((bSNEPServer == SNEP_RECEIVED_PUT) && (status == PH_ERR_SUCCESS)) { DEBUG_PRINTF("\t SNEP Server : Received PUT message of length %d bytes\n", baSnepRxLen); for(i = 0; i < baSnepRxLen; i++) { if((baSnepAppBuffer[i] < 0x20) || (baSnepAppBuffer[i] > 0x7e)) { baSnepAppBuffer[i] = '.'; } } baSnepAppBuffer[baSnepRxLen] = '\0'; DEBUG_PRINTF("\t PUT Message : %s\n", baSnepAppBuffer); baSnepRxLen = 0; } #endif /* SNEP_SERVER */ bSNEPClient = 0; bSNEPServer = 0; /* Perform LLCP DeInit procedure to release acquired resources. */ status = phlnLlcp_DeInit(&slnLlcp); CHECK_STATUS(status); } else { PRINT_INFO("\n phpalI18092mT_Activate failed :"); PrintErrorInfo(status); } #endif /* NXPBUILD__PHAC_DISCLOOP_TARGET */ } #endif /* NXPBUILD__PHPAL_I18092MT_SW */ else { if((status & PH_ERR_MASK) == PHAC_DISCLOOP_FAILURE) { status = phacDiscLoop_GetConfig(pDataParams, PHAC_DISCLOOP_CONFIG_ADDITIONAL_INFO, &wValue); CHECK_STATUS(status); PRINT_INFO("\n Discovery loop:"); DEBUG_ERROR_PRINT(PrintErrorInfo(wValue)); } else { PRINT_INFO("\n Discovery loop:"); DEBUG_ERROR_PRINT(PrintErrorInfo(wValue)); } } /* On successful activated by Peer, switch to POLL mode */ wEntryPoint = PHAC_DISCLOOP_ENTRY_POINT_POLL; } /* Reset state of layers. */ (void)phalTop_Reset(palTop); #ifdef NXPBUILD__PHPAL_I14443P4_SW (void)phpalI14443p4_ResetProtocol(phNfcLib_GetDataParams(PH_COMP_PAL_ISO14443P4)); #endif /* NXPBUILD__PHPAL_I14443P4_SW */ #ifdef NXPBUILD__PHPAL_I18092MPI_SW (void)phpalI18092mPI_ResetProtocol(ppalI18092mPI); #endif /* NXPBUILD__PHPAL_I14443P4_SW */ #ifdef NXPBUILD__PHPAL_I18092MT_SW /* This component is disabled for Rc663. But the example have to build for Rc663 in Linux. */ (void)phpalI18092mT_ResetProtocol(ppalI18092mT); #endif /* NXPBUILD__PHPAL_I14443P4_SW */ } } #ifdef SNEP_SERVER /** * Task 2 : SNEP server task * This task will first block on LLCP activated event from reader library thread, once * event is obtained this task will register SNEP server socket on LLCP running in reader * library thread and will wait for remote client to get connected and perform SNEP PUT operation. * \note : SNEP server task will run in a infinite while loop. */ void TSNEPServer(void * pLlcp) { phStatus_t status = 0; uint32_t dwServerRxBuffLength = sizeof(bServerRxBuffer); uint32_t baSnepAppBufSize = sizeof(baSnepAppBuffer) - 1; uint8_t bClientReq; int ret; ret = phOsal_SemCreate(&xTaskSema.SemHandle, &xTaskSema, E_OS_SEM_OPT_SIGNALLING_SEM); if (ret != 0) { DEBUG_PRINTF ("Server task application semaphore could not be created.\n"); } do{ /* Wait until LLCP activation is complete. */ status = phlnLlcp_WaitForActivation(pLlcp); CHECK_STATUS(status); baSnepRxLen = 0; bSNEPServer = 0; /* Initialize SNEP server component. */ status = phnpSnep_Sw_Init(&snpSnepServer, sizeof(phnpSnep_Sw_DataParams_t), &slnLlcp, &ServerSocket); CHECK_STATUS(status); /* Perform server initialization to handle remote SNEP client connection. */ status = phnpSnep_ServerInit(&snpSnepServer, phnpSnep_Default_Server, NULL, bServerRxBuffer, dwServerRxBuffLength); if (status == PH_ERR_SUCCESS) { do { /* Handle client PUT request. */ status = phnpSnep_ServerListen(&snpSnepServer, 0, NULL, NULL, &bClientReq); if (status == PH_ERR_SUCCESS) { status = phnpSnep_ServerSendResponse(&snpSnepServer, bClientReq, NULL, 0, baSnepAppBufSize, baSnepAppBuffer, &baSnepRxLen); } }while(!status); if (!(((status & PH_ERR_MASK) == PH_ERR_PEER_DISCONNECTED) || ((status & PH_ERR_MASK) == PH_ERR_LLCP_DEACTIVATED)) || ((status & PH_ERR_MASK) == PH_ERR_SUCCESS)) { CHECK_STATUS(status); } else { if (baSnepRxLen > 0) { /* Print only if server received PUT message of length greater than 0 bytes. */ bSNEPServer = SNEP_RECEIVED_PUT; } } status = phOsal_SemPost(&xTaskSema.SemHandle, E_OS_SEM_OPT_NONE); } else { /* Server initialization is un-successful as peer did not send CONNECT PDU. */ } phOsal_EventClear(&slnLlcp.LlcpEventObj.EventHandle, E_OS_EVENT_OPT_NONE, E_PH_OSAL_EVT_LLCP_ACTIVATED, NULL); /* Perform server de-init. */ status = phnpSnep_ServerDeInit(&snpSnepServer); CHECK_STATUS(status); }while(bInfLoop); } #endif /* SNEP_SERVER */ #ifdef SNEP_CLIENT /** * Task 3 : SNEP client task. * This task will first block on LLCP activated event from reader library thread, once * event is obtained this task will register client socket on LLCP running in reader * library thread and will connect to remote SNEP server and performs SNEP PUT operation. * \note : SNEP client task will run in a infinite while loop. */ void TSNEPClient(void * pLlcp) { phStatus_t status = 0; while (bInfLoop) { do{ /* Wait until LLCP activation is complete. */ status = phlnLlcp_WaitForActivation(&slnLlcp); CHECK_STATUS(status); /* Initialize SNEP client component */ status = phnpSnep_Sw_Init(&snpSnepClient, sizeof(snpSnepClient), &slnLlcp, &ClientSocket); CHECK_STATUS(status); /* Perform SNEP client Initialization and connect to remote SNEP server. */ status = phnpSnep_ClientInit(&snpSnepClient, phnpSnep_Default_Server, NULL, bClientRxBuffer, dwClientRxBuffLength); if (status == PH_ERR_SUCCESS) { status = phnpSnep_Put(&snpSnepClient, (uint8_t *)baSnepAppBuf, dwDataLen); ClientSocket.fReady = true; phOsal_EventClear(&slnLlcp.LlcpEventObj.EventHandle, E_OS_EVENT_OPT_NONE, E_PH_OSAL_EVT_LLCP_ACTIVATED, NULL); if ((status & PH_ERR_MASK) == PH_ERR_SUCCESS) { status = phnpSnep_ClientDeInit(&snpSnepClient); if ((status & PH_ERR_MASK) == PH_ERR_SUCCESS) { status = phlnLlcp_Deactivate(&slnLlcp); } bSNEPClient = SNEP_PUT; } else { status = phlnLlcp_Transport_Socket_Unregister(snpSnepClient.plnLlcpDataParams, snpSnepClient.psSocket); CHECK_STATUS(status); } } else { phOsal_EventClear(&slnLlcp.LlcpEventObj.EventHandle, E_OS_EVENT_OPT_NONE, E_PH_OSAL_EVT_LLCP_ACTIVATED, NULL); /* Client initialization is un-successful as failed to connect to remote server. * Release RTOS memory by performing socket unregister. */ status = phlnLlcp_Transport_Socket_Unregister(snpSnepClient.plnLlcpDataParams, snpSnepClient.psSocket); CHECK_STATUS(status); } } while ((status == PH_ERR_PEER_DISCONNECTED) || (status == PH_ERR_LLCP_DEACTIVATED) || (status == PH_ERR_SUCCESS)); } } #endif /* SNEP_CLIENT */ /** * This function will load/configure Discovery loop with default values based on interested profiles. * Application can read these values from EEPROM area and load/configure Discovery loop via SetConfig * \param bProfile Reader Library Profile * \note Values used below are default and is for demonstration purpose. */ static phStatus_t LoadDiscoveryConfiguration(void) { phStatus_t status = PH_ERR_SUCCESS; uint16_t wPasPollConfig = 0; uint16_t wActPollConfig = 0; uint16_t wPasLisConfig = 0; uint16_t wActLisConfig = 0; #ifdef INITIATOR_MODE #ifdef PASSIVE_MODE #ifdef NXPBUILD__PHAC_DISCLOOP_TYPEA_TAGS wPasPollConfig |= PHAC_DISCLOOP_POS_BIT_MASK_A; #endif /* NXPBUILD__PHAC_DISCLOOP_TYPEA_TAGS */ #ifdef NXPBUILD__PHAC_DISCLOOP_TYPEB_TAGS wPasPollConfig |= PHAC_DISCLOOP_POS_BIT_MASK_B; #endif /* NXPBUILD__PHAC_DISCLOOP_TYPEB_TAGS */ #ifdef NXPBUILD__PHAC_DISCLOOP_TYPEF_TAGS wPasPollConfig |= (PHAC_DISCLOOP_POS_BIT_MASK_F212 | PHAC_DISCLOOP_POS_BIT_MASK_F424); #endif /* NXPBUILD__PHAC_DISCLOOP_TYPEF_TAGS */ #ifdef NXPBUILD__PHAC_DISCLOOP_TYPEV_TAGS wPasPollConfig |= PHAC_DISCLOOP_POS_BIT_MASK_V; #endif /* NXPBUILD__PHAC_DISCLOOP_TYPEV_TAGS */ #ifdef NXPBUILD__PHAC_DISCLOOP_I18000P3M3_TAGS wPasPollConfig |= PHAC_DISCLOOP_POS_BIT_MASK_18000P3M3; #endif /* NXPBUILD__PHAC_DISCLOOP_I18000P3M3_TAGS */ #endif /* PASSIVE_MODE */ #ifdef ACTIVE_MODE #ifdef NXPBUILD__PHAC_DISCLOOP_TYPEA_P2P_ACTIVE wActPollConfig |= PHAC_DISCLOOP_ACT_POS_BIT_MASK_106; #endif /* NXPBUILD__PHAC_DISCLOOP_TYPEA_P2P_ACTIVE */ #ifdef NXPBUILD__PHAC_DISCLOOP_TYPEF212_P2P_ACTIVE wActPollConfig |= PHAC_DISCLOOP_ACT_POS_BIT_MASK_212; #endif /* NXPBUILD__PHAC_DISCLOOP_TYPEF212_P2P_ACTIVE */ #ifdef NXPBUILD__PHAC_DISCLOOP_TYPEF424_P2P_ACTIVE wActPollConfig |= PHAC_DISCLOOP_ACT_POS_BIT_MASK_424; #endif /* NXPBUILD__PHAC_DISCLOOP_TYPEF424_P2P_ACTIVE */ #endif /* ACTIVE_MODE */ #endif /* INITIATOR_MODE */ #ifdef TARGET_MODE #ifdef PASSIVE_MODE #ifdef NXPBUILD__PHAC_DISCLOOP_TYPEA_TARGET_PASSIVE wPasLisConfig |= PHAC_DISCLOOP_POS_BIT_MASK_A; #endif /* NXPBUILD__PHAC_DISCLOOP_TYPEA_TARGET_PASSIVE */ #ifdef NXPBUILD__PHAC_DISCLOOP_TYPEF212_TARGET_PASSIVE wPasLisConfig |= PHAC_DISCLOOP_POS_BIT_MASK_F212; #endif /* NXPBUILD__PHAC_DISCLOOP_TYPEF212_TARGET_PASSIVE */ #ifdef NXPBUILD__PHAC_DISCLOOP_TYPEF424_TARGET_PASSIVE wPasLisConfig |= PHAC_DISCLOOP_POS_BIT_MASK_F424; #endif /* NXPBUILD__PHAC_DISCLOOP_TYPEF424_TARGET_PASSIVE */ #endif /* PASSIVE_MODE */ #ifdef ACTIVE_MODE #ifdef NXPBUILD__PHAC_DISCLOOP_TYPEA_TARGET_ACTIVE wActLisConfig |= PHAC_DISCLOOP_POS_BIT_MASK_A; #endif /* NXPBUILD__PHAC_DISCLOOP_TYPEA_TARGET_ACTIVE */ #ifdef NXPBUILD__PHAC_DISCLOOP_TYPEF212_TARGET_ACTIVE wActLisConfig |= PHAC_DISCLOOP_POS_BIT_MASK_F212; #endif /* NXPBUILD__PHAC_DISCLOOP_TYPEF212_TARGET_ACTIVE */ #ifdef NXPBUILD__PHAC_DISCLOOP_TYPEF424_TARGET_ACTIVE wActLisConfig |= PHAC_DISCLOOP_POS_BIT_MASK_F424; #endif /* NXPBUILD__PHAC_DISCLOOP_TYPEF424_TARGET_ACTIVE */ #endif /* ACTIVE_MODE */ #endif /* TARGET_MODE */ /* Passive poll bitmap configuration. */ status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_PAS_POLL_TECH_CFG, wPasPollConfig); CHECK_STATUS(status); /* Active poll bitmap configuration. */ status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_ACT_POLL_TECH_CFG, wActPollConfig); CHECK_STATUS(status); /* Passive listen bitmap configuration. */ status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_PAS_LIS_TECH_CFG, wPasLisConfig); CHECK_STATUS(status); /* Active listen bitmap configuration. */ status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_ACT_LIS_TECH_CFG, wActLisConfig); CHECK_STATUS(status); /* Passive Bailout bitmap configuration. */ status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_BAIL_OUT, 0x00); CHECK_STATUS(status); #if defined(NXPBUILD__PHAC_DISCLOOP_TYPEA_P2P_TAGS) || defined(NXPBUILD__PHAC_DISCLOOP_TYPEA_P2P_ACTIVE) /* Set LRI value for Type-A polling to 3. LLCP mandates that LRI value to be 3. */ status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_TYPEA_P2P_LRI, 3); CHECK_STATUS(status); /* Set LRI value for Type-F polling to 3. LLCP mandates that LRI value to be 3. */ status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_TYPEF_P2P_LRI, 3); CHECK_STATUS(status); #endif /* defined(NXPBUILD__PHAC_DISCLOOP_TYPEA_P2P_TAGS) || defined(NXPBUILD__PHAC_DISCLOOP_TYPEA_P2P_ACTIVE) */ /* Reset collision pending */ status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_COLLISION_PENDING, PH_OFF); CHECK_STATUS(status); /* Set Discovery loop mode to NFC mode. */ status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_OPE_MODE, RD_LIB_MODE_NFC); CHECK_STATUS(status); return status; } /** * This function will retrieve and print tag information like UID, NFC type etc.. * \param pDataParams The discovery loop data parameters * \param wNumberOfTags Total number of tags detected * \param wTagsDetected Technology detected */ static void GetTagInfo(phacDiscLoop_Sw_DataParams_t *pDataParams, uint16_t wNumberOfTags, uint16_t wTagsDetected) { uint16_t bIndex; #if defined(NXPBUILD__PHAC_DISCLOOP_TYPEA_TAGS) || defined(NXPBUILD__PHAC_DISCLOOP_TYPEA_P2P_ACTIVE) uint8_t bTagType; #endif phStatus_t status = 0; /* Required if DETECT_ERROR is not set. DETECT_ERROR is required for debugging purpose only */ PH_UNUSED_VARIABLE(status); #if defined(NXPBUILD__PHAC_DISCLOOP_TYPEA_TAGS) || defined(NXPBUILD__PHAC_DISCLOOP_TYPEA_P2P_ACTIVE) /* Check for Type A tag */ if (PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_A)) { /* Check for T1T */ if(pDataParams->sTypeATargetInfo.bT1TFlag) { DEBUG_PRINTF("\tType A : T1T detected \n"); /* Check for NDEF and Read */ status = ReadNdefMessage(PHAL_TOP_TAG_TYPE_T1T_TAG); if (status != PH_ERR_SUCCESS) { DEBUG_ERROR_PRINT(status); } } else { DEBUG_PRINTF("\tTechnology : Type A"); /* Loop through all the detected tags (if multiple tags are * detected) */ for(bIndex = 0; bIndex < wNumberOfTags; bIndex++) { DEBUG_PRINTF ("\n\t\tCard : %d",bIndex + 1); DEBUG_PRINTF ("\n\t\tUID :"); phApp_Print_Buff( pDataParams->sTypeATargetInfo.aTypeA_I3P3[bIndex].aUid, pDataParams->sTypeATargetInfo.aTypeA_I3P3[bIndex].bUidSize); DEBUG_PRINTF ("\n\t\tSAK: 0x%x",pDataParams->sTypeATargetInfo.aTypeA_I3P3[bIndex].aSak); if ((pDataParams->sTypeATargetInfo.aTypeA_I3P3[bIndex].aSak & (uint8_t) ~0xFB) == 0) { /* Bit b3 is set to zero, [Digital] 4.8.2 */ /* Mask out all other bits except for b7 and b6 */ bTagType = (pDataParams->sTypeATargetInfo.aTypeA_I3P3[bIndex].aSak & 0x60); bTagType = bTagType >> 5; /* Switch to tag type */ switch(bTagType) { case PHAC_DISCLOOP_TYPEA_TYPE2_TAG_CONFIG_MASK: DEBUG_PRINTF ("\n\t\tType : Type 2 tag\n"); if (!DetectClassic( pDataParams->sTypeATargetInfo.aTypeA_I3P3[bIndex].aAtqa, &pDataParams->sTypeATargetInfo.aTypeA_I3P3[bIndex].aSak)) { /* Check for NDEF and Read NDEF if mifare Ultralite card is detected. */ status = ReadNdefMessage(PHAL_TOP_TAG_TYPE_T2T_TAG); DEBUG_ERROR_PRINT(status); } break; case PHAC_DISCLOOP_TYPEA_TYPE4A_TAG_CONFIG_MASK: DEBUG_PRINTF ("\n\t\tType : Type 4A tag\n"); /* Check for NDEF and Read NDEF */ status = ReadNdefMessage(PHAL_TOP_TAG_TYPE_T4T_TAG); DEBUG_ERROR_PRINT(status); break; case PHAC_DISCLOOP_TYPEA_TYPE_NFC_DEP_TAG_CONFIG_MASK: DEBUG_PRINTF ("\n\t\tType : P2P\n"); break; case PHAC_DISCLOOP_TYPEA_TYPE_NFC_DEP_TYPE4A_TAG_CONFIG_MASK: DEBUG_PRINTF ("\n\t\tType : Type NFC_DEP and 4A tag\n"); break; default: break; } } } } } #endif #ifdef NXPBUILD__PHAC_DISCLOOP_TYPEB_TAGS /* Check for Type B tag */ if (PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_B)) { DEBUG_PRINTF("\tTechnology: Type B"); /* Loop through all the Type B tags detected and print the PUPI */ for (bIndex = 0; bIndex < wNumberOfTags; bIndex++) { DEBUG_PRINTF ("\n\t\tCard : %d",bIndex + 1); DEBUG_PRINTF ("\n\t\tUID :"); /* PUPI Length is always 4 bytes */ phApp_Print_Buff( pDataParams->sTypeBTargetInfo.aTypeB_I3P3[bIndex].aPupi, 0x04); } DEBUG_PRINTF("\n"); } #endif /* NXPBUILD__PHAC_DISCLOOP_TYPEB_TAGS */ #ifdef NXPBUILD__PHAC_DISCLOOP_TYPEF_TAGS /* Check for Type F tag */ if( PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_F212) || PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_F424)) { DEBUG_PRINTF("\tTechnology: Type F"); /* Loop through all the type F tags and print the IDm */ for (bIndex = 0; bIndex < wNumberOfTags; bIndex++) { DEBUG_PRINTF ("\n\t\tCard : %d",bIndex + 1); DEBUG_PRINTF ("\n\t\tUID :"); phApp_Print_Buff( pDataParams->sTypeFTargetInfo.aTypeFTag[bIndex].aIDmPMm, PHAC_DISCLOOP_FELICA_IDM_LENGTH ); /* Check data rate */ if(pDataParams->sTypeFTargetInfo.aTypeFTag[bIndex].bBaud != PHAC_DISCLOOP_CON_BITR_212) { DEBUG_PRINTF ("\n\t\tBit Rate: 424 kbps"); } else { DEBUG_PRINTF ("\n\t\tBit Rate: 212 kbps"); } if ((pDataParams->sTypeFTargetInfo.aTypeFTag[bIndex].aIDmPMm[0] == 0x01) && (pDataParams->sTypeFTargetInfo.aTypeFTag[bIndex].aIDmPMm[1] == 0xFE)) { /* This is type F tag with P2P capabilities */ DEBUG_PRINTF ("\n\t\tType : P2P\n"); } else { /* This is Type F T3T tag */ DEBUG_PRINTF ("\n\t\tType : Type 3 tag\n"); /* Check for NDEF and read NDEF */ status = ReadNdefMessage(PHAL_TOP_TAG_TYPE_T3T_TAG); DEBUG_ERROR_PRINT(status); } } } #endif /* NXPBUILD__PHAC_DISCLOOP_TYPEF_TAGS */ #ifdef NXPBUILD__PHAC_DISCLOOP_TYPEV_TAGS if (PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_V)) { DEBUG_PRINTF("\tTechnology : Type V / ISO 15693 / T5T"); /* Loop through all the Type V tags detected and print the UIDs */ for (bIndex = 0; bIndex < wNumberOfTags; bIndex++) { DEBUG_PRINTF ("\n\t\tCard: %d",bIndex + 1); DEBUG_PRINTF ("\n\t\tUID :"); phApp_Print_Buff( pDataParams->sTypeVTargetInfo.aTypeV[bIndex].aUid, 0x08); /* Check for NDEF and Read */ status = ReadNdefMessage(PHAL_TOP_TAG_TYPE_T5T_TAG); if (status != PH_ERR_SUCCESS) { DEBUG_ERROR_PRINT(status); } } DEBUG_PRINTF("\n"); } #endif /* NXPBUILD__PHAC_DISCLOOP_TYPEV_TAGS */ #ifdef NXPBUILD__PHAC_DISCLOOP_I18000P3M3_TAGS if (PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_18000P3M3)) { DEBUG_PRINTF("\tTechnology : ISO 18000p3m3 / EPC Gen2"); /* Loop through all the 18000p3m3 tags detected and print the UII */ for (bIndex = 0; bIndex < wNumberOfTags; bIndex++) { DEBUG_PRINTF("\n\t\tCard: %d",bIndex + 1); DEBUG_PRINTF("\n\t\tUII :"); phApp_Print_Buff( pDataParams->sI18000p3m3TargetInfo.aI18000p3m3[bIndex].aUii, (pDataParams->sI18000p3m3TargetInfo.aI18000p3m3[bIndex].wUiiLength / 8)); } DEBUG_PRINTF("\n"); } #endif /* NXPBUILD__PHAC_DISCLOOP_I18000P3M3_TAGS */ } /** * Reads NDEF Message if the detected tag has a valid NDEF message */ phStatus_t ReadNdefMessage(uint8_t TopTagType) { phStatus_t status; uint8_t bTagState = 0; uint32_t dwDataLength = 0; /* Configure Top layer for specified tag type */ status = phalTop_SetConfig(palTop, PHAL_TOP_CONFIG_TAG_TYPE, TopTagType); DEBUG_ERROR_PRINT(status); /* Check for NDEF presence */ status = phalTop_CheckNdef(palTop, &bTagState); DEBUG_ERROR_PRINT(status); if((bTagState == PHAL_TOP_STATE_READONLY) || (bTagState == PHAL_TOP_STATE_READWRITE)) { /* Read NDEF message */ status = phalTop_ReadNdef(palTop, baSnepAppBuffer, &dwDataLength); DEBUG_ERROR_PRINT(status); /* Print NDEF message, if not NULL NDEF */ if(dwDataLength) { DEBUG_PRINTF("\tNDEF detected...\n"); DEBUG_PRINTF("\tNDEF length: %d\n", dwDataLength); DEBUG_PRINTF("\tNDEF message:\n"); //DumpBuffer(aData, dwDataLength); DumpBuffer(baSnepAppBuffer, 50); } else { DEBUG_PRINTF("\tNDEF content is NULL...\n"); } } else { DEBUG_PRINTF("\tNo NDEF content detected...\n"); } return status; }