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>&copy; 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 */