1618 lines
59 KiB
Plaintext
1618 lines
59 KiB
Plaintext
/*----------------------------------------------------------------------------*/
|
|
/* Copyright 2016-2022 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
|
|
* Card Emulation component for Type 4A Tag.
|
|
* $Author$
|
|
* $Revision$ (v07.10.00)
|
|
* $Date$
|
|
*/
|
|
|
|
#include <ph_RefDefs.h>
|
|
#include <ph_Status.h>
|
|
#include <phpalI14443p4mC.h>
|
|
#include <phOsal.h>
|
|
|
|
#ifdef NXPBUILD__PHCE_T4T_SW
|
|
#include "phceT4T_Sw.h"
|
|
#include "phceT4T_Sw_Int.h"
|
|
|
|
phStatus_t phceT4T_Sw_Int_SetCcFile(
|
|
phceT4T_Sw_DataParams_t *pDataParams,
|
|
uint8_t *pCcFile,
|
|
uint16_t wCcFileId,
|
|
uint16_t wCcFileSize,
|
|
uint16_t wCcContentLen
|
|
)
|
|
{
|
|
#ifdef NXPBUILD__PHCE_T4T_PROPRIETARY
|
|
uint16_t PH_MEMLOC_COUNT wIndex;
|
|
#endif /* NXPBUILD__PHCE_T4T_PROPRIETARY */
|
|
|
|
/* Check current state */
|
|
if(pDataParams->bTagState != PHCE_T4T_STATE_NONE)
|
|
{
|
|
return (PH_ERR_USE_CONDITION | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Check for CC file size */
|
|
if((wCcFileSize < 15U) || (wCcFileSize == 0xFFFFU))
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Content length shall not be more than file size */
|
|
if(wCcFileSize < wCcContentLen)
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Validate file ID */
|
|
if(wCcFileId != PHCE_T4T_CC_FILE_ID)
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Validate content length */
|
|
if((wCcContentLen > 0U) && (wCcContentLen < 15U))
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Validate T4T version number */
|
|
if((pDataParams->bVno != 0x20) && (pDataParams->bVno != 0x30))
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Initialize CC file with default values, if content length is '0' */
|
|
if(wCcContentLen == 0U)
|
|
{
|
|
if(pDataParams->bVno == 0x30)
|
|
{
|
|
/* CC Length */
|
|
pCcFile[0] = 0x00;
|
|
pCcFile[1] = 0x11;
|
|
|
|
/* Mapping Version */
|
|
pCcFile[2] = 0x30;
|
|
|
|
/* MLe */
|
|
pCcFile[3] = 0x00;
|
|
pCcFile[4] = 0xFF;
|
|
|
|
/* MLc */
|
|
pCcFile[5] = 0x00;
|
|
pCcFile[6] = 0xFF;
|
|
|
|
/* Tag (T) of Default Extended NDEF TLV */
|
|
pCcFile[7] = 0x06;
|
|
|
|
/* Length (L) of Default Extended NDEF TLV */
|
|
pCcFile[8] = 0x08;
|
|
|
|
/* NDEF File ID */
|
|
pCcFile[9] = 0xE1;
|
|
pCcFile[10] = 0x04;
|
|
|
|
/* NDEF File Size */
|
|
pCcFile[11] = 0x00;
|
|
pCcFile[12] = 0x00;
|
|
pCcFile[13] = 0x00;
|
|
pCcFile[14] = 0x00;
|
|
|
|
/* Read access */
|
|
pCcFile[15] = 0x00;
|
|
|
|
/* Write access */
|
|
pCcFile[16] = 0x00;
|
|
|
|
/* Update content length */
|
|
wCcContentLen = 17;
|
|
}
|
|
else
|
|
{
|
|
/* CC Length */
|
|
pCcFile[0] = 0x00;
|
|
pCcFile[1] = 0x0F;
|
|
|
|
/* Mapping Version */
|
|
pCcFile[2] = 0x20;
|
|
|
|
/* MLe */
|
|
pCcFile[3] = 0x00;
|
|
pCcFile[4] = 0xFF;
|
|
|
|
/* MLc */
|
|
pCcFile[5] = 0x00;
|
|
pCcFile[6] = 0xFF;
|
|
|
|
/* Tag (T) of Default NDEF TLV */
|
|
pCcFile[7] = 0x04;
|
|
|
|
/* Length (L) of Default NDEF TLV */
|
|
pCcFile[8] = 0x06;
|
|
|
|
/* NDEF File ID */
|
|
pCcFile[9] = 0xE1;
|
|
pCcFile[10] = 0x04;
|
|
|
|
/* NDEF File Size */
|
|
pCcFile[11] = 0x00;
|
|
pCcFile[12] = 0x00;
|
|
|
|
/* Read access */
|
|
pCcFile[13] = 0x00;
|
|
|
|
/* Write access */
|
|
pCcFile[14] = 0x00;
|
|
|
|
/* Update content length */
|
|
wCcContentLen = 15;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Validate content of CCLEN field with provided CC content length */
|
|
if((((uint16_t)pCcFile[0] << 8U ) | pCcFile[1]) != wCcContentLen)
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Validate supported version numbers */
|
|
if((pCcFile[2] != 0x30U) && (pCcFile[2] != 0x20U))
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Validate content length and version number */
|
|
if((pCcFile[2] == 0x30U) && (wCcContentLen < 17U))
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Check for minimum MLe */
|
|
if(((((uint16_t)pCcFile[3] << 8U) & 0xFF00U) | pCcFile[4]) < 0x0FU)
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Check for minimum MLc */
|
|
if(((((uint16_t)pCcFile[5] << 8U) & 0xFF00U) | pCcFile[6]) < 0x01U)
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Validate NDEF file ID */
|
|
if((((((uint16_t)pCcFile[9] << 8U) & 0xFF00U) | (pCcFile[10])) == 0x0000U)
|
|
|| (((((uint16_t)pCcFile[9] << 8U) & 0xFF00U) | (pCcFile[10])) == 0xE102U)
|
|
|| (((((uint16_t)pCcFile[9] << 8U) & 0xFF00U) | (pCcFile[10])) == 0xE103U)
|
|
|| (((((uint16_t)pCcFile[9] << 8U) & 0xFF00U) | (pCcFile[10]))== 0x3F00U)
|
|
|| (((((uint16_t)pCcFile[9] << 8U) & 0xFF00U) | (pCcFile[10])) == 0x3FFFU)
|
|
|| (((((uint16_t)pCcFile[9] << 8U) & 0xFF00U) | (pCcFile[10])) == 0xFFFFU))
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Validate NDEF TLV and NDEF file size (5 - 0xFFFE) */
|
|
if((pCcFile[2] == 0x20U) && ((pCcFile[7] != 0x04U) || (pCcFile[8] != 0x06U)
|
|
|| ((((((uint16_t)pCcFile[11]) << 8U) & 0xFF00U) | pCcFile[12]) < 0x05U)
|
|
|| ((((((uint16_t)pCcFile[11]) << 8U) & 0xFF00U) | pCcFile[12]) == 0xFFFFU)))
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Validate Extended NDEF TLV and NDEF file size (0xFFFF - 0xFFFFFFFE) */
|
|
if((pCcFile[2] == 0x30U) && ((pCcFile[7] != 0x06U) || (pCcFile[8] != 0x08U)
|
|
|| (((((uint32_t)pCcFile[11] << 24U) & 0xFF000000U)
|
|
| (((uint32_t)pCcFile[12] << 16U) & 0xFF0000U)
|
|
| (((uint32_t)pCcFile[13] << 8U) & 0xFF00U) | pCcFile[14]) < 0xFFFFU)
|
|
|| (((((uint32_t)pCcFile[11] << 24U) & 0xFF000000U)
|
|
| (((uint32_t)pCcFile[12] << 16U) & 0xFF0000U)
|
|
| (((uint32_t)pCcFile[13] << 8U) & 0xFF00U) | pCcFile[14]) == 0xFFFFFFFFU)))
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Validate NDEF read access */
|
|
if(((pCcFile[2] == 0x20U) && (pCcFile[13] != 0x00U))
|
|
|| ((pCcFile[2] == 0x30U) && (pCcFile[15] != 0x00U)))
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Validate NDEF write access */
|
|
if(((pCcFile[2] == 0x20U) && (pCcFile[14] != 0x00U) && (pCcFile[14] != 0xFFU))
|
|
|| ((pCcFile[2] == 0x30U) && (pCcFile[16] != 0x00U) && (pCcFile[16] != 0xFFU)))
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
}
|
|
|
|
#ifdef NXPBUILD__PHCE_T4T_PROPRIETARY
|
|
/* Check NDEF type to get content length till NDEF TLV end */
|
|
if(pCcFile[2] == 0x20U)
|
|
{
|
|
wIndex = 15;
|
|
}
|
|
else
|
|
{
|
|
wIndex = 17;
|
|
}
|
|
|
|
/* Validate Proprietary TLVs length */
|
|
if(((wCcContentLen - wIndex) % 8U) != 0U)
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Validate Proprietary TLV content */
|
|
while(wCcContentLen > wIndex)
|
|
{
|
|
/* Validate T and L field of proprietary TLV */
|
|
if((pCcFile[wIndex] != 0x05U) || (pCcFile[wIndex + 1U] != 0x06U))
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Validate file ID */
|
|
if((((((uint16_t)pCcFile[wIndex + 2U] << 8U) & 0xFF00U) | (pCcFile[wIndex + 3U])) == 0x0000U)
|
|
|| (((((uint16_t)pCcFile[wIndex + 2U] << 8U) & 0xFF00U) | (pCcFile[wIndex + 3U])) == 0xE102U)
|
|
|| (((((uint16_t)pCcFile[wIndex + 2U] << 8U) & 0xFF00U) | (pCcFile[wIndex + 3U])) == 0xE103U)
|
|
|| (((((uint16_t)pCcFile[wIndex + 2U] << 8U) & 0xFF00U) | (pCcFile[wIndex + 3U]))== 0x3F00U)
|
|
|| (((((uint16_t)pCcFile[wIndex + 2U] << 8U) & 0xFF00U) | (pCcFile[wIndex + 3U])) == 0x3FFFU)
|
|
|| (((((uint16_t)pCcFile[wIndex + 2U] << 8U) & 0xFF00U) | (pCcFile[wIndex + 3U])) == 0xFFFFU))
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Validate minimum file size */
|
|
if((((((uint16_t)pCcFile[wIndex + 4U]) << 8U) & 0xFF00U) | pCcFile[wIndex + 5U]) < 0x03U)
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Validate read access */
|
|
if(pCcFile[wIndex + 6U] != 0x00U)
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Validate write access */
|
|
if((pCcFile[wIndex + 7U] != 0x00U) && (pCcFile[wIndex + 7U] != 0xFFU))
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Increment Index */
|
|
wIndex += 8U;
|
|
}
|
|
#endif /* NXPBUILD__PHCE_T4T_PROPRIETARY */
|
|
#if !defined(NXPBUILD__PHCE_T4T_PROPRIETARY)
|
|
/* If only NDEF TLV is present, content length shall be 15 or 17 */
|
|
if((wCcContentLen != 15U) && (wCcContentLen != 17U))
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
#endif /* NXPBUILD__PHCE_T4T_PROPRIETARY */
|
|
|
|
pDataParams->pCcFile = pCcFile;
|
|
pDataParams->wCcFileSize = wCcFileSize;
|
|
pDataParams->wCcContentLen = wCcContentLen;
|
|
|
|
/* Set '0' for remaining file content */
|
|
(void)memset(&pCcFile[wCcContentLen], 0, (wCcFileSize - wCcContentLen));
|
|
|
|
/* Update state */
|
|
pDataParams->bTagState = PHCE_T4T_STATE_CC_FILE_CREATED;
|
|
|
|
return PH_ERR_SUCCESS;
|
|
}
|
|
|
|
phStatus_t phceT4T_Sw_Int_SetNdefFile(
|
|
phceT4T_Sw_DataParams_t *pDataParams,
|
|
uint8_t *pNdefFile,
|
|
uint16_t wNdefFileId,
|
|
uint32_t dwNdefFileSize,
|
|
uint32_t dwNdefContentLen
|
|
)
|
|
{
|
|
/* Check current state */
|
|
if(pDataParams->bTagState != PHCE_T4T_STATE_CC_FILE_CREATED)
|
|
{
|
|
return (PH_ERR_USE_CONDITION | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
if(pDataParams->bVno == PHCE_T4T_NDEF_SUPPORTED_VNO_20)
|
|
{
|
|
/* Check max NDEF file size for NDEF message mapping version 2.0 */
|
|
if((dwNdefFileSize < 5U) || (dwNdefFileSize > 0x7FFDU))
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Check max NDEF file size for NDEF message mapping version 3.0 */
|
|
if((dwNdefFileSize < 7U) || (dwNdefFileSize > 0xFFFFFFFAU))
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
}
|
|
|
|
/* Content length shall not be more than file size */
|
|
if(dwNdefFileSize < dwNdefContentLen)
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Validate file ID */
|
|
if((wNdefFileId == 0x0000U) || (wNdefFileId == 0xE102U) || (wNdefFileId == 0xE103U)
|
|
|| (wNdefFileId == 0x3F00U) || (wNdefFileId == 0x3FFFU) || (wNdefFileId == 0xFFFFU))
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
if(pDataParams->bVno == PHCE_T4T_NDEF_SUPPORTED_VNO)
|
|
{
|
|
if(pDataParams->wCcFileSize < 17U)
|
|
{
|
|
/* Extended NDEF TLV not supported with current CC file size */
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* NDEF File Size */
|
|
pDataParams->pCcFile[11] = (uint8_t)((dwNdefFileSize & 0xFF000000U) >> 24U);
|
|
pDataParams->pCcFile[12] = (uint8_t)((dwNdefFileSize & 0xFF0000U) >> 16U);
|
|
pDataParams->pCcFile[13] = (uint8_t)((dwNdefFileSize & 0xFF00U) >> 8U);
|
|
pDataParams->pCcFile[14] = (uint8_t)(dwNdefFileSize & 0xFFU);
|
|
}
|
|
else
|
|
{
|
|
if(pDataParams->wCcFileSize < 15U)
|
|
{
|
|
/* NDEF TLV not supported with current CC file size */
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Reset CC content if SetCcfile content and SetNdefFile content are not
|
|
* matching in NDEF TLV type / T4T version */
|
|
if(dwNdefFileSize > 0x7FFEU)
|
|
{
|
|
/* CC Length */
|
|
pDataParams->pCcFile[0] = 0x00;
|
|
pDataParams->pCcFile[1] = 0x11;
|
|
|
|
/* Mapping Version */
|
|
pDataParams->pCcFile[2] = 0x30;
|
|
|
|
/* Tag field of TLV */
|
|
pDataParams->pCcFile[7] = 0x06;
|
|
/* Length field of TLV */
|
|
pDataParams->pCcFile[8] = 0x08;
|
|
|
|
/* Read access */
|
|
pDataParams->pCcFile[15] = 0x00;
|
|
/* Write access */
|
|
pDataParams->pCcFile[16] = 0x00;
|
|
|
|
/* NDEF File Size */
|
|
pDataParams->pCcFile[11] = (uint8_t)((dwNdefFileSize & 0xFF000000U) >> 24U);
|
|
pDataParams->pCcFile[12] = (uint8_t)((dwNdefFileSize & 0xFF0000U) >> 16U);
|
|
pDataParams->pCcFile[13] = (uint8_t)((dwNdefFileSize & 0xFF00U) >> 8U);
|
|
pDataParams->pCcFile[14] = (uint8_t)(dwNdefFileSize & 0xFFU);
|
|
}
|
|
|
|
/* NDEF File Size */
|
|
pDataParams->pCcFile[11] = (uint8_t)((dwNdefFileSize & 0xFF00U) >> 8U);
|
|
pDataParams->pCcFile[12] = (uint8_t)(dwNdefFileSize & 0xFFU);
|
|
}
|
|
|
|
/* Update file ID in CC */
|
|
pDataParams->pCcFile[9] = (uint8_t)((wNdefFileId & 0xFF00U) >> 8U);
|
|
pDataParams->pCcFile[10] = (uint8_t)(wNdefFileId & 0xFFU);
|
|
|
|
pDataParams->pNdefFile = pNdefFile;
|
|
pDataParams->dwNdefFileSize = dwNdefFileSize;
|
|
|
|
/* Set '0' for remaining file content */
|
|
(void)memset(&pNdefFile[dwNdefContentLen], 0, (dwNdefFileSize - dwNdefContentLen));
|
|
|
|
/* Update state */
|
|
pDataParams->bTagState = PHCE_T4T_STATE_NDEF_FILE_CREATED;
|
|
|
|
return PH_ERR_SUCCESS;
|
|
}
|
|
|
|
#ifdef NXPBUILD__PHCE_T4T_PROPRIETARY
|
|
phStatus_t phceT4T_Sw_Int_SetProprietaryFile(
|
|
phceT4T_Sw_DataParams_t *pDataParams,
|
|
uint8_t *pFile,
|
|
uint16_t wFileId,
|
|
uint16_t wFileSize,
|
|
uint16_t wContentLen
|
|
)
|
|
{
|
|
uint16_t PH_MEMLOC_COUNT wIndex;
|
|
uint8_t PH_MEMLOC_COUNT bCount;
|
|
|
|
/* Check current state */
|
|
if(pDataParams->bTagState != PHCE_T4T_STATE_NDEF_FILE_CREATED)
|
|
{
|
|
return (PH_ERR_USE_CONDITION | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Check for file size */
|
|
if((wFileSize < 3U) || (wFileSize == 0xFFFFU))
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Content length shall not be more than file size */
|
|
if(wFileSize < wContentLen)
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Check proprietary file count */
|
|
if(pDataParams->bProprietaryFileCount == PHCE_T4T_MAX_PROPRIETARY_FILE)
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Validate with reserved file ID */
|
|
if((wFileId == 0x0000U) || (wFileId == 0xE102U) || (wFileId == 0xE103U)
|
|
|| (wFileId == 0x3F00U) || (wFileId == 0x3FFFU) || (wFileId == 0xFFFFU))
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Check with the NDEF file ID */
|
|
if((((((uint16_t)pDataParams->pCcFile[9] << 8U) & 0xFF00U)
|
|
| (pDataParams->pCcFile[10])) == wFileId))
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Check NDEF version to get CC content length till NDEF TLV end */
|
|
if(pDataParams->pCcFile[2] == 0x20U)
|
|
{
|
|
wIndex = 15;
|
|
}
|
|
else
|
|
{
|
|
wIndex = 17;
|
|
}
|
|
|
|
/* Check file ID with already created proprietary file IDs */
|
|
for(bCount = 0; bCount < pDataParams->bProprietaryFileCount; bCount++)
|
|
{
|
|
if(((((uint16_t)pDataParams->pCcFile[wIndex + (bCount * 8U) + 2U] << 8U) & 0xFF00U)
|
|
| (pDataParams->pCcFile[wIndex + (bCount * 8U) + 3U])) == wFileId)
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
}
|
|
|
|
/* Increment CC index based on current proprietary file count */
|
|
wIndex += pDataParams->bProprietaryFileCount * 8U;
|
|
|
|
/* Check if CC file can hold one more TLV */
|
|
if((wIndex + 8U) > pDataParams->wCcFileSize)
|
|
{
|
|
return (PH_ERR_INVALID_PARAMETER | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Check if this file was specified in CC */
|
|
if((pDataParams->wCcContentLen <= wIndex)
|
|
|| (pDataParams->pCcFile[wIndex + 2U] != (uint8_t)((wFileId & 0xFF00U) >> 8U))
|
|
|| (pDataParams->pCcFile[wIndex + 3U] != (uint8_t)(wFileId & 0xFFU)))
|
|
{
|
|
/* Tag */
|
|
pDataParams->pCcFile[wIndex] = 0x05;
|
|
/* Length */
|
|
pDataParams->pCcFile[wIndex + 1U] = 0x06;
|
|
|
|
/* File ID */
|
|
pDataParams->pCcFile[wIndex + 2U] = (uint8_t)((wFileId & 0xFF00U) >> 8U);
|
|
pDataParams->pCcFile[wIndex + 3U] = (uint8_t)(wFileId & 0xFFU);
|
|
|
|
/* Read access */
|
|
pDataParams->pCcFile[wIndex + 6U] = 0x00;
|
|
/* Write access */
|
|
pDataParams->pCcFile[wIndex + 7U] = 0x00;
|
|
}
|
|
|
|
/* File size */
|
|
pDataParams->pCcFile[wIndex + 4U] = (uint8_t)((wFileSize & 0xFF00U) >> 8U);
|
|
pDataParams->pCcFile[wIndex + 5U] = (uint8_t)(wFileSize & 0xFFU);
|
|
|
|
/* Update index */
|
|
wIndex += 8U;
|
|
|
|
/* Update CC Length to indicate content length till this TLV */
|
|
pDataParams->pCcFile[0] = (uint8_t)((wIndex & 0xFF00U) >> 8U);
|
|
pDataParams->pCcFile[1] = (uint8_t)(wIndex & 0xFFU);
|
|
|
|
/* Update proprietary file parameters */
|
|
pDataParams->asProprietaryFile[pDataParams->bProprietaryFileCount].pFile = pFile;
|
|
pDataParams->asProprietaryFile[pDataParams->bProprietaryFileCount].wFileSize = wFileSize;
|
|
pDataParams->asProprietaryFile[pDataParams->bProprietaryFileCount].wContentenLen = wContentLen;
|
|
|
|
/* Set '0' for remaining file content */
|
|
(void)memset(&pFile[wContentLen], 0, (wFileSize - wContentLen));
|
|
|
|
/* Increment file count */
|
|
pDataParams->bProprietaryFileCount++;
|
|
|
|
return PH_ERR_SUCCESS;
|
|
}
|
|
#endif /* NXPBUILD__PHCE_T4T_PROPRIETARY */
|
|
|
|
phStatus_t phceT4T_Sw_Int_Select(
|
|
phceT4T_Sw_DataParams_t *pDataParams,
|
|
uint8_t *pRxData,
|
|
uint16_t wRxDataLen,
|
|
uint16_t *pStatusWord
|
|
)
|
|
{
|
|
#ifdef NXPBUILD__PHCE_T4T_PROPRIETARY
|
|
uint16_t PH_MEMLOC_COUNT wIndex;
|
|
uint8_t PH_MEMLOC_COUNT bCount;
|
|
#endif /* NXPBUILD__PHCE_T4T_PROPRIETARY */
|
|
uint16_t PH_MEMLOC_REM wFileId;
|
|
uint8_t PH_MEMLOC_BUF bNdefAppName[7] = {0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01};
|
|
|
|
/* Select file/application by name */
|
|
if((pRxData[2] == 0x04U) && (pRxData[3] == 0x00U))
|
|
{
|
|
/* Check the command length and Lc for NDEF APP Select */
|
|
if((wRxDataLen < 0x0DU) || (pRxData[4] != 0x07U))
|
|
{
|
|
/* Length of the command is invalid */
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_LENGTH;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Validate NDEF Tag application name. */
|
|
if(memcmp(&pRxData[5], bNdefAppName, 7))
|
|
{
|
|
/* Application name mismatch */
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_FILE_NOT_FOUND;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
else
|
|
{
|
|
/* NDEF Tag application Selected */
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_SUCCESS;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
pDataParams->bTagState = PHCE_T4T_STATE_NDEF_APP_SELECTED;
|
|
|
|
return (PH_CE_T4T_SELECT | PH_COMP_CE_T4T);
|
|
}
|
|
}
|
|
/* Select file by ID */
|
|
else if((pRxData[2] == 0x00U) && (pRxData[3] == 0x0CU))
|
|
{
|
|
if (pDataParams->bTagState < PHCE_T4T_STATE_NDEF_APP_SELECTED)
|
|
{
|
|
/* Files are present only in NDEF APP. */
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_FILE_NOT_FOUND;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Check the length of select command and the Lc byte is 0x02. */
|
|
if ((wRxDataLen > 0x07U) || ((pRxData[4] != 0x02U)))
|
|
{
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_FILE_NOT_FOUND;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* File ID to be selected */
|
|
wFileId = (uint16_t)((((uint16_t)(pRxData[5])) << 8U) & 0xFF00U) | ((uint16_t)(pRxData[6]));
|
|
|
|
if(wFileId == PHCE_T4T_CC_FILE_ID)
|
|
{
|
|
pDataParams->wSelectedFileId = wFileId;
|
|
pDataParams->pSelectedFile = pDataParams->pCcFile;
|
|
pDataParams->dwFileSize = pDataParams->wCcFileSize;
|
|
pDataParams->bFileWriteAccess = 0xFF;
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_SUCCESS;
|
|
pDataParams->bTagState = PHCE_T4T_STATE_FILE_SELECTED;
|
|
|
|
return (PH_CE_T4T_SELECT | PH_COMP_CE_T4T);
|
|
}
|
|
else if(wFileId == (((((uint16_t)(pDataParams->pCcFile[9])) << 8U) & 0xFF00U)
|
|
| (((uint16_t)(pDataParams->pCcFile[10])))))
|
|
{
|
|
pDataParams->wSelectedFileId = wFileId;
|
|
pDataParams->pSelectedFile = pDataParams->pNdefFile;
|
|
pDataParams->dwFileSize = pDataParams->dwNdefFileSize;
|
|
|
|
if(pDataParams->pCcFile[2] == 0x20U)
|
|
{
|
|
/* NDEF File Write access */
|
|
pDataParams->bFileWriteAccess = pDataParams->pCcFile[14];
|
|
}
|
|
else
|
|
{
|
|
/* Extended NDEF Writ access */
|
|
pDataParams->bFileWriteAccess = pDataParams->pCcFile[16];
|
|
}
|
|
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_SUCCESS;
|
|
pDataParams->bTagState = PHCE_T4T_STATE_FILE_SELECTED;
|
|
|
|
/* File selected */
|
|
return (PH_CE_T4T_SELECT | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
#ifdef NXPBUILD__PHCE_T4T_PROPRIETARY
|
|
else if(0U != (pDataParams->bProprietaryFileCount))
|
|
{
|
|
if(pDataParams->pCcFile[2] == 0x20U)
|
|
{
|
|
/* Index of the first Proprietary TLV in version 2.0 */
|
|
wIndex = 17;
|
|
}
|
|
else
|
|
{
|
|
/* Index of the first Proprietary TLV in version 3 .0 */
|
|
wIndex = 19;
|
|
}
|
|
|
|
/* Check file ID exists in the application */
|
|
for(bCount = 0; bCount < pDataParams->bProprietaryFileCount; bCount++)
|
|
{
|
|
if((((((uint16_t)pDataParams->pCcFile[wIndex + (bCount * 8U)]) << 8U) & 0xFF00U)
|
|
| (pDataParams->pCcFile[wIndex + (bCount * 8U) + 1U])) == wFileId)
|
|
{
|
|
/* Proprietary file Selected */
|
|
pDataParams->wSelectedFileId = wFileId;
|
|
pDataParams->pSelectedFile = pDataParams->asProprietaryFile[bCount].pFile;
|
|
pDataParams->dwFileSize = pDataParams->asProprietaryFile[bCount].wFileSize;
|
|
pDataParams->bFileWriteAccess = (pDataParams->pCcFile[wIndex + (bCount * 8U) + 5U]);
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_SUCCESS;
|
|
pDataParams->bTagState = PHCE_T4T_STATE_FILE_SELECTED;
|
|
|
|
/* File selected */
|
|
return (PH_CE_T4T_SELECT | PH_COMP_CE_T4T);
|
|
}
|
|
}
|
|
|
|
/* File ID to be selected does not exist among proprietary files */
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_FILE_NOT_FOUND;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
#endif /* NXPBUILD__PHCE_T4T_PROPRIETARY */
|
|
else
|
|
{
|
|
/* Requested fileID to be selected does not exist */
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_FILE_NOT_FOUND;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_PARAMETER;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
}
|
|
|
|
phStatus_t phceT4T_Sw_Int_ReadBinary(
|
|
phceT4T_Sw_DataParams_t *pDataParams,
|
|
uint8_t *pRxData,
|
|
uint16_t wRxDataLen,
|
|
uint16_t *pStatusWord,
|
|
uint8_t **ppTxData,
|
|
uint16_t *pTxDataLen
|
|
)
|
|
{
|
|
uint32_t PH_MEMLOC_REM wOffset;
|
|
uint16_t PH_MEMLOC_REM wLe;
|
|
uint8_t PH_MEMLOC_REM bCommandType;
|
|
|
|
/* Check if the File is selected */
|
|
if(pDataParams->pSelectedFile == NULL)
|
|
{
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_UNSUPPORTED_FUNC;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* For tag NDEF supported version 2.0, Check whether Lc and Le values is of short/extended field coding */
|
|
if(((pDataParams->bVno == PHCE_T4T_NDEF_SUPPORTED_VNO_20) || (pDataParams->bVno == PHCE_T4T_NDEF_SUPPORTED_VNO)) && (pRxData[1] == 0xB0)
|
|
&& ((wRxDataLen == 0x05U) || (wRxDataLen == 0x06U) || (wRxDataLen == 0x07U)))
|
|
{
|
|
bCommandType = PHCE_T4T_SHORT_LEN_CMD;
|
|
|
|
/* Set the Offset value */
|
|
wOffset = (uint16_t)((((uint16_t)pRxData[2] << 8U) & 0xFF00U) | pRxData[3]);
|
|
|
|
/* Check for valid offset value */
|
|
if((uint16_t) wOffset > 0x7FFFU)
|
|
{
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_PARAMETER;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* 2 bytes Extended field coding of Le */
|
|
if(wRxDataLen == 0x06U)
|
|
{
|
|
/* Set the Expected Length */
|
|
wLe = (uint16_t)((((uint16_t) pRxData[wRxDataLen - 2u] << 8U) & 0xFF00U) | pRxData[wRxDataLen - 1u]);
|
|
|
|
/* Return if Le = 0, which encodes the maximum number of bytes expected equal to 65536 bytes */
|
|
if(wLe == 0U)
|
|
{
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_LENGTH;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
}
|
|
/* 3 bytes Extended field coding of Le */
|
|
if(wRxDataLen == 0x07U)
|
|
{
|
|
/* Set the Expected Length */
|
|
wLe = (uint16_t)((((uint16_t) pRxData[wRxDataLen - 2u] << 8U) & 0xFF00U) | pRxData[wRxDataLen - 1u]);
|
|
|
|
/* Return if Le = 0, which encodes the maximum number of bytes expected equal to 65536 bytes */
|
|
if((pRxData[wRxDataLen - 3u] != 0x0U) || (wLe == 0U))
|
|
{
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_LENGTH;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
}
|
|
/* Short field coding of Le */
|
|
else
|
|
{
|
|
/* Set the Expected Length */
|
|
wLe = pRxData[wRxDataLen - 1u];
|
|
|
|
if(wLe == 0x0U)
|
|
{
|
|
/* In short field coding Le = 0 encodes the maximum number of bytes expected equal to 256 bytes */
|
|
wLe = 256U;
|
|
}
|
|
}
|
|
|
|
/* Check for MLe and Expected Length */
|
|
if(((((uint16_t) pDataParams->pCcFile[3] << 8U) & 0xFF00U) | pDataParams->pCcFile[4]) < wLe)
|
|
{
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_LENGTH;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
}
|
|
/* For tag NDEF supported version 3.0, verify the Lc and Le values for short field coding */
|
|
else if((pDataParams->bVno == PHCE_T4T_NDEF_SUPPORTED_VNO) && (pRxData[1] == 0xB1) && (wRxDataLen == 0x0BU))
|
|
{
|
|
bCommandType = PHCE_T4T_EXT_LEN_CMD;
|
|
|
|
/* Lc field value should not be zero for Short field coding */
|
|
if(pRxData[4] == 0x00U)
|
|
{
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_LENGTH;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Set the Offset value */
|
|
wOffset = (((pRxData[7] << 16U) & 0xFF0000U) | ((pRxData[8] << 8U) & 0x00FF00U) | pRxData[9]);
|
|
|
|
/* Check for valid offset value */
|
|
if(wOffset > 0xFFFFFEU)
|
|
{
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_PARAMETER;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Set the Expected Length */
|
|
wLe = pRxData[wRxDataLen - 1u];
|
|
|
|
if(wLe == 0x0U)
|
|
{
|
|
/* In short field coding Le = 0 encodes the maximum number of bytes expected equal to 256 bytes */
|
|
wLe = 256U;
|
|
}
|
|
|
|
/* Check for MLe and expected Length */
|
|
if(((((uint16_t)pDataParams->pCcFile[3] << 8U) & 0xFF00U) | pDataParams->pCcFile[4]) < wLe)
|
|
{
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_LENGTH;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
}
|
|
/* For tag NDEF supported version 3.0, verify the Lc and Le values for extended field coding */
|
|
else if((pDataParams->bVno == PHCE_T4T_NDEF_SUPPORTED_VNO) && (pRxData[1] == 0xB1) && (wRxDataLen == 0x0EU))
|
|
{
|
|
bCommandType = PHCE_T4T_EXT_LEN_CMD;
|
|
|
|
/* Lc field value should be zero for extended field coding */
|
|
if(pRxData[4] != 0x00U)
|
|
{
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_LENGTH;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Set the Offset value */
|
|
wOffset = (((pRxData[9] << 16U) & 0xFF0000U) | ((pRxData[10] << 8U) & 0x00FF00U) | pRxData[11]);
|
|
|
|
/* Check for valid offset value */
|
|
if(wOffset > 0xFFFFFEU)
|
|
{
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_PARAMETER;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Set the Expected Length */
|
|
wLe = (uint16_t)((((uint16_t) pRxData[wRxDataLen - 2u] << 8U) & 0xFF00U) | pRxData[wRxDataLen - 1u]);
|
|
|
|
/* Check for MLe and expected Length */
|
|
/* Return if Le = 0, which encodes the maximum number of bytes expected equal to 65536 bytes */
|
|
if((((((uint16_t)pDataParams->pCcFile[3] << 8U) & 0xFF00U) | pDataParams->pCcFile[4]) < wLe) || (wLe == 0U))
|
|
{
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_LENGTH;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
}
|
|
/* Invalid Read Binary cmd length */
|
|
else
|
|
{
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_LENGTH;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
if((((pDataParams->dwFileSize) - wOffset) < wLe) && (wLe != 0x0000U))
|
|
{
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_LENGTH;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Assign the the data pointer and the data length to be executed */
|
|
*ppTxData = &(pDataParams->pSelectedFile[wOffset]);
|
|
|
|
if(wLe != 0x0000U)
|
|
{
|
|
*pTxDataLen = wLe;
|
|
}
|
|
else
|
|
{
|
|
if(bCommandType == PHCE_T4T_SHORT_LEN_CMD)
|
|
{
|
|
*pTxDataLen = (uint16_t)(((pDataParams->dwFileSize - wOffset) > 0x0100U)?
|
|
0x0100 : (pDataParams->dwFileSize - wOffset));
|
|
}
|
|
else
|
|
{
|
|
*pTxDataLen = (uint16_t)(((pDataParams->dwFileSize - wOffset) > 0xFFFFU)?
|
|
0xFFFF : (pDataParams->dwFileSize - wOffset));
|
|
}
|
|
}
|
|
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_SUCCESS;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
pDataParams->bTagState = PHCE_T4T_STATE_FILE_READ;
|
|
|
|
return (PH_CE_T4T_READ_BINARY | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
phStatus_t phceT4T_Sw_Int_UpdateBinary(
|
|
phceT4T_Sw_DataParams_t *pDataParams,
|
|
uint16_t wOption,
|
|
uint8_t *pRxData,
|
|
uint16_t wRxDataLen,
|
|
uint16_t *pStatusWord,
|
|
uint8_t **ppTxData,
|
|
uint16_t *pTxDataLen
|
|
)
|
|
{
|
|
uint32_t PH_MEMLOC_REM wOffset = 0;
|
|
uint8_t PH_MEMLOC_REM bCommandType = 0;
|
|
uint8_t PH_MEMLOC_REM bIns = 0;
|
|
|
|
if((pDataParams->bTagState < PHCE_T4T_STATE_FILE_SELECTED) || (pDataParams->pSelectedFile == NULL))
|
|
{
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_UNSUPPORTED_FUNC;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
if(pDataParams->bFileWriteAccess != 0x00U)
|
|
{
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_UNSUPPORTED_FUNC;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Check offset of the NDEF file to start writing the data and Length of the data to be written as per v2.0 */
|
|
if(((pDataParams->bVno == PHCE_T4T_NDEF_SUPPORTED_VNO_20) || (pDataParams->bVno == PHCE_T4T_NDEF_SUPPORTED_VNO)) && (pRxData[1] == 0xD6U))
|
|
{
|
|
/* Update binary cmd */
|
|
bIns = PHCE_T4T_INS_UPDATE;
|
|
|
|
/* Set the offset from the Parameter bytes */
|
|
wOffset = (uint16_t)((((uint16_t)pRxData[2] << 8U) & 0xFF00U) | pRxData[3]);
|
|
|
|
/* Set the wLc bytes */
|
|
if(pRxData[4] != 0x00U)
|
|
{
|
|
bCommandType = PHCE_T4T_SHORT_LEN_CMD;
|
|
pDataParams->wLc = pRxData[4]; /* Num of bytes in the data field */
|
|
pDataParams->wWriteDataOffset = 0x5U; /* Index from which Data to be written to the NDEF File starts */
|
|
|
|
if(wOption == PHCE_T4T_RXDEFAULT)
|
|
{
|
|
if((wRxDataLen - 5u) != pDataParams->wLc)
|
|
{
|
|
/* Change error code to length error */
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_LENGTH;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(!((wRxDataLen - 5u) <= pDataParams->wLc))
|
|
{
|
|
/* Change error code to length error */
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_LENGTH;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bCommandType = PHCE_T4T_EXT_LEN_CMD;
|
|
pDataParams->wLc = (uint16_t)((((uint16_t)pRxData[5] << 8U) & 0xFF00U) | pRxData[6]); /* Num of bytes in the data field */
|
|
pDataParams->wWriteDataOffset = 0x7U; /* Index from which Data to be written to the NDEF File starts */
|
|
|
|
if(wOption == PHCE_T4T_RXDEFAULT)
|
|
{
|
|
if((wRxDataLen - 7u) != pDataParams->wLc)
|
|
{
|
|
/* Change error code to length error */
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_LENGTH;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(!((wRxDataLen - 7u) <= pDataParams->wLc))
|
|
{
|
|
/* Change error code to length error */
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_LENGTH;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Num of data bytes to be written to the NDEF File */
|
|
pDataParams->wTxDataLen = pDataParams->wLc;
|
|
}
|
|
/* Check offset of the NDEF file to start writing the data and Length of the data to be written as per v3.0 */
|
|
else if((pDataParams->bVno == PHCE_T4T_NDEF_SUPPORTED_VNO) && (pRxData[1] == 0xD7U))
|
|
{
|
|
/* Update binary cmd with ODO and DDO */
|
|
bIns = PHCE_T4T_INS_UPDATE_ODO;
|
|
|
|
/* P1 and P2 values should be zero for T4T v3.0 */
|
|
if((pRxData[2] != 0x00U) || (pRxData[3] != 0x00U))
|
|
{
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_PARAMETER;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Set the wLc bytes */
|
|
if(pRxData[4] != 0x00U)
|
|
{
|
|
/* Set the offset from the Parameter bytes */
|
|
wOffset = (((pRxData[7] << 16U) & 0xFF0000U) | ((pRxData[8] << 8U) & 0x00FF00U) | pRxData[9]);
|
|
bCommandType = PHCE_T4T_SHORT_LEN_CMD;
|
|
pDataParams->wLc = pRxData[4]; /* Num of bytes in the data field */
|
|
if(pRxData[11] > 0x7F)
|
|
{
|
|
/* Index from which Data to be written to the NDEF File starts */
|
|
pDataParams->wWriteDataOffset = (11U + ((pRxData[11] & 0x0F) + 1));
|
|
|
|
if(pRxData[11] == 0x81U)
|
|
{
|
|
/* Num of data bytes to be written to the NDEF File */
|
|
pDataParams->wTxDataLen = pRxData[12];
|
|
}
|
|
else if(pRxData[11] == 0x82U)
|
|
{
|
|
/* Num of data bytes to be written to the NDEF File */
|
|
pDataParams->wTxDataLen = (uint16_t)((((uint16_t)pRxData[12] << 8U) & 0xFF00U) | pRxData[13]);
|
|
}
|
|
else
|
|
{
|
|
/* Change error code to length error */
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_LENGTH;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pDataParams->wWriteDataOffset = 12U; /* Index from which Data to be written to the NDEF File starts */
|
|
pDataParams->wTxDataLen = pRxData[11]; /* Num of data bytes to be written to the NDEF File */
|
|
}
|
|
|
|
if(wOption == PHCE_T4T_RXDEFAULT)
|
|
{
|
|
if((wRxDataLen - 5u) != pDataParams->wLc)
|
|
{
|
|
/* Change error code to length error */
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_LENGTH;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(!((wRxDataLen - 5u) <= pDataParams->wLc))
|
|
{
|
|
/* Change error code to length error */
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_LENGTH;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Set the offset from the Parameter bytes */
|
|
wOffset = (((pRxData[9] << 16U) & 0xFF0000U) | ((pRxData[10] << 8U) & 0x00FF00U) | pRxData[11]);
|
|
bCommandType = PHCE_T4T_EXT_LEN_CMD;
|
|
pDataParams->wLc = (uint16_t)((((uint16_t)pRxData[5] << 8U) & 0xFF00U) | pRxData[6]); /* Num of bytes in the data field */
|
|
|
|
if(pRxData[13] > 0x7F)
|
|
{
|
|
/* Index from which Data to be written to the NDEF File starts */
|
|
pDataParams->wWriteDataOffset = (13U + ((pRxData[13] & 0x0F) + 1));
|
|
|
|
if(pRxData[13] == 0x81U)
|
|
{
|
|
/* Num of data bytes to be written to the NDEF File */
|
|
pDataParams->wTxDataLen = pRxData[14];
|
|
}
|
|
else if(pRxData[13] == 0x82U)
|
|
{
|
|
/* Num of data bytes to be written to the NDEF File */
|
|
pDataParams->wTxDataLen = (uint16_t)((((uint16_t)pRxData[14] << 8U) & 0xFF00U) | pRxData[15]);
|
|
}
|
|
else
|
|
{
|
|
/* Change error code to length error */
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_LENGTH;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pDataParams->wWriteDataOffset = 14U; /* Index from which Data to be written to the NDEF File starts */
|
|
pDataParams->wTxDataLen = pRxData[13]; /* Num of data bytes to be written to the NDEF File */
|
|
}
|
|
|
|
if(wOption == PHCE_T4T_RXDEFAULT)
|
|
{
|
|
if((wRxDataLen - 7u) != pDataParams->wLc)
|
|
{
|
|
/* Change error code to length error */
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_LENGTH;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(!((wRxDataLen - 7u) <= pDataParams->wLc))
|
|
{
|
|
/* Change error code to length error */
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_LENGTH;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_LENGTH;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Update the file offset in data parameter */
|
|
pDataParams->dwFileOffset = wOffset;
|
|
|
|
/* Check for Max File size and the data to be written */
|
|
if((uint32_t)(pDataParams->dwFileSize) < (uint32_t)(wOffset + pDataParams->wLc))
|
|
{
|
|
/* Change error code to length error */
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_LENGTH;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Assign the default out parameters */
|
|
if(bCommandType == PHCE_T4T_SHORT_LEN_CMD)
|
|
{
|
|
*ppTxData = &pRxData[pDataParams->wWriteDataOffset];
|
|
*pTxDataLen = (bIns == PHCE_T4T_INS_UPDATE) ? (wRxDataLen - 5u) : pDataParams->wTxDataLen;
|
|
pDataParams->wLc = pDataParams->wLc - (wRxDataLen - 5u);
|
|
}
|
|
else
|
|
{
|
|
*ppTxData = &pRxData[pDataParams->wWriteDataOffset];
|
|
*pTxDataLen = (bIns == PHCE_T4T_INS_UPDATE) ? (wRxDataLen - 7u) : pDataParams->wTxDataLen;
|
|
pDataParams->wLc = pDataParams->wLc - (wRxDataLen - 7u);
|
|
}
|
|
|
|
/* Check for MLc and data to be written Length */
|
|
if(((((uint16_t)pDataParams->pCcFile[5] << 8U) & 0xFF00U) | pDataParams->pCcFile[6]) < *pTxDataLen)
|
|
{
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_ERR_LENGTH;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
|
|
return (PH_CE_T4T_FAILURE | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
/* Update file if configured to */
|
|
if(pDataParams->bHandleUpdateCmd == PH_ON)
|
|
{
|
|
phceT4T_Sw_Int_UpdateFile(
|
|
pDataParams,
|
|
*ppTxData,
|
|
*pTxDataLen);
|
|
|
|
/* Set TX data to 0 */
|
|
*ppTxData = NULL;
|
|
*pTxDataLen = 0;
|
|
}
|
|
|
|
pDataParams->wStatusWord = PHCE_T4T_ISO7816_SUCCESS;
|
|
*pStatusWord = pDataParams->wStatusWord;
|
|
pDataParams->bTagState = PHCE_T4T_STATE_FILE_UPDATE;
|
|
|
|
return (PH_CE_T4T_UPDATE_BINARY | PH_COMP_CE_T4T);
|
|
}
|
|
|
|
phStatus_t phceT4T_Sw_Int_Activate(
|
|
phceT4T_Sw_DataParams_t *pDataParams
|
|
)
|
|
{
|
|
#ifndef _WIN32
|
|
phOsal_EventBits_t PH_MEMLOC_REM events;
|
|
phStatus_t PH_MEMLOC_REM status = 0;
|
|
uint16_t PH_MEMLOC_REM wOption = PH_RECEIVE_DEFAULT;
|
|
uint8_t PH_MEMLOC_BUF *pRxData = NULL;
|
|
uint16_t PH_MEMLOC_REM wRxDataLen = 0;
|
|
uint8_t PH_MEMLOC_BUF *pTxData;
|
|
uint16_t PH_MEMLOC_REM wTxDataLen = 0;
|
|
uint16_t PH_MEMLOC_REM wTxChainingLen = 0;
|
|
uint16_t PH_MEMLOC_REM wStatusWord;
|
|
uint16_t PH_MEMLOC_REM wFsd;
|
|
uint16_t PH_MEMLOC_REM wCidPresence;
|
|
uint16_t PH_MEMLOC_REM wNadPresence;
|
|
uint8_t PH_MEMLOC_REM bTxType = PHCE_SEND_NO_DATA;
|
|
uint8_t PH_MEMLOC_REM bExitLoop = FALSE;
|
|
uint8_t PH_MEMLOC_REM bWaitForData;
|
|
uint8_t PH_MEMLOC_BUF aSw[2];
|
|
uint8_t PH_MEMLOC_BUF aRapduOdo[4] = {0};
|
|
uint8_t PH_MEMLOC_BUF bRapduOdoLen = 0;
|
|
|
|
/* Reset RX option */
|
|
pDataParams->bRxOption = PH_RECEIVE_DEFAULT;
|
|
|
|
/* Be in HCE state till DESELECTED or receive error */
|
|
while(bExitLoop != TRUE)
|
|
{
|
|
/* Receive loop for RX chaining */
|
|
do
|
|
{
|
|
/* Reset Data to be send flag */
|
|
bTxType = PHCE_SEND_NO_DATA;
|
|
|
|
/* Receive Data */
|
|
status = phpalI14443p4mC_Receive(
|
|
pDataParams->pPalI14443p4mCDataParams,
|
|
wOption,
|
|
&pRxData,
|
|
&wRxDataLen);
|
|
|
|
if((status & PH_ERR_MASK) == PH_ERR_SUCCESS)
|
|
{
|
|
if(wOption == PH_RECEIVE_DEFAULT)
|
|
{
|
|
/* Default processing option */
|
|
pDataParams->bRxOption = PHCE_T4T_RXDEFAULT;
|
|
}
|
|
else
|
|
{
|
|
/* Last buffer of RX chaining */
|
|
pDataParams->bRxOption = PHCE_T4T_RXCHAINING_BUFFER_LAST;
|
|
}
|
|
/* Set to default receive option */
|
|
wOption = PH_RECEIVE_DEFAULT;
|
|
}
|
|
else if((status & PH_ERR_MASK) == PH_ERR_SUCCESS_CHAINING)
|
|
{
|
|
if(wOption == PH_RECEIVE_DEFAULT)
|
|
{
|
|
/* First buffer of RX chaining */
|
|
pDataParams->bRxOption = PHCE_T4T_RXCHAINING_BUFFER_FIRST;
|
|
}
|
|
else
|
|
{
|
|
/* Subsequent buffer of RX chaining */
|
|
pDataParams->bRxOption = PHCE_T4T_RXCHAINING_BUFFER_CONT;
|
|
}
|
|
/* Set chaining receive option */
|
|
wOption = PH_RECEIVE_CHAINING;
|
|
}
|
|
else if((status & PH_ERR_MASK) == PH_ERR_SUCCESS_DESELECTED)
|
|
{
|
|
/* DESELECTED */
|
|
status = (PH_ERR_SUCCESS_DESELECTED | PH_COMP_CE_T4T);
|
|
|
|
/* Exit */
|
|
break;
|
|
}
|
|
else if((status & PH_ERR_MASK) == PH_ERR_EXT_RF_ERROR)
|
|
{
|
|
/* External RF off */
|
|
status = (PH_ERR_EXT_RF_ERROR | PH_COMP_CE_T4T);
|
|
|
|
/* Exit */
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
/* Exit */
|
|
break;
|
|
}
|
|
|
|
/* Process the received command */
|
|
status = phceT4T_Sw_ProcessCmd(
|
|
pDataParams,
|
|
pDataParams->bRxOption,
|
|
pRxData,
|
|
wRxDataLen,
|
|
&wStatusWord,
|
|
&pTxData,
|
|
&wTxDataLen);
|
|
|
|
switch(status & PH_ERR_MASK)
|
|
{
|
|
case PH_CE_T4T_UPDATE_BINARY:
|
|
case PH_CE_T4T_PROPRIETARY:
|
|
/* If UPDATE BINARY is handled by ProcessCmd, send Status Word. */
|
|
if(((status & PH_ERR_MASK) == PH_CE_T4T_UPDATE_BINARY)
|
|
&& (pDataParams->bHandleUpdateCmd == PH_ON))
|
|
{
|
|
/* Update TX data */
|
|
pTxData = NULL;
|
|
wTxDataLen = 0;
|
|
|
|
/* Set data to be send flag */
|
|
bTxType = PHCE_SEND_DATA;
|
|
break;
|
|
}
|
|
|
|
/* If proprietary command handling is disabled, send the Status
|
|
* Word (indicating unsupported command). */
|
|
if(((status & PH_ERR_MASK) == PH_CE_T4T_PROPRIETARY)
|
|
&& (pDataParams->bSupportProprietaryCmd == PH_OFF))
|
|
{
|
|
/* Update TX data */
|
|
pTxData = NULL;
|
|
wTxDataLen = 0;
|
|
|
|
/* Set data to be send flag */
|
|
bTxType = PHCE_SEND_DATA;
|
|
break;
|
|
}
|
|
|
|
/* Copy data to application buffer */
|
|
if(pDataParams->wAppBufferSize < wRxDataLen)
|
|
{
|
|
/* Return buffer overflow error */
|
|
return (PH_ERR_BUFFER_OVERFLOW | PH_COMP_CE_T4T);
|
|
}
|
|
else
|
|
{
|
|
(void)memcpy(pDataParams->pAppBuffer, pRxData, wRxDataLen);
|
|
|
|
/* Update data to be shared with AppProcessCmd */
|
|
pDataParams->pSharedData = pDataParams->pAppBuffer;
|
|
pDataParams->wSharedDataLen = wRxDataLen;
|
|
}
|
|
|
|
/* Set RX Data available event */
|
|
PH_CHECK_SUCCESS_FCT(status,
|
|
phOsal_EventPost(&pDataParams->T4TEventObj.EventHandle, E_OS_EVENT_OPT_NONE, E_PH_OSAL_EVT_RXDATA_AVAILABLE, NULL));
|
|
|
|
/* Loop till TX data is received from AppProcessCmd */
|
|
do
|
|
{
|
|
/* Wait for TX Data or WTX */
|
|
PH_CHECK_SUCCESS_FCT(status, phOsal_EventPend((volatile phOsal_Event_t * )(&pDataParams->T4TEventObj.EventHandle), E_OS_EVENT_OPT_PEND_SET_ANY, 0xFFFFFFFFU,
|
|
(E_PH_OSAL_EVT_TXDATA_AVAILABLE | E_PH_OSAL_EVT_RTO_TIMEOUT | E_PH_OSAL_EVT_ABORT), &events));
|
|
|
|
if((events & E_PH_OSAL_EVT_RTO_TIMEOUT) == E_PH_OSAL_EVT_RTO_TIMEOUT)
|
|
{
|
|
/* Clear event */
|
|
PH_CHECK_SUCCESS_FCT(status,
|
|
phOsal_EventClear(&pDataParams->T4TEventObj.EventHandle, E_OS_EVENT_OPT_NONE, E_PH_OSAL_EVT_RTO_TIMEOUT, NULL));
|
|
|
|
/* Send WTX */
|
|
PH_CHECK_SUCCESS_FCT(status, phpalI14443p4mC_Wtx(
|
|
pDataParams->pPalI14443p4mCDataParams));
|
|
|
|
/* Back to wait TX data or WTX */
|
|
bWaitForData = TRUE;
|
|
}
|
|
else if((events & E_PH_OSAL_EVT_TXDATA_AVAILABLE) == E_PH_OSAL_EVT_TXDATA_AVAILABLE)
|
|
{
|
|
/* Clear event */
|
|
PH_CHECK_SUCCESS_FCT(status,
|
|
phOsal_EventClear(&pDataParams->T4TEventObj.EventHandle, E_OS_EVENT_OPT_NONE, E_PH_OSAL_EVT_TXDATA_AVAILABLE, NULL));
|
|
|
|
/* Update TX Data */
|
|
pTxData = pDataParams->pSharedData;
|
|
wTxDataLen = pDataParams->wSharedDataLen;
|
|
|
|
/* Set data to be send flag */
|
|
bTxType = PHCE_SEND_DATA;
|
|
|
|
/* Data received, exit and transmit the data */
|
|
bWaitForData = FALSE;
|
|
}
|
|
else
|
|
{
|
|
/* Aborted */
|
|
return (PH_ERR_ABORTED | PH_COMP_CE_T4T);
|
|
}
|
|
}
|
|
while(0U != bWaitForData);
|
|
break;
|
|
|
|
case PH_CE_T4T_SELECT:
|
|
case PH_CE_T4T_FAILURE:
|
|
case PH_CE_T4T_READ_BINARY:
|
|
/* For select and failure, only status word is send */
|
|
if(((status & PH_ERR_MASK) == PH_CE_T4T_FAILURE)
|
|
|| ((status & PH_ERR_MASK) == PH_CE_T4T_SELECT))
|
|
{
|
|
pTxData = NULL;
|
|
wTxDataLen = 0;
|
|
}
|
|
|
|
/* Enable transmission of response */
|
|
bTxType = PHCE_SEND_DATA;
|
|
break;
|
|
|
|
default:
|
|
/* Control will never come here */
|
|
break;
|
|
}
|
|
}
|
|
while(wOption == PH_RECEIVE_CHAINING);
|
|
|
|
if(bTxType == PHCE_SEND_DATA)
|
|
{
|
|
/* Reset data length used for TX chaining */
|
|
wTxChainingLen = 0;
|
|
|
|
/* Preparing the content data to be encapsulated in a DDO method */
|
|
if((pDataParams->bVno == PHCE_T4T_NDEF_SUPPORTED_VNO) && (pRxData[1] == 0xB1))
|
|
{
|
|
aRapduOdo[0] = 0x53U;
|
|
|
|
if(wTxDataLen <= 0x7FU)
|
|
{
|
|
wTxDataLen -= 2; /* 0x53 + Len(1 byte) */
|
|
aRapduOdo[1] = (uint8_t)wTxDataLen;
|
|
bRapduOdoLen = 2;
|
|
}
|
|
else if((wTxDataLen > 0x7FU) && (wTxDataLen <= 0xFFU))
|
|
{
|
|
wTxDataLen -= 3; /* 0x53 + 0x81 + Len(1 byte) */
|
|
aRapduOdo[1] = 0x81;
|
|
aRapduOdo[2] = (uint8_t)wTxDataLen;
|
|
bRapduOdoLen = 3;
|
|
}
|
|
else
|
|
{
|
|
wTxDataLen -= 4; /* 0x53 + 0x81 + Len(2 bytes) */
|
|
aRapduOdo[1] = 0x82;
|
|
aRapduOdo[2] = (uint8_t)(wTxDataLen & 0xFF00);
|
|
aRapduOdo[3] = (uint8_t)(wTxDataLen & 0x00FF);
|
|
bRapduOdoLen = 4;
|
|
}
|
|
}
|
|
|
|
if(0U != (wTxDataLen))
|
|
{
|
|
/* Get FSD from PAL */
|
|
PH_CHECK_SUCCESS_FCT(status, phpalI14443p4mC_GetConfig(
|
|
pDataParams->pPalI14443p4mCDataParams,
|
|
PHPAL_I14443P4MC_CONFIG_FSD,
|
|
&wFsd));
|
|
|
|
/* Decrement PCB length (1 byte) from frame size */
|
|
wFsd--;
|
|
|
|
/* Check if CID is present */
|
|
PH_CHECK_SUCCESS_FCT(status, phpalI14443p4mC_GetConfig(
|
|
pDataParams->pPalI14443p4mCDataParams,
|
|
PHPAL_I14443P4MC_CONFIG_CID_PRESENCE,
|
|
&wCidPresence));
|
|
|
|
/* Decrement CID length (1 byte) from frame size if present */
|
|
if(0U != (wCidPresence))
|
|
{
|
|
wFsd--;
|
|
}
|
|
|
|
/* Check if NAD is present */
|
|
PH_CHECK_SUCCESS_FCT(status, phpalI14443p4mC_GetConfig(
|
|
pDataParams->pPalI14443p4mCDataParams,
|
|
PHPAL_I14443P4MC_CONFIG_NAD_PRESENCE,
|
|
&wNadPresence));
|
|
|
|
/* The content data is encapsulated in a DDO method */
|
|
if((pDataParams->bVno == PHCE_T4T_NDEF_SUPPORTED_VNO) && (pRxData[1] == 0xB1))
|
|
{
|
|
PH_CHECK_SUCCESS_FCT(status, phpalI14443p4mC_Transmit(
|
|
pDataParams->pPalI14443p4mCDataParams,
|
|
PH_TRANSMIT_BUFFER_FIRST,
|
|
aRapduOdo,
|
|
bRapduOdoLen));
|
|
}
|
|
|
|
/* Calculate Data length to be send with TXCHAINING option */
|
|
wTxChainingLen = (wFsd * (((((wTxDataLen + 2U + wNadPresence) % wFsd) == 0U)?
|
|
(((wTxDataLen + 2U + wNadPresence) / wFsd) - 1)
|
|
: ((wTxDataLen + 2U + wNadPresence) / wFsd)))) - wNadPresence;
|
|
|
|
/* Transmit first part of chain data */
|
|
if(0U != (wTxChainingLen))
|
|
{
|
|
PH_CHECK_SUCCESS_FCT(status, phpalI14443p4mC_Transmit(
|
|
pDataParams->pPalI14443p4mCDataParams,
|
|
PH_TRANSMIT_TXCHAINING,
|
|
pTxData,
|
|
(wTxChainingLen > wTxDataLen)? --wTxChainingLen : wTxChainingLen));
|
|
}
|
|
|
|
/* Buffer balance TX data */
|
|
if(wTxDataLen > wTxChainingLen)
|
|
{
|
|
if((pDataParams->bVno == PHCE_T4T_NDEF_SUPPORTED_VNO) && (pRxData[1] == 0xB1))
|
|
{
|
|
PH_CHECK_SUCCESS_FCT(status, phpalI14443p4mC_Transmit(
|
|
pDataParams->pPalI14443p4mCDataParams,
|
|
PH_TRANSMIT_BUFFER_CONT,
|
|
&pTxData[wTxChainingLen],
|
|
(wTxDataLen - wTxChainingLen)));
|
|
}
|
|
else
|
|
{
|
|
PH_CHECK_SUCCESS_FCT(status, phpalI14443p4mC_Transmit(
|
|
pDataParams->pPalI14443p4mCDataParams,
|
|
PH_TRANSMIT_BUFFER_FIRST,
|
|
&pTxData[wTxChainingLen],
|
|
(wTxDataLen - wTxChainingLen)));
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Copy Status word from data parameter for transmitting */
|
|
aSw[0] = (uint8_t)((pDataParams->wStatusWord & 0xFF00U) >> 8U);
|
|
aSw[1] = (uint8_t)(pDataParams->wStatusWord & 0xFFU);
|
|
|
|
/* Send status word */
|
|
PH_CHECK_SUCCESS_FCT(status, phpalI14443p4mC_Transmit(
|
|
pDataParams->pPalI14443p4mCDataParams,
|
|
PH_TRANSMIT_BUFFER_LAST,
|
|
aSw,
|
|
2));
|
|
}
|
|
else
|
|
{
|
|
/* Error from lower layer or DESELECTED, return back to application */
|
|
bExitLoop = TRUE;
|
|
}
|
|
}
|
|
|
|
return status;
|
|
#endif /* _WIN32 */
|
|
#ifdef _WIN32
|
|
PH_UNUSED_VARIABLE(pDataParams);
|
|
return (PH_ERR_UNSUPPORTED_COMMAND | PH_COMP_CE_T4T);
|
|
#endif /* _WIN32 */
|
|
}
|
|
|
|
void phceT4T_Sw_Int_UpdateFile(
|
|
phceT4T_Sw_DataParams_t *pDataParams,
|
|
uint8_t *pData,
|
|
uint32_t dwDataLen
|
|
)
|
|
{
|
|
/* Update File */
|
|
(void)memcpy(
|
|
&pDataParams->pSelectedFile[pDataParams->dwFileOffset],
|
|
pData,
|
|
dwDataLen);
|
|
|
|
/* Update file offset */
|
|
pDataParams->dwFileOffset += dwDataLen;
|
|
}
|
|
|
|
#endif /* NXPBUILD__PHCE_T4T_SW */
|