Fork of the GitHub
rfal_nfcf.cpp
- Committer:
- DiegoOstuni
- Date:
- 2019-11-14
- Revision:
- 0:75fc82583a41
File content as of revision 0:75fc82583a41:
/****************************************************************************** * @attention * * <h2><center>© COPYRIGHT 2016 STMicroelectronics</center></h2> * * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty * * 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, * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/ /* * PROJECT: ST25R391x firmware * $Revision: $ * LANGUAGE: ISO C99 */ /*! \file rfal_nfcf.c * * \author Gustavo Patricio * * \brief Implementation of NFC-F Poller (FeliCa PCD) device * * The definitions and helpers methods provided by this module are * aligned with NFC-F (FeliCa - JIS X6319-4) * */ /* ****************************************************************************** * INCLUDES ****************************************************************************** */ #include <platform1.h> #include "rfal_nfcf.h" #include "utils.h" /* ****************************************************************************** * ENABLE SWITCH ****************************************************************************** */ #ifndef RFAL_FEATURE_NFCF #error " RFAL: Module configuration missing. Please enable/disable NFC-F module by setting: RFAL_FEATURE_NFCF " #endif #if RFAL_FEATURE_NFCF /* ****************************************************************************** * GLOBAL DEFINES ****************************************************************************** */ #define RFAL_NFCF_SENSF_REQ_LEN_MIN 5 /*!< SENSF_RES minimum length */ #define RFAL_NFCF_READ_WO_ENCRYPTION_MIN_LEN 15 /*!< Minimum length for a Check Command - T3T 5.4.1 */ #define RFAL_NFCF_WRITE_WO_ENCRYPTION_MIN_LEN 31 /*!< Minimum length for an Update Command - T3T 5.5.1 */ /* ****************************************************************************** * GLOBAL MACROS ****************************************************************************** */ #define rfalNfcfSlots2CardNum( s ) (s+1) /*!< Converts Time Slot Number (TSN) into num of slots */ /* ****************************************************************************** * GLOBAL TYPES ****************************************************************************** */ /*! Structure/Buffer to hold the SENSF_RES with LEN byte prepended */ typedef struct{ uint8_t LEN; /*!< NFC-F LEN byte */ rfalNfcfSensfRes SENSF_RES; /*!< SENSF_RES */ } rfalNfcfSensfResBuf; /*! Greedy collection for NFCF GRE_POLL_F Activity 1.0 Table 10 */ typedef struct{ uint8_t pollFound; /*!< Number of devices found by the Poll */ uint8_t pollCollision; /*!< Number of collisions detected */ rfalFeliCaPollRes POLL_F[RFAL_NFCF_POLL_MAXCARDS]; /*!< GRE_POLL_F Activity 1.0 Table 10 */ } rfalNfcfGreedyF; /*! NFC-F SENSF_REQ format Digital 1.1 8.6.1 */ typedef struct { uint8_t CMD; /*!< Command code: 00h */ uint8_t SC[RFAL_NFCF_SENSF_SC_LEN]; /*!< System Code */ uint8_t RC; /*!< Request Code */ uint8_t TSN; /*!< Time Slot Number */ } rfalNfcfSensfReq; /* ****************************************************************************** * LOCAL VARIABLES ****************************************************************************** */ static rfalNfcfGreedyF gRfalNfcfGreedyF; /*!< Activity's NFCF Greedy collection */ /* ****************************************************************************** * LOCAL FUNCTION PROTOTYPES ****************************************************************************** */ static void rfalNfcfComputeValidSENF( rfalNfcfListenDevice *outDevInfo, uint8_t *curDevIdx, uint8_t devLimit, bool overwrite, bool *nfcDepFound ); /* ****************************************************************************** * LOCAL VARIABLES ****************************************************************************** */ /*******************************************************************************/ static void rfalNfcfComputeValidSENF( rfalNfcfListenDevice *outDevInfo, uint8_t *curDevIdx, uint8_t devLimit, bool overwrite, bool *nfcDepFound ) { uint8_t tmpIdx; bool duplicate; rfalNfcfSensfResBuf *sensfBuf; /*******************************************************************************/ /* Go through all responses check if valid and duplicates */ /*******************************************************************************/ while( (gRfalNfcfGreedyF.pollFound > 0) && ((*curDevIdx) < devLimit) ) { duplicate = false; gRfalNfcfGreedyF.pollFound--; /* Point to received SENSF_RES */ sensfBuf = (rfalNfcfSensfResBuf*) &gRfalNfcfGreedyF.POLL_F[gRfalNfcfGreedyF.pollFound]; /* Check for devices that are already in device list */ for( tmpIdx = 0; tmpIdx < (*curDevIdx); tmpIdx++ ) { if( !ST_BYTECMP( sensfBuf->SENSF_RES.NFCID2, outDevInfo[tmpIdx].sensfRes.NFCID2, RFAL_NFCF_NFCID2_LEN ) ) { duplicate = true; break; } } /* If is a duplicate skip this (and not to overwrite)*/ if(duplicate && !overwrite) { continue; } /* Check if response length is OK */ if( (( sensfBuf->LEN - RFAL_NFCF_HEADER_LEN) < RFAL_NFCF_SENSF_RES_LEN_MIN) || ((sensfBuf->LEN - RFAL_NFCF_HEADER_LEN) > RFAL_NFCF_SENSF_RES_LEN_MAX) ) { continue; } /* Check if the response is a SENSF_RES / Polling response */ if( sensfBuf->SENSF_RES.CMD != RFAL_NFCF_CMD_POLLING_RES ) { continue; } /* Check if is an overwrite request or new device*/ if(duplicate && overwrite) { /* overwrite deviceInfo/GRE_SENSF_RES with SENSF_RES */ outDevInfo[tmpIdx].sensfResLen = (sensfBuf->LEN - RFAL_NFCF_LENGTH_LEN); ST_MEMCPY( &outDevInfo[tmpIdx].sensfRes, &sensfBuf->SENSF_RES.CMD, outDevInfo[tmpIdx].sensfResLen ); continue; } else { /* fill deviceInfo/GRE_SENSF_RES with new SENSF_RES */ outDevInfo[(*curDevIdx)].sensfResLen = (sensfBuf->LEN - RFAL_NFCF_LENGTH_LEN); ST_MEMCPY( &outDevInfo[(*curDevIdx)].sensfRes, &sensfBuf->SENSF_RES.CMD, outDevInfo[(*curDevIdx)].sensfResLen ); } /* Check if this device supports NFC-DEP and signal it (ACTIVITY 1.1 9.3.6.63) */ *nfcDepFound = rfalNfcfIsNfcDepSupported( &outDevInfo[(*curDevIdx)] ); (*curDevIdx)++; } } /* ****************************************************************************** * GLOBAL FUNCTIONS ****************************************************************************** */ /*******************************************************************************/ ReturnCode rfalNfcfPollerInitialize( rfalBitRate bitRate,SPI* mspiChannel, ST25R3911* mST25, DigitalOut* gpio_cs, InterruptIn* IRQ, DigitalOut* fieldLED_01, DigitalOut* fieldLED_02, DigitalOut* fieldLED_03, DigitalOut* fieldLED_04, DigitalOut* fieldLED_05, DigitalOut* fieldLED_06 ) { ReturnCode ret; if( (bitRate != RFAL_BR_212) && (bitRate != RFAL_BR_424) ) { return ERR_PARAM; } EXIT_ON_ERR( ret, rfalSetMode( RFAL_MODE_POLL_NFCF, bitRate, bitRate, mspiChannel, mST25, gpio_cs, IRQ, fieldLED_01, fieldLED_02, fieldLED_03, fieldLED_04, fieldLED_05, fieldLED_06 ) ); rfalSetErrorHandling( RFAL_ERRORHANDLING_NFC ); rfalSetGT( RFAL_GT_NFCF ); rfalSetFDTListen( RFAL_FDT_LISTEN_NFCF_POLLER ); rfalSetFDTPoll( RFAL_FDT_POLL_NFCF_POLLER ); return ERR_NONE; } /*******************************************************************************/ ReturnCode rfalNfcfPollerPoll( rfalFeliCaPollSlots slots, uint16_t sysCode, uint8_t reqCode, rfalFeliCaPollRes *cardList, uint8_t *devCnt, uint8_t *collisions, SPI* mspiChannel, ST25R3911* mST25, DigitalOut* gpio_cs, InterruptIn* IRQ, DigitalOut* fieldLED_01, DigitalOut* fieldLED_02, DigitalOut* fieldLED_03, DigitalOut* fieldLED_04, DigitalOut* fieldLED_05, DigitalOut* fieldLED_06 ) { return rfalFeliCaPoll( slots, sysCode, reqCode, cardList, rfalNfcfSlots2CardNum(slots), devCnt, collisions, mspiChannel, mST25, gpio_cs, IRQ, fieldLED_01, fieldLED_02, fieldLED_03, fieldLED_04, fieldLED_05, fieldLED_06 ) ; } /*******************************************************************************/ ReturnCode rfalNfcfPollerCheckPresence( SPI* mspiChannel, ST25R3911* mST25, DigitalOut* gpio_cs, InterruptIn* IRQ, DigitalOut* fieldLED_01, DigitalOut* fieldLED_02, DigitalOut* fieldLED_03, DigitalOut* fieldLED_04, DigitalOut* fieldLED_05, DigitalOut* fieldLED_06 ) { gRfalNfcfGreedyF.pollFound = 0; gRfalNfcfGreedyF.pollCollision = 0; /* ACTIVITY 1.0 & 1.1 - 9.2.3.17 SENSF_REQ must be with number of slots equal to 4 * SC must be 0xFFFF * RC must be 0x00 (No system code info required) */ return rfalFeliCaPoll( RFAL_FELICA_4_SLOTS, RFAL_NFCF_SYSTEMCODE, RFAL_FELICA_POLL_RC_NO_REQUEST, gRfalNfcfGreedyF.POLL_F, rfalNfcfSlots2CardNum(RFAL_FELICA_4_SLOTS), &gRfalNfcfGreedyF.pollFound, &gRfalNfcfGreedyF.pollCollision, mspiChannel, mST25, gpio_cs, IRQ, fieldLED_01, fieldLED_02, fieldLED_03, fieldLED_04, fieldLED_05, fieldLED_06 ) ; } /*******************************************************************************/ ReturnCode rfalNfcfPollerCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcfListenDevice *nfcfDevList, uint8_t *devCnt, SPI* mspiChannel, ST25R3911* mST25, DigitalOut* gpio_cs, InterruptIn* IRQ, DigitalOut* fieldLED_01, DigitalOut* fieldLED_02, DigitalOut* fieldLED_03, DigitalOut* fieldLED_04, DigitalOut* fieldLED_05, DigitalOut* fieldLED_06 ) { ReturnCode ret; bool nfcDepFound; if( nfcfDevList == NULL || devCnt == NULL ) { return ERR_PARAM; } *devCnt = 0; nfcDepFound = false; /*******************************************************************************************/ /* ACTIVITY 1.0 - 9.3.6.3 Copy valid SENSF_RES in GRE_POLL_F into GRE_SENSF_RES */ /* ACTIVITY 1.0 - 9.3.6.6 The NFC Forum Device MUST remove all entries from GRE_SENSF_RES[]*/ /* ACTIVITY 1.1 - 9.3.63.59 Populate GRE_SENSF_RES with data from GRE_POLL_F */ /* */ /* CON_DEVICES_LIMIT = 0 Just check if devices from Tech Detection exceeds -> always true */ /* Allow the number of slots open on Technology Detection */ /*******************************************************************************************/ rfalNfcfComputeValidSENF( nfcfDevList, devCnt, (devLimit == 0 ? rfalNfcfSlots2CardNum( RFAL_FELICA_4_SLOTS ) : devLimit), false, &nfcDepFound ); /*******************************************************************************/ /* ACTIVITY 1.0 - 9.3.6.4 */ /* ACTIVITY 1.1 - 9.3.63.60 Check if devices found are lower than the limit */ /* and send a SENSF_REQ if so */ /*******************************************************************************/ if( *devCnt < devLimit ) { /* ACTIVITY 1.0 - 9.3.6.5 Copy valid SENSF_RES and then to remove it * ACTIVITY 1.1 - 9.3.6.65 Copy and filter duplicates * For now, due to some devices keep generating different nfcid2, we use 1.0 * Phones detected: Samsung Galaxy Nexus,Samsung Galaxy S3,Samsung Nexus S */ *devCnt = 0; ret = rfalNfcfPollerPoll( RFAL_FELICA_16_SLOTS, RFAL_NFCF_SYSTEMCODE, RFAL_FELICA_POLL_RC_NO_REQUEST, gRfalNfcfGreedyF.POLL_F, &gRfalNfcfGreedyF.pollFound, &gRfalNfcfGreedyF.pollCollision, mspiChannel, mST25, gpio_cs, IRQ, fieldLED_01, fieldLED_02, fieldLED_03, fieldLED_04, fieldLED_05, fieldLED_06 ) ; if( ret == ERR_NONE ) { rfalNfcfComputeValidSENF( nfcfDevList, devCnt, devLimit, false, &nfcDepFound ); } /*******************************************************************************/ /* ACTIVITY 1.1 - 9.3.6.63 Check if any device supports NFC DEP */ /*******************************************************************************/ if( nfcDepFound && (compMode == RFAL_COMPLIANCE_MODE_NFC) ) { ret = rfalNfcfPollerPoll( RFAL_FELICA_16_SLOTS, RFAL_NFCF_SYSTEMCODE, RFAL_FELICA_POLL_RC_SYSTEM_CODE, gRfalNfcfGreedyF.POLL_F, &gRfalNfcfGreedyF.pollFound, &gRfalNfcfGreedyF.pollCollision, mspiChannel, mST25, gpio_cs, IRQ, fieldLED_01, fieldLED_02, fieldLED_03, fieldLED_04, fieldLED_05, fieldLED_06 ) ; if( ret == ERR_NONE ) { rfalNfcfComputeValidSENF( nfcfDevList, devCnt, devLimit, true, &nfcDepFound ); } } } return ERR_NONE; } /*******************************************************************************/ bool rfalNfcfListenerIsT3TReq( uint8_t* buf, uint16_t bufLen, uint8_t* nfcid2 ) { /* Check cmd byte */ switch( *buf ) { case RFAL_NFCF_CMD_READ_WITHOUT_ENCRYPTION: if( bufLen < RFAL_NFCF_READ_WO_ENCRYPTION_MIN_LEN ) { return false; } break; case RFAL_NFCF_CMD_WRITE_WITHOUT_ENCRYPTION: if( bufLen < RFAL_NFCF_WRITE_WO_ENCRYPTION_MIN_LEN ) { return false; } break; default: return false; } /* Output NFID2 if requested */ if( nfcid2 != NULL ) { ST_MEMCPY( nfcid2, (uint8_t*)(buf + RFAL_NFCF_CMD_LEN), RFAL_NFCF_NFCID2_LEN ); } return true; } #endif /* RFAL_FEATURE_NFCF */