RFAL library for the STMicroelectronics X-NUCLEO-NFC05A1

Dependents:   mbed-os-nfc05a1

Revision:
0:75fc82583a41
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rfal_nfcf.cpp	Thu Nov 14 14:34:50 2019 +0000
@@ -0,0 +1,344 @@
+
+/******************************************************************************
+  * @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 */