mirror of
https://gitlab.com/fabinfra/fabhardware/FabReader2.git
synced 2025-03-13 07:01:53 +01:00
673 lines
22 KiB
C
673 lines
22 KiB
C
|
/**
|
||
|
******************************************************************************
|
||
|
* @file demo_ce.c
|
||
|
* @author MMY Application Team
|
||
|
* @brief Body function to manage card emul mode
|
||
|
******************************************************************************
|
||
|
** This notice applies to any and all portions of this file
|
||
|
* that are not between comment pairs USER CODE BEGIN and
|
||
|
* USER CODE END. Other portions of this file, whether
|
||
|
* inserted by the user or by software development tools
|
||
|
* are owned by their respective copyright owners.
|
||
|
*
|
||
|
* COPYRIGHT(c) 2018 STMicroelectronics
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||
|
* are permitted provided that the following conditions are met:
|
||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||
|
* this list of conditions and the following disclaimer.
|
||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||
|
* this list of conditions and the following disclaimer in the documentation
|
||
|
* and/or other materials provided with the distribution.
|
||
|
* 3. Neither the name of STMicroelectronics nor the names of its contributors
|
||
|
* may be used to endorse or promote products derived from this software
|
||
|
* without specific prior written permission.
|
||
|
*
|
||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
*
|
||
|
******************************************************************************
|
||
|
*/
|
||
|
|
||
|
/* Includes ------------------------------------------------------------------*/
|
||
|
#include "demo_ce.h"
|
||
|
#include "utils.h"
|
||
|
#include "st_errno.h"
|
||
|
#include "rfal_rf.h"
|
||
|
#include "rfal_nfca.h"
|
||
|
#include "rfal_nfcf.h"
|
||
|
|
||
|
/** @addtogroup X-CUBE-NFC6_Applications
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
/** @addtogroup CardEmulation
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
/** @addtogroup CE_CardEmul
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
/* Private typedef -----------------------------------------------------------*/
|
||
|
/** @defgroup CE_CardEmul_Private_Typedef
|
||
|
* @{
|
||
|
*/
|
||
|
enum States
|
||
|
{
|
||
|
STATE_IDLE = 0, /*!< Emulated Tag state idle */
|
||
|
STATE_APP_SELECTED = 1, /*!< Emulated Tag state application selected */
|
||
|
STATE_CC_SELECTED = 2, /*!< Emulated Tag state CCFile selected */
|
||
|
STATE_FID_SELECTED = 3, /*!< Emulated Tag state FileID selected */
|
||
|
};
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
/* Private define ------------------------------------------------------------*/
|
||
|
/** @defgroup CE_CardEmul_Private_Define
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
#define NDEF_SIZE 0xFFFE /*!< Max NDEF size emulated */
|
||
|
#define T4T_CLA_00 0x00 /*!< CLA value for type 4 command */
|
||
|
#define T4T_INS_SELECT 0xA4 /*!< INS value for select command */
|
||
|
#define T4T_INS_READ 0xB0 /*!< INS value for reabbinary command */
|
||
|
#define T4T_INS_UPDATE 0xD6 /*!< INS value for update command */
|
||
|
#define FID_CC 0xE103 /*!< File ID number for CCFile */
|
||
|
#define FID_NDEF 0xE104 /*!< File ID number for NDEF file */
|
||
|
#define T3T_BLOCK_SIZE 0x10 /*!< Block size in Type 3 Tag */
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
/* Private macro -------------------------------------------------------------*/
|
||
|
/* Private variables ---------------------------------------------------------*/
|
||
|
/** @defgroup CE_CardEmul_Private_Variables
|
||
|
* @{
|
||
|
*/
|
||
|
static uint8_t gNfcfNfcid[RFAL_NFCF_NFCID2_LEN];
|
||
|
static uint8_t ndefFile[2048]; /*!< Buffer to store NDEF File */
|
||
|
static int8_t nState = STATE_IDLE; /*!< Type 4 tag emulation status */
|
||
|
static int32_t nSelectedIdx = -1; /*!< current file selected */
|
||
|
static int32_t nFiles = 2; /*!< Number of file emulated */
|
||
|
|
||
|
|
||
|
/**
|
||
|
* CCLEN : Indicates the size of this CC File <BR>
|
||
|
* T4T_VNo : Indicates the Mapping Version <BR>
|
||
|
* MLe high : Max R-APDU size <BR>
|
||
|
* MLc high : Max C-APDU size <BR>
|
||
|
* NDEF FCI T: Indicates the NDEF-File_Ctrl_TLV <BR>
|
||
|
* NDEF FCI L: The length of the V-field <BR>
|
||
|
* NDEF FCI V1: NDEF File Identifier <BR>
|
||
|
* NDEF FCI V2: NDEF File size <BR>
|
||
|
* NDEF FCI V3: NDEF Read AC <BR>
|
||
|
* NDEF FCI V4: NDEF Write AC <BR>
|
||
|
*/
|
||
|
static uint8_t ccfile[] = {
|
||
|
0x00, 0x0F, /* CCLEN */
|
||
|
0x20, /* T4T_VNo */
|
||
|
0x00, 0x7F, /* MLe */
|
||
|
0x00, 0x7F, /* MLc */
|
||
|
0x04, /* T */
|
||
|
0x06, /* L */
|
||
|
(FID_NDEF & 0xFF00) >> 8, (FID_NDEF & 0x00FF), /* V1 */
|
||
|
(NDEF_SIZE & 0xFF00) >> 8, (NDEF_SIZE & 0x00FF), /* V2 */
|
||
|
0x00, /* V3 */
|
||
|
0x00 /* V4 */
|
||
|
};
|
||
|
|
||
|
static uint32_t pdwFileSize[] = {sizeof(ccfile), NDEF_SIZE}; /*!< Current emulated files size */
|
||
|
|
||
|
/**
|
||
|
* NDEF length <BR>
|
||
|
* NDEF Header: MB,ME,SR,Well known Type <BR>
|
||
|
* NDEF type length <BR>
|
||
|
* NDEF payload length <BR>
|
||
|
* NDEF Type : URI <BR>
|
||
|
* NDEF URI abreviation field : http://www. <BR>
|
||
|
* NDEF URI string : st.com/st25r <BR>
|
||
|
* NDEF URI string : st.com/st25-demo <BR>
|
||
|
*/
|
||
|
static const uint8_t ndef_uri[] = { 0x00, 0x15, /* NDEF length */
|
||
|
0xD1, /* NDEF Header */
|
||
|
0x01, /* NDEF type length */
|
||
|
0x11, /* NDEF payload length */
|
||
|
0x55, /* NDEF Type */
|
||
|
0x01, /* NDEF URI abreviation field */
|
||
|
0x73, 0x74, 0x2E, 0x63, 0x6F, /* NDEF URI string */
|
||
|
0x6D, 0x2F, 0x73, 0x74, 0x32,
|
||
|
0x35, 0x2D, 0x64, 0x65, 0x6D, 0x6F };
|
||
|
|
||
|
/**
|
||
|
* Ver : Indicates the NDEF mapping versiom <BR>
|
||
|
* Nbr : Indicates the number of blocks that can be read <BR>
|
||
|
* Nbw : Indicates the number of blocks that can be written <BR>
|
||
|
* NmaxB : Indicates the maximum number of blocks available for NDEF data <BR>
|
||
|
* WriteFlag : Indicates whether a previous NDEF write procedure has finished or not <BR>
|
||
|
* RWFlag : Indicates data can be updated or not <BR>
|
||
|
* Ln : Is the size of the actual stored NDEF data in bytes <BR>
|
||
|
* Checksum : allows the Reader/Writer to check whether the Attribute Data are correct <BR>
|
||
|
*/
|
||
|
static uint8_t InformationBlock[] = { 0x10, /* Ver */
|
||
|
0x0F, /* Nbr */
|
||
|
0x0D, /* Nbw */
|
||
|
0x00, 0x0F, /* NmaxB */
|
||
|
0x00, 0x00, 0x00, 0x00, /* RFU */
|
||
|
0x00, /* WriteFlag */
|
||
|
0x01, /* RWFlag */
|
||
|
0x00, 0x00, 0x15, /* Ln */
|
||
|
0x00, 0x51 /* Checksum */
|
||
|
};
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
/* Private function prototypes -----------------------------------------------*/
|
||
|
|
||
|
/* Private functions ---------------------------------------------------------*/
|
||
|
/** @defgroup CE_CardEmul_Private_Functions
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
*****************************************************************************
|
||
|
* @brief Compare 2 commands supplied in parameters
|
||
|
*
|
||
|
* @param[in] cmd : pointer to the received command.
|
||
|
* @param[in] find : pointer to the avalaible command.
|
||
|
* @param[in] len : length of the available command.
|
||
|
*
|
||
|
* @retval True : Same command.
|
||
|
* @retval False : Different command.
|
||
|
*****************************************************************************
|
||
|
*/
|
||
|
static bool cmdCompare(uint8_t *cmd, uint8_t *find, uint16_t len)
|
||
|
{
|
||
|
for(int i = 0; i < 20; i++)
|
||
|
{
|
||
|
if(!memcmp(&cmd[i],find, len))
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*****************************************************************************
|
||
|
* @brief Manage the T4T Select answer to the reader
|
||
|
*
|
||
|
* @param[in] cmdData : pointer to the received command.
|
||
|
* @param[out] rspData : pointer to the answer to send.
|
||
|
*
|
||
|
* @return Answer size.
|
||
|
*****************************************************************************
|
||
|
*/
|
||
|
static uint16_t demoCeT4TSelect(uint8_t *cmdData, uint8_t *rspData)
|
||
|
{
|
||
|
bool success = false;
|
||
|
/*
|
||
|
* Cmd: CLA(1) | INS(1) | P1(1) | P2(1) | Lc(1) | Data(n) | [Le(1)]
|
||
|
* Rsp: [FCI(n)] | SW12
|
||
|
*
|
||
|
* Select App by Name NDEF: 00 A4 04 00 07 D2 76 00 00 85 01 01 00
|
||
|
* Select App by Name NDEF 4 ST: 00 A4 04 00 07 A0 00 00 00 03 00 00 00
|
||
|
* Select CC FID: 00 A4 00 0C 02 xx xx
|
||
|
* Select NDEF FID: 00 A4 00 0C 02 xx xx
|
||
|
*/
|
||
|
|
||
|
uint8_t aid[] = {0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01};
|
||
|
uint8_t fidCC[] = {FID_CC >> 8 , FID_CC & 0xFF};
|
||
|
uint8_t fidNDEF[] = {FID_NDEF >> 8, FID_NDEF & 0xFF};
|
||
|
uint8_t selectFileId[] = {0xA4, 0x00, 0x0C, 0x02, 0x00, 0x01 };
|
||
|
|
||
|
if(cmdCompare( cmdData, aid, sizeof(aid)))
|
||
|
{ /* Select Appli */
|
||
|
nState = STATE_APP_SELECTED;
|
||
|
success = true;
|
||
|
}
|
||
|
else if((nState >= STATE_APP_SELECTED) && cmdCompare(cmdData, fidCC, sizeof(fidCC)))
|
||
|
{ /* Select CC */
|
||
|
nState = STATE_CC_SELECTED;
|
||
|
nSelectedIdx = 0;
|
||
|
success = true;
|
||
|
}
|
||
|
else if((nState >= STATE_APP_SELECTED) && (cmdCompare(cmdData,fidNDEF,sizeof(fidNDEF)) || cmdCompare(cmdData,selectFileId,sizeof(selectFileId))))
|
||
|
{ /* Select NDEF */
|
||
|
nState = STATE_FID_SELECTED;
|
||
|
nSelectedIdx = 1;
|
||
|
success = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
nState = STATE_IDLE;
|
||
|
}
|
||
|
|
||
|
rspData[0] = (success ? (char)0x90 : 0x6A);
|
||
|
rspData[1] = (success ? (char)0x00 : 0x82);
|
||
|
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*****************************************************************************
|
||
|
* @brief Manage the T4T Read answer to the reader
|
||
|
*
|
||
|
* @param[in] cmdData : pointer to the received command.
|
||
|
* @param[out] rspData : pointer to the answer to send.
|
||
|
*
|
||
|
* @return Answer size.
|
||
|
*****************************************************************************
|
||
|
*/
|
||
|
static uint16_t demoCeT4TRead(uint8_t *cmdData, uint8_t *rspData)
|
||
|
{
|
||
|
/*
|
||
|
* Cmd: CLA(1) | INS(1) | P1(1).. offset inside file high | P2(1).. offset inside file high | Le(1).. nBytes to read
|
||
|
* Rsp: BytesRead | SW12
|
||
|
*/
|
||
|
unsigned short offset = (cmdData[2] << 8) | cmdData[3];
|
||
|
unsigned short toRead = cmdData[4];
|
||
|
uint8_t * ppbMemory;
|
||
|
|
||
|
/* Any file selected */
|
||
|
if(nSelectedIdx < 0 || nSelectedIdx >= nFiles)
|
||
|
{
|
||
|
rspData[0] = ((char)0x6A);
|
||
|
rspData[1] = ((char)0x82);
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
/* offset + length exceed file size */
|
||
|
if((unsigned long)(offset + toRead) > pdwFileSize[nSelectedIdx])
|
||
|
{
|
||
|
toRead = pdwFileSize[nSelectedIdx] - offset;
|
||
|
}
|
||
|
|
||
|
ppbMemory = (nSelectedIdx == 0 ? ccfile : ndefFile);
|
||
|
/* read data */
|
||
|
memcpy(rspData, &ppbMemory[offset], toRead);
|
||
|
|
||
|
rspData[toRead] = ((char)0x90);
|
||
|
rspData[toRead+1] = ((char)0x00);
|
||
|
return toRead + 2;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*****************************************************************************
|
||
|
* @brief Manage the T4T Update answer to the reader
|
||
|
*
|
||
|
* @param[in] cmdData : pointer to the received command.
|
||
|
* @param[in] rspData : pointer to the answer to send.
|
||
|
*
|
||
|
* @return Answer size.
|
||
|
*****************************************************************************
|
||
|
*/
|
||
|
static uint16_t demoCeT4TUpdate(uint8_t *cmdData, uint8_t *rspData)
|
||
|
{
|
||
|
uint32_t offset = (cmdData[2] << 8) | cmdData[3];
|
||
|
uint32_t length = cmdData[4];
|
||
|
|
||
|
if(nSelectedIdx != 1)
|
||
|
{
|
||
|
rspData[0] = ((char)0x6A);
|
||
|
rspData[1] = ((char)0x82);
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
if((unsigned long)(offset + length) > pdwFileSize[nSelectedIdx])
|
||
|
{
|
||
|
rspData[0] = ((char)0x62);
|
||
|
rspData[1] = ((char)0x82);
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
memcpy((ndefFile + offset), &cmdData[5], length);
|
||
|
|
||
|
rspData[0] = ((char)0x90);
|
||
|
rspData[1] = ((char)0x00);
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*****************************************************************************
|
||
|
* @brief Manage the T4T Read answer to the reader
|
||
|
*
|
||
|
* @param[in] cmdData : pointer to the received command.
|
||
|
* @param[out] rspData : pointer to the answer to send.
|
||
|
*
|
||
|
* @return Answer size.
|
||
|
*****************************************************************************
|
||
|
*/
|
||
|
static uint16_t demoCeT3TCheck(uint8_t *cmdData, uint8_t *rspData)
|
||
|
{
|
||
|
/*
|
||
|
* Cmd: cmd | NFCID2 | NoS | Service code list | NoB | Block list
|
||
|
* Rsp: rsp | NFCID2 | Status Flag 1 | Status Flag 2 | NoB | Block Data
|
||
|
*/
|
||
|
uint8_t *block;
|
||
|
uint16_t blocknb[256];
|
||
|
uint32_t idx = 0;
|
||
|
uint32_t cnt = 0;
|
||
|
uint32_t nbmax = 0;
|
||
|
|
||
|
/* Command response */
|
||
|
rspData[idx++] = RFAL_NFCF_CMD_READ_WITHOUT_ENCRYPTION + 1;
|
||
|
|
||
|
/* NFCID 2 bytes */
|
||
|
if( ST_BYTECMP( gNfcfNfcid, &cmdData[ RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_CMD_LEN ], RFAL_NFCF_NFCID2_LEN ) == 0 )
|
||
|
{
|
||
|
ST_MEMCPY( &rspData[idx], &gNfcfNfcid, RFAL_NFCF_NFCID2_LEN );
|
||
|
idx += RFAL_NFCF_NFCID2_LEN;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* If NFCID2 in command is different, no answer */
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* Check for command errors */
|
||
|
if( (cmdData[10] != 1) || ((cmdData[11] != 0x09) && (cmdData[11] != 0x0B))
|
||
|
|| (cmdData[13] == 0) || (cmdData[13] > InformationBlock[1]) )
|
||
|
{
|
||
|
rspData[idx++] = 0xFF;
|
||
|
rspData[idx++] = 0xFF;
|
||
|
return idx;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
rspData[idx++] = 0x00;
|
||
|
rspData[idx++] = 0x00;
|
||
|
}
|
||
|
|
||
|
/* Nob */
|
||
|
rspData[idx++] = cmdData[13];
|
||
|
|
||
|
/* Retrieving block to read */
|
||
|
block = &cmdData[14];
|
||
|
for( cnt = 0; cnt < cmdData[13]; cnt++ )
|
||
|
{
|
||
|
/* Check block list element size */
|
||
|
if( *block & 0x80 )
|
||
|
{
|
||
|
/* 2-byte Block List element */
|
||
|
blocknb[cnt] = *(block + 1);
|
||
|
block += 2;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* 3-byte Block List element */
|
||
|
blocknb[cnt] = *(block + 1);
|
||
|
blocknb[cnt] <<= 8;
|
||
|
blocknb[cnt] |= *(block + 2);
|
||
|
block += 3;
|
||
|
}
|
||
|
|
||
|
/* Return error if Blocknb > NmaxB */
|
||
|
nbmax = InformationBlock[3];
|
||
|
nbmax = (nbmax << 8) | InformationBlock[4];
|
||
|
if( blocknb[cnt] > nbmax )
|
||
|
{
|
||
|
rspData[idx - 3] = 0xFF;
|
||
|
rspData[idx - 2] = 0x70;
|
||
|
return (idx - 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for( cnt = 0; cnt < cmdData[13]; cnt++ )
|
||
|
{
|
||
|
if( blocknb[cnt] == 0x0000 )
|
||
|
{
|
||
|
/* Read information block */
|
||
|
ST_MEMCPY( &rspData[idx], InformationBlock, sizeof(InformationBlock));
|
||
|
idx += sizeof(InformationBlock);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* Read ndef block */
|
||
|
ST_MEMCPY( &rspData[idx], &ndefFile[2 + ((blocknb[cnt] - 1) * T3T_BLOCK_SIZE) ], T3T_BLOCK_SIZE);
|
||
|
idx += T3T_BLOCK_SIZE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return idx;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*****************************************************************************
|
||
|
* @brief Manage the T3T Update answer to the reader
|
||
|
*
|
||
|
* @param[in] cmdData : pointer to the received command.
|
||
|
* @param[in] rspData : pointer to the answer to send.
|
||
|
*
|
||
|
* @return Answer size.
|
||
|
*****************************************************************************
|
||
|
*/
|
||
|
static uint16_t demoCeT3TUpdate(uint8_t *cmdData, uint8_t *rspData)
|
||
|
{
|
||
|
/*
|
||
|
* Cmd: cmd | NFCID2 | NoS | Service code list | NoB | Block list | Block Data
|
||
|
* Rsp: rsp | NFCID2 | Status Flag 1 | Status Flag 2
|
||
|
*/
|
||
|
uint8_t *block;
|
||
|
uint16_t blocknb[256];
|
||
|
uint32_t idx = 0;
|
||
|
uint32_t cnt = 0;
|
||
|
uint32_t nbmax = 0;
|
||
|
|
||
|
/* Command response */
|
||
|
rspData[idx++] = RFAL_NFCF_CMD_WRITE_WITHOUT_ENCRYPTION + 1;
|
||
|
|
||
|
/* NFCID 2 bytes */
|
||
|
if( ST_BYTECMP( gNfcfNfcid, &cmdData[ RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_CMD_LEN ], RFAL_NFCF_NFCID2_LEN ) == 0 )
|
||
|
{
|
||
|
ST_MEMCPY( &rspData[idx], gNfcfNfcid, RFAL_NFCF_NFCID2_LEN );
|
||
|
idx += RFAL_NFCF_NFCID2_LEN;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* If NFCID2 in command is different, no answer */
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* Check for command errors */
|
||
|
if( (cmdData[10] != 1) || (cmdData[11] != 0x09)
|
||
|
|| (cmdData[13] == 0) || (cmdData[13] > InformationBlock[2]) )
|
||
|
{
|
||
|
rspData[idx++] = 0xFF;
|
||
|
rspData[idx++] = 0xFF;
|
||
|
return idx;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
rspData[idx++] = 0x00;
|
||
|
rspData[idx++] = 0x00;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Retrieving block to read */
|
||
|
block = &cmdData[14];
|
||
|
for( cnt = 0; cnt < cmdData[13]; cnt++ )
|
||
|
{
|
||
|
/* Check block list element size */
|
||
|
if( *block & 0x80 )
|
||
|
{
|
||
|
/* 2-byte Block List element */
|
||
|
blocknb[cnt] = *(block + 1);
|
||
|
block += 2;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* 3-byte Block List element */
|
||
|
blocknb[cnt] = *(block + 1);
|
||
|
blocknb[cnt] <<= 8;
|
||
|
blocknb[cnt] |= *(block + 2);
|
||
|
block += 3;
|
||
|
}
|
||
|
/* Return error if Blocknb > NmaxB */
|
||
|
nbmax = InformationBlock[3];
|
||
|
nbmax = (nbmax << 8) | InformationBlock[4];
|
||
|
if( blocknb[cnt] > nbmax )
|
||
|
{
|
||
|
rspData[idx - 2] = 0xFF;
|
||
|
rspData[idx - 1] = 0x70;
|
||
|
return idx;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for( cnt = 0; cnt < cmdData[13]; cnt++ )
|
||
|
{
|
||
|
if( blocknb[cnt] == 0x0000 )
|
||
|
{
|
||
|
/* Write information block */
|
||
|
ST_MEMCPY( InformationBlock, block, T3T_BLOCK_SIZE);
|
||
|
block += T3T_BLOCK_SIZE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* Read ndef block */
|
||
|
ST_MEMCPY( &ndefFile[2 + ((blocknb[cnt] - 1) * T3T_BLOCK_SIZE) ], block, T3T_BLOCK_SIZE);
|
||
|
block += T3T_BLOCK_SIZE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Status flag answer */
|
||
|
rspData[idx++] = 0x00;
|
||
|
rspData[idx++] = 0x00;
|
||
|
|
||
|
return idx;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
*****************************************************************************
|
||
|
* @brief Demo CE Initialize
|
||
|
*
|
||
|
* Initializes the demo CE
|
||
|
*
|
||
|
* @param[in] nfcfNfcid : The NFCID to be used in T3T CE.
|
||
|
*
|
||
|
* @return None
|
||
|
*****************************************************************************
|
||
|
*/
|
||
|
void demoCeInit( uint8_t* nfcfNfcid )
|
||
|
{
|
||
|
ST_MEMCPY(gNfcfNfcid, nfcfNfcid, RFAL_NFCF_NFCID2_LEN );
|
||
|
ST_MEMCPY(ndefFile, (uint8_t *)ndef_uri, sizeof(ndef_uri) );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*****************************************************************************
|
||
|
* @brief Demo CE T3T
|
||
|
*
|
||
|
* Parses the received command and computes the response to be sent back to
|
||
|
* the Reader
|
||
|
*
|
||
|
* @param[in] rxData : pointer to the received command.
|
||
|
* @param[in] rxDataLen : length of the received command.
|
||
|
* @param[in] txBuf : pointer to where the response will be placed.
|
||
|
* @param[in] txBufLen : size of txBuf.
|
||
|
*
|
||
|
* @return Response size.
|
||
|
*****************************************************************************
|
||
|
*/
|
||
|
uint16_t demoCeT4T(uint8_t *rxData, uint16_t rxDataLen, uint8_t *txBuf, uint16_t txBufLen )
|
||
|
{
|
||
|
if( (rxData == NULL) || (rxDataLen < 4) || (txBuf == NULL) || (txBufLen < 2) )
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if(rxData[0] == T4T_CLA_00)
|
||
|
{
|
||
|
switch(rxData[1])
|
||
|
{
|
||
|
case T4T_INS_SELECT:
|
||
|
return demoCeT4TSelect(rxData, txBuf);
|
||
|
|
||
|
case T4T_INS_READ:
|
||
|
return demoCeT4TRead(rxData, txBuf);
|
||
|
|
||
|
case T4T_INS_UPDATE:
|
||
|
return demoCeT4TUpdate(rxData, txBuf);
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Function not supported ... */
|
||
|
txBuf[0] = ((char)0x68);
|
||
|
txBuf[1] = ((char)0x00);
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*****************************************************************************
|
||
|
* @brief Demo CE T3T
|
||
|
*
|
||
|
* Parses the received command and computes the response to be sent back to
|
||
|
* the Reader
|
||
|
*
|
||
|
* @param[in] rxData : pointer to the received command.
|
||
|
* @param[in] rxDataLen : length of the received command.
|
||
|
* @param[in] txBuf : pointer to where the response will be placed.
|
||
|
* @param[in] txBufLen : size of txBuf.
|
||
|
*
|
||
|
* @return Response size.
|
||
|
*****************************************************************************
|
||
|
*/
|
||
|
uint16_t demoCeT3T(uint8_t *rxData, uint16_t rxDataLen, uint8_t *txBuf, uint16_t txBufLen )
|
||
|
{
|
||
|
if( (rxData == NULL) || (rxDataLen < 4) || (txBuf == NULL) || (txBufLen < 2) )
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
switch(rxData[1])
|
||
|
{
|
||
|
case RFAL_NFCF_CMD_READ_WITHOUT_ENCRYPTION:
|
||
|
return demoCeT3TCheck(rxData, txBuf);
|
||
|
|
||
|
case RFAL_NFCF_CMD_WRITE_WITHOUT_ENCRYPTION:
|
||
|
return demoCeT3TUpdate(rxData, txBuf);
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/* Function not supported ... */
|
||
|
txBuf[0] = ((char)0xFF);
|
||
|
txBuf[1] = ((char)0xFF);
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|