Files
NxpNfcRdLib/.svn/pristine/0b/0ba8983d08b6e285f3aca5370561bb4d763a010e.svn-base
2024-07-08 21:03:06 +08:00

1495 lines
48 KiB
Plaintext

/*----------------------------------------------------------------------------*/
/* Copyright 2016-2023 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
* Internal functions for Tag Operation Application Layer Component of
* Reader Library Framework.
* $Author$
* $Revision$ (v07.10.00)
* $Date$
*/
#include <ph_TypeDefs.h>
#include <ph_Status.h>
#include <ph_RefDefs.h>
#include <phNxpNfcRdLib_Config.h>
#include <phalT1T.h>
#include <phalTop.h>
#ifdef NXPBUILD__PHAL_TOP_SW
#ifdef NXPBUILD__PHAL_TOP_T1T_SW
#include "phalTop_Sw_Int_T1T.h"
static void phMemCpy(void* dest, void* src, uint16_t wLength);
phStatus_t phalTop_Sw_Int_T1T_SetReadOnly(
phalTop_Sw_DataParams_t * pDataParams
)
{
phStatus_t PH_MEMLOC_REM status;
uint8_t PH_MEMLOC_BUF aRxData[11];
uint16_t PH_MEMLOC_REM wRxLength = 0;
uint16_t PH_MEMLOC_COUNT wIndex;
uint16_t PH_MEMLOC_COUNT wTempIndex;
uint16_t PH_MEMLOC_COUNT wLockCtrlTlvSize;
phalTop_T1T_t PH_MEMLOC_REM * pT1T = &pDataParams->ualTop.salTop_T1T;
if((pDataParams->pTopTagsDataParams[pDataParams->bTagType - 1U]) != NULL)
{
pT1T->pAlT1TDataParams = pDataParams->pTopTagsDataParams[pDataParams->bTagType - 1U];
}
else
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_USE_CONDITION, PH_COMP_AL_TOP);
}
/* Check if tag is in valid state */
if(pDataParams->bTagState == PHAL_TOP_STATE_NONE)
{
return PH_ADD_COMPCODE_FIXED(PHAL_TOP_ERR_INVALID_STATE, PH_COMP_AL_TOP);
}
/* Check for NDEF length > 0 (in initialized state NDEF length is 0) */
if(pDataParams->bTagState == PHAL_TOP_STATE_INITIALIZED)
{
return PH_ADD_COMPCODE_FIXED(PHAL_TOP_ERR_EMPTY_NDEF, PH_COMP_AL_TOP);
}
/* Check if tag is already in read-only state */
if(pDataParams->bTagState == PHAL_TOP_STATE_READONLY)
{
return PH_ADD_COMPCODE_FIXED(PHAL_TOP_ERR_READONLY_TAG, PH_COMP_AL_TOP);
}
/* Update RW access */
pT1T->bRwa = PHAL_TOP_T1T_CC_RWA_RO;
/* Write Read/Write access byte*/
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteEraseByte(
pT1T->pAlT1TDataParams,
pT1T->bUid,
PHAL_TOP_T1T_BLOCK_RWA,
pT1T->bRwa,
aRxData,
&wRxLength));
/* Update Lock-0 */
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteNoEraseByte(
pT1T->pAlT1TDataParams,
pT1T->bUid,
PHAL_TOP_T1T_BLOCK_LOCK0,
0xFF,
aRxData,
&wRxLength));
/* Update Lock-1 */
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteNoEraseByte(
pT1T->pAlT1TDataParams,
pT1T->bUid,
PHAL_TOP_T1T_BLOCK_LOCK1,
0xFF,
aRxData,
&wRxLength));
/* Update dynamic lock bytes */
for(wIndex = 0; wIndex < pT1T->bLockTlvCount; wIndex++)
{
wLockCtrlTlvSize = (((uint16_t)(pT1T->asLockCtrlTlv[wIndex].bSizeInBits)) / 8U);
for(wTempIndex = 0; wTempIndex < wLockCtrlTlvSize; wTempIndex++)
{
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteNoEraseByte(
pT1T->pAlT1TDataParams,
pT1T->bUid,
(uint8_t)(pT1T->asLockCtrlTlv[wIndex].wByteAddr + wTempIndex),
0xFF,
aRxData,
&wRxLength));
}
if(0u != ((pT1T->asLockCtrlTlv[wIndex].bSizeInBits) % 8U))
{
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteNoEraseByte(
pT1T->pAlT1TDataParams,
pT1T->bUid,
(uint8_t)(pT1T->asLockCtrlTlv[wIndex].wByteAddr + wTempIndex),
0xFF,
aRxData,
&wRxLength));
}
}
pDataParams->bTagState = PHAL_TOP_STATE_READONLY;
return PH_ERR_SUCCESS;
}
void phalTop_Sw_Int_T1T_CalculateMaxNdefSize(
phalTop_Sw_DataParams_t * pDataParams,
phalTop_T1T_t * pT1T
)
{
uint16_t PH_MEMLOC_COUNT wIndex;
uint16_t PH_MEMLOC_REM wTagSize;
if(pT1T->bTagMemoryType == PHAL_TOP_T1T_TAG_MEMORY_TYPE_STATIC)
{
pDataParams->dwMaxNdefLength = 90;
}
else
{
/* Reset max. NDEF length */
pDataParams->dwMaxNdefLength = 0;
/* Calculate total tag size including lock and reserved bytes */
{
uint16_t wTms = 0;
wTms = pT1T->bTms;
wTagSize = (wTms + 1U) * 8U;
}
/* Calculate NDEF Header Address */
if((pT1T->bLockTlvCount !=0U) && (pT1T->bMemoryTlvCount != 0U))
{
pT1T->wNdefHeaderAddr = ((pT1T->asLockCtrlTlv[pT1T->bLockTlvCount - 1U].wOffset >
pT1T->asMemCtrlTlv[pT1T->bMemoryTlvCount - 1U].wOffset)?
pT1T->asLockCtrlTlv[pT1T->bLockTlvCount - 1U].wOffset:
((pT1T->asMemCtrlTlv[pT1T->bMemoryTlvCount - 1U].wOffset) + 5U));
}
else if(pT1T->bLockTlvCount !=0U)
{
pT1T->wNdefHeaderAddr = pT1T->asLockCtrlTlv[pT1T->bLockTlvCount - 1U].wOffset + 5U;
}
else if(pT1T->bMemoryTlvCount != 0U)
{
pT1T->wNdefHeaderAddr = pT1T->asMemCtrlTlv[pT1T->bMemoryTlvCount - 1U].wOffset + 5U;
}
else
{
pT1T->wNdefHeaderAddr = 12;
}
/* Calculate max. NDEF TLV length */
for(wIndex = pT1T->wNdefHeaderAddr; wIndex < wTagSize; wIndex++)
{
/* Update Lock/Reserved/OTP block status when segment changes */
if((wIndex % PHAL_TOP_T1T_SEGMENT_SIZE) == 0U)
{
pT1T->sSegment.bAddress = (uint8_t)(wIndex / PHAL_TOP_T1T_SEGMENT_SIZE);
(void)phalTop_Sw_Int_T1T_UpdateLockReservedOtp(pT1T);
}
/* Increment max. NDEF length if not lock/OTP/reserved byte */
if(0u != (phalTop_Sw_Int_T1T_CheckLockReservedOtp(pT1T, wIndex)))
{
pDataParams->dwMaxNdefLength++;
}
}
/* Subtract T and L field length to get NDEF message (V field) length */
if(pDataParams->dwMaxNdefLength < 0xFFU)
{
pDataParams->dwMaxNdefLength -= 2u;
}
else
{
pDataParams->dwMaxNdefLength -= 4u;
}
}
}
phStatus_t phalTop_Sw_Int_T1T_UpdateLockReservedOtp(
phalTop_T1T_t * pT1T
)
{
uint16_t PH_MEMLOC_COUNT wOffset;
uint16_t PH_MEMLOC_COUNT wIndex;
uint16_t PH_MEMLOC_REM wSegmentOffset;
uint16_t PH_MEMLOC_REM wLockCtrlTlvSize;
(void)memset(pT1T->sSegment.bLockReservedOtp, 0, 16);
if(pT1T->sSegment.bAddress == 0U)
{
pT1T->sSegment.bLockReservedOtp[0x00] = 0xFF;
pT1T->sSegment.bLockReservedOtp[0x0D] = 0xFF;
pT1T->sSegment.bLockReservedOtp[0x0E] = 0xFF;
pT1T->sSegment.bLockReservedOtp[0x0F] = 0xFF;
}
else
{
/* Update Lock Bytes */
for(wIndex = 0; wIndex < pT1T->bLockTlvCount; wIndex++)
{
if((pT1T->asLockCtrlTlv[wIndex].wByteAddr / PHAL_TOP_T1T_SEGMENT_SIZE) == pT1T->sSegment.bAddress)
{
wSegmentOffset = pT1T->asLockCtrlTlv[wIndex].wByteAddr % PHAL_TOP_T1T_SEGMENT_SIZE;
wLockCtrlTlvSize = (((uint16_t)(pT1T->asLockCtrlTlv[wIndex].bSizeInBits)) / 8U);
for(wOffset = wSegmentOffset;
wOffset < (wSegmentOffset + wLockCtrlTlvSize);
wOffset++)
{
pT1T->sSegment.bLockReservedOtp[wOffset / 8U] |=
(uint8_t)(1U << (wOffset % 8U));
}
}
}
/* Update Memory Bytes */
for(wIndex = 0; wIndex < pT1T->bMemoryTlvCount; wIndex++)
{
if((pT1T->asMemCtrlTlv[wIndex].wByteAddr / PHAL_TOP_T1T_SEGMENT_SIZE) == (pT1T->sSegment.bAddress))
{
wSegmentOffset = pT1T->asMemCtrlTlv[wIndex].wByteAddr % PHAL_TOP_T1T_SEGMENT_SIZE;
for(wOffset = wSegmentOffset;
wOffset < (wSegmentOffset + (pT1T->asMemCtrlTlv[wIndex].bSizeInBytes));
wOffset++)
{
pT1T->sSegment.bLockReservedOtp[wOffset / 8U] |= (uint8_t)(1U << (wOffset % 8U));
}
}
}
}
return PH_ERR_SUCCESS;
}
uint8_t phalTop_Sw_Int_T1T_CheckLockReservedOtp(
phalTop_T1T_t * pT1T,
uint16_t wIndex
)
{
if((pT1T->sSegment.bLockReservedOtp[(wIndex % PHAL_TOP_T1T_SEGMENT_SIZE) / 8U] != 0U) && (((1U << (wIndex % 8U)) != 0U)))
{
/* Lock/Reserved/OTP block */
return PH_OFF;
}
else
{
/* Data block */
return PH_ON;
}
}
phStatus_t phalTop_Sw_Int_T1T_Read(
phalTop_T1T_t * pT1T,
uint16_t wAddress,
uint8_t * pData,
uint8_t bFreshRead
)
{
phStatus_t PH_MEMLOC_REM status;
uint16_t PH_MEMLOC_REM wLength;
uint8_t PH_MEMLOC_REM * pRxData = NULL;
if(pT1T->bTagMemoryType != PHAL_TOP_T1T_TAG_MEMORY_TYPE_STATIC)
{
if(bFreshRead == PH_ON)
{
/* Get segment address */
pT1T->sSegment.bAddress = (uint8_t)(wAddress / PHAL_TOP_T1T_SEGMENT_SIZE);
/* Read segment */
PH_CHECK_SUCCESS_FCT(status, phalT1T_ReadSegment(
pT1T->pAlT1TDataParams,
pT1T->bUid,
(uint8_t)((pT1T->sSegment.bAddress << 4U) & 0xF0U),
&pRxData,
&wLength));
/* Remove ADDS */
pT1T->sSegment.pData = pRxData + 1U;
}
(*pData) = pT1T->sSegment.pData[(wAddress % PHAL_TOP_T1T_SEGMENT_SIZE)];
}
else
{
if(bFreshRead == PH_ON)
{
/* First segment */
pT1T->sSegment.bAddress = 0;
/* Read first segment */
PH_CHECK_SUCCESS_FCT(status, phalT1T_ReadAll(
pT1T->pAlT1TDataParams,
pT1T->bUid,
&pRxData,
&wLength));
/* Remove HR0 and HR1 */
pT1T->sSegment.pData = pRxData + 2U;
}
*pData = pT1T->sSegment.pData[wAddress];
}
return PH_ERR_SUCCESS;
}
phStatus_t phalTop_Sw_Int_T1T_Write(
phalTop_Sw_DataParams_t * pDataParams,
phalTop_T1T_t * pT1T,
uint16_t wAddress,
uint8_t * pData,
uint16_t pDataIndex
)
{
phStatus_t PH_MEMLOC_REM status;
uint8_t PH_MEMLOC_BUF aRxData[11];
uint8_t PH_MEMLOC_BUF aTempData[11];
uint16_t PH_MEMLOC_REM wRxLength = 0;
uint8_t PH_MEMLOC_REM bFirstBlock = 0;
uint8_t PH_MEMLOC_REM bLastBlock = 0;
uint8_t PH_MEMLOC_BUF bIndex = 0;
if(pT1T->bTagMemoryType != PHAL_TOP_T1T_TAG_MEMORY_TYPE_STATIC)
{
if((wAddress % 8U) == 0U)
{
if((pDataIndex + 8U) <= pDataParams->dwNdefLength)
{
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteEraseBlock(
pT1T->pAlT1TDataParams,
pT1T->bUid,
(uint8_t)(wAddress / 8U),
&pData[pDataIndex],
aRxData,
&wRxLength));
}
else
{
/* If Last block of NDEF message is less than 8 bytes, write
* byte by byte */
bLastBlock = 1;
}
}
if(((pT1T->wNdefMsgAddr % 8U) != 0U) && (pT1T->wNdefMsgAddr == wAddress))
{
/* If First block of NDEF message is not starting from start of a
* block, write byte by byte. */
bFirstBlock = 1;
}
}
else
{
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteEraseByte(
pT1T->pAlT1TDataParams,
pT1T->bUid,
(uint8_t)wAddress,
pData[pDataIndex],
aRxData,
&wRxLength));
/* Write Terminator TLV, if enabled and space is available */
if((pT1T->bTerminatorTlvPresence == PH_ON) && ((pDataIndex + 1U) == pDataParams->dwNdefLength))
{
/* Loop is needed, if current byte address is Lock, Reserved Memory
* or OTP. Loop till we find data byte. */
for(bIndex = ((uint8_t)(wAddress + 1U)); bIndex < ((pT1T->bTms + 1U) * 8U); bIndex++)
{
if(0u != (phalTop_Sw_Int_T1T_CheckLockReservedOtp(pT1T, bIndex)))
{
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteEraseByte(
pT1T->pAlT1TDataParams,
pT1T->bUid,
bIndex,
0xFE,
aRxData,
&wRxLength));
break;
}
}
}
}
/* Write partially filled first block */
if(0U != (bFirstBlock))
{
PH_CHECK_SUCCESS_FCT(status, phalT1T_ReadBlock(
pT1T->pAlT1TDataParams,
pT1T->bUid,
(uint8_t)(wAddress / 8U),
aTempData,
&wRxLength));
phMemCpy(&aTempData[(wAddress % 8U) + 1U], &pData[pDataIndex], (8U - (wAddress % 8U)));
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteEraseBlock(
pT1T->pAlT1TDataParams,
pT1T->bUid,
(uint8_t)(wAddress / 8U),
&aTempData[1],
aRxData,
&wRxLength));
}
/* Write partially filled last block */
else if(0U != (bLastBlock))
{
(void)memset(aTempData, 0, 8);
phMemCpy(aTempData, &pData[pDataIndex], ((pDataParams->dwNdefLength) - pDataIndex));
/* Add terminator TLV, if enabled */
if(((pDataParams->dwNdefLength - pDataIndex) < 8U) && (pT1T->bTerminatorTlvPresence == PH_ON))
{
aTempData[(pDataParams->dwNdefLength - pDataIndex)] = 0xFE;
}
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteEraseBlock(
pT1T->pAlT1TDataParams,
pT1T->bUid,
(uint8_t)(wAddress / 8U),
aTempData,
aRxData,
&wRxLength));
/* Write terminator TLV, if enabled and space is available */
if(((pDataParams->dwNdefLength - pDataIndex) == 8U) && (pT1T->bTerminatorTlvPresence == PH_ON))
{
(void)memset(aTempData, 0, 8);
aTempData[0] = 0xFE;
/* Loop is needed, if current byte address is Lock, Reserved Memory
* or OTP. Loop till we find data byte. */
for(bIndex = ((uint8_t)((wAddress / 8U) + 1U)); (bIndex * 8U) < ((pT1T->bTms + 1U) * 8U); bIndex++)
{
if(0u != (phalTop_Sw_Int_T1T_CheckLockReservedOtp(pT1T, (((uint16_t)(bIndex)) * 8U))))
{
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteEraseBlock(
pT1T->pAlT1TDataParams,
pT1T->bUid,
bIndex,
aTempData,
aRxData,
&wRxLength));
}
}
}
}
else
{
return PH_ERR_SUCCESS; /* Do Nothing */
}
return PH_ERR_SUCCESS;
}
phStatus_t phalTop_Sw_Int_T1T_ClearState(
phalTop_Sw_DataParams_t * pDataParams,
phalTop_T1T_t * pT1T
)
{
/* Reset parameters */
pT1T->bLockTlvCount = 0;
pT1T->bRwa = 0;
pT1T->bTms = 0;
pDataParams->bVno = 0;
pT1T->bMemoryTlvCount = 0;
pT1T->bTagMemoryType = 0;
pDataParams->bTagState = 0;
pT1T->bTerminatorTlvPresence = 0;
pDataParams->dwMaxNdefLength = 0;
pT1T->wNdefHeaderAddr = 0;
pDataParams->dwNdefLength = 0;
pT1T->wNdefMsgAddr = 0;
pT1T->sSegment.bAddress = 0;
return PH_ERR_SUCCESS;
}
/* Finds the count and position of memory, lock and NDEF TLV */
phStatus_t phalTop_Sw_Int_T1T_DetectTlvBlocks(
phalTop_Sw_DataParams_t * pDataParams,
phalTop_T1T_t * pT1T
)
{
phStatus_t PH_MEMLOC_REM status;
uint16_t PH_MEMLOC_COUNT wIndex;
uint8_t PH_MEMLOC_REM bPageAddr;
uint8_t PH_MEMLOC_REM bByteOffset;
uint8_t PH_MEMLOC_REM bBytesPerPage;
uint8_t PH_MEMLOC_BUF aLength[3];
uint8_t PH_MEMLOC_REM bExitLoop = 0;
uint8_t PH_MEMLOC_BUF aData[1];
uint16_t PH_MEMLOC_REM wShift = 1;
/* Check for NDEF TLV is done only in first segment */
wIndex = PHAL_TOP_T1T_SEGMENT_START_INDEX;
/* Loop through first segment */
while(wIndex < PHAL_TOP_T1T_SEGMENT_END_INDEX)
{
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_Read(
pT1T,
wIndex,
aData,
PH_OFF));
switch(aData[0])
{
case PHAL_TOP_T1T_NULL_TLV:
break;
case PHAL_TOP_T1T_LOCK_CTRL_TLV:
if(pT1T->bLockTlvCount >= PHAL_TOP_T1T_MAX_LOCK_CTRL_TLV)
{
return PH_ADD_COMPCODE_FIXED(PHAL_TOP_ERR_UNSUPPORTED_TAG, PH_COMP_AL_TOP);
}
if(pT1T->bTagMemoryType != PHAL_TOP_T1T_TAG_MEMORY_TYPE_STATIC)
{
/* Read TLV length */
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_Read(
pT1T,
(wIndex + 1U),
aData,
PH_OFF));
/* Validate length */
if(aData[0] != 3U)
{
bExitLoop = 1;
break;
}
pT1T->asLockCtrlTlv[pT1T->bLockTlvCount].wOffset = wIndex;
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_Read(
pT1T,
(wIndex + 2U),
aData,
PH_OFF));
bPageAddr = (uint8_t)((aData[0] & 0xF0U) >> 4U);
bByteOffset = aData[0] & 0x0FU;
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_Read(
pT1T,
(wIndex + 3U),
aData,
PH_OFF));
pT1T->asLockCtrlTlv[pT1T->bLockTlvCount].bSizeInBits = aData[0];
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_Read(
pT1T,
(wIndex + 4U),
aData,
PH_OFF));
bBytesPerPage = aData[0] & 0x0FU;
pT1T->asLockCtrlTlv[pT1T->bLockTlvCount].bBytesPerPage = aData[0] & 0x0FU;
pT1T->asLockCtrlTlv[pT1T->bLockTlvCount].bBytesLockedPerBit = (uint8_t)((aData[0] & 0xF0U) >> 4U);
{
uint16_t wPageAddr = 0;
wPageAddr = bPageAddr;
wShift = 1U;
wPageAddr = (wPageAddr * (wShift << ((uint16_t)(bBytesPerPage))));
wPageAddr += bByteOffset;
pT1T->asLockCtrlTlv[pT1T->bLockTlvCount].wByteAddr = wPageAddr;
}
pT1T->bLockTlvCount++;
wIndex = wIndex + 4U;
}
break;
case PHAL_TOP_T1T_MEMORY_CTRL_TLV:
if(pT1T->bMemoryTlvCount >= PHAL_TOP_T1T_MAX_MEM_CTRL_TLV)
{
return PH_ADD_COMPCODE_FIXED(PHAL_TOP_ERR_UNSUPPORTED_TAG, PH_COMP_AL_TOP);
}
if(pT1T->bTagMemoryType != PHAL_TOP_T1T_TAG_MEMORY_TYPE_STATIC)
{
/* Read TLV length */
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_Read(
pT1T,
(wIndex + 1U),
aData,
PH_OFF));
/* Validate length */
if(aData[0] != 3U)
{
bExitLoop = 1;
break;
}
pT1T->asMemCtrlTlv[pT1T->bMemoryTlvCount].wOffset = wIndex;
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_Read(
pT1T,
(wIndex + 2U),
aData,
PH_OFF));
bPageAddr = (uint8_t)((aData[0] & 0xF0U) >> 4U);
bByteOffset = (uint8_t)(aData[0] & 0x0FU);
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_Read(
pT1T,
(wIndex + 3U),
aData,
PH_OFF));
pT1T->asMemCtrlTlv[pT1T->bMemoryTlvCount].bSizeInBytes = aData[0];
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_Read(
pT1T,
(wIndex + 4U),
aData,
PH_OFF));
bBytesPerPage = aData[0] & 0x0FU;
pT1T->asMemCtrlTlv[pT1T->bMemoryTlvCount].bBytesPerPage = aData[0] & 0x0FU;
{
uint16_t wByteAddress = 0;
wShift = 1U;
wByteAddress = (uint16_t)bPageAddr;
wByteAddress = (wByteAddress * (wShift << ((uint16_t)(bBytesPerPage))));
wByteAddress = wByteAddress + bByteOffset;
pT1T->asMemCtrlTlv[pT1T->bMemoryTlvCount].wByteAddr = wByteAddress;
}
pT1T->bMemoryTlvCount++;
wIndex = wIndex + 4U;
}
break;
case PHAL_TOP_T1T_NDEF_TLV:
pT1T->wNdefHeaderAddr = wIndex;
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_Read(
pT1T,
(wIndex + 1U),
aData,
PH_OFF));
aLength[0] = aData[0];
if(aLength[0] == 0xFFU)
{
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_Read(
pT1T,
(wIndex + 2U),
aData,
PH_OFF));
aLength[1] = aData[0];
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_Read(
pT1T,
(wIndex + 3U),
aData,
PH_OFF));
aLength[2] = aData[0];
pDataParams->dwNdefLength = ((uint16_t)aLength[1] << 8U) | aLength[2];
pT1T->wNdefMsgAddr = pT1T->wNdefHeaderAddr + 4U;
wIndex = wIndex + pDataParams->dwNdefLength + 3U;
}
else
{
pDataParams->dwNdefLength = aLength[0];
pT1T->wNdefMsgAddr = pT1T->wNdefHeaderAddr + 2U;
wIndex = wIndex + pDataParams->dwNdefLength + 1U;
}
bExitLoop = 1;
break;
case PHAL_TOP_T1T_PROPRIETARY_TLV:
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_Read(
pT1T,
(wIndex + 1U),
aData,
PH_OFF));
aLength[0] = aData[0];
if(aLength[0] == 0xFFU)
{
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_Read(
pT1T,
(wIndex + 2U),
aData,
PH_OFF));
aLength[1] = aData[0];
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_Read(
pT1T,
(wIndex + 3U),
aData, PH_OFF));
aLength[2] = aData[0];
wIndex = wIndex + (((uint16_t)aLength[1] << 8U) | aLength[2]) + 3U;
}
else
{
wIndex = wIndex + aLength[0] + 1U;
}
break;
case PHAL_TOP_T1T_TERMINATOR_TLV:
pT1T->bTerminatorTlvPresence = PH_ON;
bExitLoop = 1;
break;
default:
bExitLoop = 1;
break;
}
if (0U != (bExitLoop))
{
break;
}
wIndex++;
}
return PH_ERR_SUCCESS;
}
phStatus_t phalTop_Sw_Int_T1T_CheckNdef(
phalTop_Sw_DataParams_t * pDataParams,
uint8_t * pTagState
)
{
phStatus_t PH_MEMLOC_REM status;
uint8_t PH_MEMLOC_REM aData[1] = {0};
phalTop_T1T_t PH_MEMLOC_REM * pT1T = &pDataParams->ualTop.salTop_T1T;
if((pDataParams->pTopTagsDataParams[pDataParams->bTagType - 1U]) != NULL)
{
pT1T->pAlT1TDataParams = pDataParams->pTopTagsDataParams[pDataParams->bTagType - 1U];
}
else
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_USE_CONDITION, PH_COMP_AL_TOP);
}
/* Update UID */
(void)memcpy(pT1T->bUid, ((phalT1T_Sw_DataParams_t *)(pT1T->pAlT1TDataParams))->abUid, 4);
/* Reset tag state */
*pTagState = PHAL_TOP_STATE_NONE;
/* Clear values from previous detection, if any */
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_ClearState(pDataParams, pT1T));
/* Check for NDEF support */
if((((phalT1T_Sw_DataParams_t *)(pT1T->pAlT1TDataParams))->abHR[0] & 0x10U) != 0x10U)
{
return PH_ADD_COMPCODE_FIXED(PHAL_TOP_ERR_NON_NDEF_TAG, PH_COMP_AL_TOP);
}
/* Check for memory type */
if((((phalT1T_Sw_DataParams_t *)(pT1T->pAlT1TDataParams))->abHR[0] & 0x01U) == 0x01U)
{
pT1T->bTagMemoryType = PHAL_TOP_T1T_TAG_MEMORY_TYPE_STATIC;
}
else
{
pT1T->bTagMemoryType = PHAL_TOP_T1T_TAG_MEMORY_TYPE_DYNAMIC;
}
/* Read NDEF Magic Number (NMN) */
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_Read(
pT1T,
PHAL_TOP_T1T_CC_NMN_ADDR,
aData,
PH_ON));
/* Validate NMN */
if(aData[0] != PHAL_TOP_T1T_NDEF_NMN)
{
return PH_ADD_COMPCODE_FIXED(PHAL_TOP_ERR_NON_NDEF_TAG, PH_COMP_AL_TOP);
}
/* Read version number */
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_Read(
pT1T,
PHAL_TOP_T1T_CC_VNO_ADDR,
aData,
PH_OFF));
/* Update version */
pDataParams->bVno = aData[0];
/* Validate if version is supported */
if((uint8_t)(pDataParams->bVno & 0xF0U) > (uint8_t)(PHAL_TOP_T1T_NDEF_SUPPORTED_VNO & 0xF0U))
{
return PH_ADD_COMPCODE_FIXED(PHAL_TOP_ERR_UNSUPPORTED_VERSION, PH_COMP_AL_TOP);
}
/* Read TMS */
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_Read(
pT1T,
PHAL_TOP_T1T_CC_TMS_ADDR,
aData,
PH_OFF));
/* Update TMS */
pT1T->bTms = aData[0];
/* Validate TMS */
if(pT1T->bTms < 0x0EU)
{
return PH_ADD_COMPCODE_FIXED(PHAL_TOP_ERR_MISCONFIGURED_TAG, PH_COMP_AL_TOP);
}
/* Validate TMS and Tag Memory Type */
if(((pT1T->bTms == 0x0EU) && (pT1T->bTagMemoryType != PHAL_TOP_T1T_TAG_MEMORY_TYPE_STATIC)) ||
((pT1T->bTms > 0x0EU) && (pT1T->bTagMemoryType != PHAL_TOP_T1T_TAG_MEMORY_TYPE_DYNAMIC)))
{
return PH_ADD_COMPCODE_FIXED(PHAL_TOP_ERR_MISCONFIGURED_TAG, PH_COMP_AL_TOP);
}
/* Read R/W access */
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_Read(
pT1T,
PHAL_TOP_T1T_CC_RWA_ADDR,
aData,
PH_OFF));
/* Update read/write access */
pT1T->bRwa = aData[0];
/* Validate read/write access */
if((pT1T->bRwa != PHAL_TOP_T1T_CC_RWA_RW) && (pT1T->bRwa != PHAL_TOP_T1T_CC_RWA_RO))
{
/* RFU/Proprietary options; Not supported */
return PH_ADD_COMPCODE_FIXED(PHAL_TOP_ERR_UNSUPPORTED_TAG, PH_COMP_AL_TOP);
}
/* Detect TLVs */
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_DetectTlvBlocks(pDataParams, pT1T));
if((pT1T->wNdefHeaderAddr != 0U) && (pDataParams->dwNdefLength != 0U))
{
if(pT1T->bRwa == PHAL_TOP_T1T_CC_RWA_RW)
{
pDataParams->bTagState = PHAL_TOP_STATE_READWRITE;
}
else
{
/* NOTE: Lock bytes status are not checked. */
pDataParams->bTagState = PHAL_TOP_STATE_READONLY;
}
}
else
{
/* If dynamic memory; check for lock and memory TLVs */
if((pT1T->bTagMemoryType == PHAL_TOP_T1T_TAG_MEMORY_TYPE_DYNAMIC) &&
((pT1T->bLockTlvCount == 0U) || (pT1T->bMemoryTlvCount == 0U)))
{
return PH_ADD_COMPCODE_FIXED(PHAL_TOP_ERR_MISCONFIGURED_TAG, PH_COMP_AL_TOP);
}
pDataParams->bTagState = PHAL_TOP_STATE_INITIALIZED;
}
/* Update max. NDEF size */
phalTop_Sw_Int_T1T_CalculateMaxNdefSize(pDataParams, pT1T);
/* Update reserved/lock bytes status for first sector */
pT1T->sSegment.bAddress = 0;
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_UpdateLockReservedOtp(pT1T));
/* Update state in out parameter */
*pTagState = pDataParams->bTagState;
return PH_ERR_SUCCESS;
}
phStatus_t phalTop_Sw_Int_T1T_FormatNdef(
phalTop_Sw_DataParams_t * pDataParams
)
{
phStatus_t PH_MEMLOC_REM status;
uint8_t PH_MEMLOC_BUF aRxData[11];
uint16_t PH_MEMLOC_REM wRxLength = 0;
uint16_t PH_MEMLOC_COUNT wIndex;
uint16_t PH_MEMLOC_COUNT wWriteIndex;
uint8_t PH_MEMLOC_BUF aTlv[5];
uint8_t PH_MEMLOC_BUF aNdefData[3] = {0xD0, 0x00, 0x00};
uint16_t PH_MEMLOC_BUF wShift = 1;
phalTop_T1T_t PH_MEMLOC_REM * pT1T = &pDataParams->ualTop.salTop_T1T;
if((pDataParams->pTopTagsDataParams[pDataParams->bTagType - 1U]) != NULL)
{
pT1T->pAlT1TDataParams = pDataParams->pTopTagsDataParams[pDataParams->bTagType - 1U];
}
else
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_USE_CONDITION, PH_COMP_AL_TOP);
}
/* Check for NDEF support */
if((((phalT1T_Sw_DataParams_t *)(pT1T->pAlT1TDataParams))->abHR[0] & 0x10U) != 0x10U)
{
return PH_ADD_COMPCODE_FIXED(PHAL_TOP_ERR_UNSUPPORTED_TAG, PH_COMP_AL_TOP);
}
/* Check for NDEF presence */
if(pDataParams->bTagState != PHAL_TOP_STATE_NONE)
{
return PH_ADD_COMPCODE_FIXED(PHAL_TOP_ERR_FORMATTED_TAG, PH_COMP_AL_TOP);
}
/* If TMS is not configured, use default configuration */
if(pT1T->bTms < 0x0EU)
{
/* Check for memory type */
if((((phalT1T_Sw_DataParams_t *)(pT1T->pAlT1TDataParams))->abHR[0] & 0x01U) == 0x01U)
{
/* Topaz96 */
pT1T->bTms = 0x0E;
}
else
{
/* Topaz512 */
pT1T->bTms = 0x3F;
}
}
/* Set R/W access */
pT1T->bRwa = PHAL_TOP_T1T_CC_RWA_RW;
/* Set version number */
pDataParams->bVno = PHAL_TOP_T1T_NDEF_SUPPORTED_VNO;
/* Write NDEF Magic Number */
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteEraseByte(
pT1T->pAlT1TDataParams,
pT1T->bUid,
PHAL_TOP_T1T_BLOCK_NMN,
PHAL_TOP_T1T_NDEF_NMN,
aRxData,
&wRxLength));
/* Write NDEF version number */
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteEraseByte(
pT1T->pAlT1TDataParams,
pT1T->bUid,
PHAL_TOP_T1T_BLOCK_VNO,
pDataParams->bVno,
aRxData,
&wRxLength));
/* Write TMS byte*/
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteEraseByte(
pT1T->pAlT1TDataParams,
pT1T->bUid,
PHAL_TOP_T1T_BLOCK_TMS,
pT1T->bTms,
aRxData,
&wRxLength));
/* Write Read/Write access byte*/
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteEraseByte(
pT1T->pAlT1TDataParams,
pT1T->bUid,
PHAL_TOP_T1T_BLOCK_RWA,
pT1T->bRwa,
aRxData,
&wRxLength));
/* Update memory type */
if((((phalT1T_Sw_DataParams_t *)(pT1T->pAlT1TDataParams))->abHR[0] & 0x01U) == 0x01U)
{
pT1T->bTagMemoryType = PHAL_TOP_T1T_TAG_MEMORY_TYPE_STATIC;
}
else
{
pT1T->bTagMemoryType = PHAL_TOP_T1T_TAG_MEMORY_TYPE_DYNAMIC;
/* Update default Lock control TLVs (for Topaz512) */
if(pT1T->bLockTlvCount == 0U)
{
/* Update Lock TLVs (default for Topaz512) */
pT1T->bLockTlvCount = 1;
pT1T->asLockCtrlTlv[0].wOffset = 0x0C;
pT1T->asLockCtrlTlv[0].wByteAddr = 0x7A;
pT1T->asLockCtrlTlv[0].bBytesLockedPerBit = 0x03;
pT1T->asLockCtrlTlv[0].bBytesPerPage = 0x03;
pT1T->asLockCtrlTlv[0].bSizeInBits = 0x30;
}
/* Update Memory control TLVs (for Topaz512) */
if(pT1T->bMemoryTlvCount == 0U)
{
/* Update Memory TLVs (default for Topaz512) */
pT1T->bMemoryTlvCount = 1;
pT1T->asMemCtrlTlv[0].wOffset = 0x11;
pT1T->asMemCtrlTlv[0].wByteAddr = 0x78;
pT1T->asMemCtrlTlv[0].bBytesPerPage = 0x03;
pT1T->asMemCtrlTlv[0].bSizeInBytes = 0x02;
}
}
/* Write lock control TLVs */
for(wIndex = 0;
((wIndex < pT1T->bLockTlvCount) && (wIndex < PHAL_TOP_T1T_MAX_LOCK_CTRL_TLV));
wIndex++)
{
/* Create lock TLVs */
aTlv[0] = 0x01;
aTlv[1] = 0x03;
{
uint16_t wBytesPage = 0;
wShift = 1U;
wBytesPage = (wShift << ((uint16_t)(pT1T->asLockCtrlTlv[wIndex].bBytesPerPage)));
aTlv[2] = (uint8_t)((uint16_t)(pT1T->asLockCtrlTlv[wIndex].wByteAddr / wBytesPage) << 4U) |
(uint8_t)(pT1T->asLockCtrlTlv[wIndex].wByteAddr % wBytesPage);
}
aTlv[3] = pT1T->asLockCtrlTlv[wIndex].bSizeInBits;
aTlv[4] = (pT1T->asLockCtrlTlv[wIndex].bBytesLockedPerBit << 4U) | pT1T->asLockCtrlTlv[wIndex].bBytesPerPage;
/* Write lock TLVs */
for(wWriteIndex = 0; wWriteIndex < 5U; wWriteIndex++)
{
/* Write byte */
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteEraseByte(
pT1T->pAlT1TDataParams,
pT1T->bUid,
(uint8_t)(pT1T->asLockCtrlTlv[wIndex].wOffset + wWriteIndex),
aTlv[wWriteIndex],
aRxData,
&wRxLength));
}
}
/* Write memory control TLVs */
for(wIndex = 0;
((wIndex < pT1T->bMemoryTlvCount) && (wIndex < PHAL_TOP_T1T_MAX_MEM_CTRL_TLV));
wIndex++)
{
/* Create memory TLV */
aTlv[0] = 0x02;
aTlv[1] = 0x03;
{
uint16_t wBytesPerPage = 0;
wShift = 1U;
wBytesPerPage = (wShift << ((uint16_t)(pT1T->asMemCtrlTlv[wIndex].bBytesPerPage)));
aTlv[2] = (uint8_t)((uint16_t)(pT1T->asMemCtrlTlv[wIndex].wByteAddr / wBytesPerPage) << 4U) |
(uint8_t)(pT1T->asMemCtrlTlv[wIndex].wByteAddr % wBytesPerPage);
}
aTlv[3] = pT1T->asMemCtrlTlv[wIndex].bSizeInBytes;
aTlv[4] = pT1T->asMemCtrlTlv[wIndex].bBytesPerPage;
/* Write memory TLV */
for(wWriteIndex = 0; wWriteIndex < 5U; wWriteIndex++)
{
/* Write byte */
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteEraseByte(
pT1T->pAlT1TDataParams,
pT1T->bUid,
(uint8_t)(pT1T->asMemCtrlTlv[wIndex].wOffset + wWriteIndex),
aTlv[wWriteIndex],
aRxData,
&wRxLength));
}
}
/* Calculate NDEF header address */
if((pT1T->bLockTlvCount !=0U) && (pT1T->bMemoryTlvCount != 0U))
{
pT1T->wNdefHeaderAddr =
((pT1T->asLockCtrlTlv[pT1T->bLockTlvCount - 1U].wOffset >
pT1T->asMemCtrlTlv[pT1T->bMemoryTlvCount - 1U].wOffset) ?
pT1T->asLockCtrlTlv[pT1T->bLockTlvCount - 1U].wOffset :
pT1T->asMemCtrlTlv[pT1T->bMemoryTlvCount - 1U].wOffset) + 5U;
}
else if(pT1T->bLockTlvCount != 0U)
{
pT1T->wNdefHeaderAddr = pT1T->asLockCtrlTlv[pT1T->bLockTlvCount - 1U].wOffset + 5U;
}
else if(pT1T->bMemoryTlvCount != 0U)
{
pT1T->wNdefHeaderAddr = pT1T->asMemCtrlTlv[pT1T->bMemoryTlvCount - 1U].wOffset + 5U;
}
else
{
pT1T->wNdefHeaderAddr = 12;
}
pDataParams->dwNdefLength = 0;
pDataParams->bTagState = PHAL_TOP_STATE_INITIALIZED;
/* Update max. NDEF size */
phalTop_Sw_Int_T1T_CalculateMaxNdefSize(pDataParams, pT1T);
/* Write empty NDEF Message */
status = phalTop_Sw_Int_T1T_WriteNdef(pDataParams, aNdefData, 3);
if((status & PH_ERR_MASK) != PH_ERR_SUCCESS)
{
/* Reset state on error */
pDataParams->bTagState = PHAL_TOP_STATE_NONE;
pT1T->wNdefHeaderAddr = 0x00;
return status;
}
/* Update state and NDEF presence */
pDataParams->bTagState = PHAL_TOP_STATE_READWRITE;
pT1T->wNdefMsgAddr = pT1T->wNdefHeaderAddr + 2U;
pDataParams->dwNdefLength = 0x03;
return PH_ERR_SUCCESS;
}
phStatus_t phalTop_Sw_Int_T1T_EraseNdef(
phalTop_Sw_DataParams_t * pDataParams
)
{
phStatus_t PH_MEMLOC_REM status;
uint8_t PH_MEMLOC_REM aRxData[11];
uint16_t PH_MEMLOC_REM wRxLength = 0;
phalTop_T1T_t PH_MEMLOC_REM * pT1T = &pDataParams->ualTop.salTop_T1T;
if((pDataParams->pTopTagsDataParams[pDataParams->bTagType - 1U]) != NULL)
{
pT1T->pAlT1TDataParams = pDataParams->pTopTagsDataParams[pDataParams->bTagType - 1U];
}
else
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_USE_CONDITION, PH_COMP_AL_TOP);
}
/* Check if tag is in valid state */
if(pDataParams->bTagState == PHAL_TOP_STATE_NONE)
{
return PH_ADD_COMPCODE_FIXED(PHAL_TOP_ERR_INVALID_STATE, PH_COMP_AL_TOP);
}
/* Check if tag is read-only */
if(pDataParams->bTagState == PHAL_TOP_STATE_READONLY)
{
return PH_ADD_COMPCODE_FIXED(PHAL_TOP_ERR_READONLY_TAG, PH_COMP_AL_TOP);
}
/* Check if tag is already in initialized state */
if(pDataParams->bTagState == PHAL_TOP_STATE_INITIALIZED)
{
return PH_ADD_COMPCODE_FIXED(PHAL_TOP_ERR_EMPTY_NDEF, PH_COMP_AL_TOP);
}
/* Make NDEF length '0' */
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteEraseByte(
pT1T->pAlT1TDataParams,
pT1T->bUid,
(uint8_t)(pT1T->wNdefHeaderAddr + 1U),
0x00,
aRxData,
&wRxLength));
/* Update state */
pDataParams->bTagState = PHAL_TOP_STATE_INITIALIZED;
pDataParams->dwNdefLength = 0;
pT1T->wNdefMsgAddr = pT1T->wNdefHeaderAddr + 2U;
return PH_ERR_SUCCESS;
}
phStatus_t phalTop_Sw_Int_T1T_ReadNdef(
phalTop_Sw_DataParams_t * pDataParams,
uint8_t * pData,
uint32_t * pLength
)
{
phStatus_t PH_MEMLOC_REM status;
uint16_t PH_MEMLOC_COUNT wIndex;
uint16_t PH_MEMLOC_COUNT wTempIndex;
uint8_t PH_MEMLOC_BUF aData[1];
uint8_t PH_MEMLOC_REM bFreshRead;
phalTop_T1T_t PH_MEMLOC_REM * pT1T = &pDataParams->ualTop.salTop_T1T;
if((pDataParams->pTopTagsDataParams[pDataParams->bTagType - 1U]) != NULL)
{
pT1T->pAlT1TDataParams = pDataParams->pTopTagsDataParams[pDataParams->bTagType - 1U];
}
else
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_USE_CONDITION, PH_COMP_AL_TOP);
}
/* Reset NDEF length */
*pLength = 0;
/* Check if tag is in valid state */
if(pDataParams->bTagState == PHAL_TOP_STATE_NONE)
{
return PH_ADD_COMPCODE_FIXED(PHAL_TOP_ERR_INVALID_STATE, PH_COMP_AL_TOP);
}
/* Check for NDEF length > 0 (in initialized state NDEF length is 0) */
if(pDataParams->bTagState == PHAL_TOP_STATE_INITIALIZED)
{
return PH_ADD_COMPCODE_FIXED(PHAL_TOP_ERR_EMPTY_NDEF, PH_COMP_AL_TOP);
}
/* Buffer allocated by user is less than NDEF message size on Tag. */
if (pDataParams->dwNdefLength > PH_NXPNFCRDLIB_CONFIG_MAX_NDEF_DATA)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_BUFFER_OVERFLOW, PH_COMP_AL_TOP);
}
pT1T->sSegment.bAddress = (uint8_t)(pT1T->wNdefMsgAddr / PHAL_TOP_T1T_SEGMENT_SIZE);
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_UpdateLockReservedOtp(pT1T));
/* Do a fresh read of segment for one time */
bFreshRead = PH_ON;
wIndex = pT1T->wNdefMsgAddr;
wTempIndex = 0;
while(wTempIndex < pDataParams->dwNdefLength)
{
if(((wIndex / PHAL_TOP_T1T_SEGMENT_SIZE) != pT1T->sSegment.bAddress))
{
pT1T->sSegment.bAddress = (uint8_t)(wIndex / PHAL_TOP_T1T_SEGMENT_SIZE);
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_UpdateLockReservedOtp(pT1T));
/* Do a fresh read of segment for one time */
bFreshRead = PH_ON;
}
if(0u != (phalTop_Sw_Int_T1T_CheckLockReservedOtp(pT1T, wIndex)))
{
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_Read(
pT1T,
wIndex,
aData,
bFreshRead));
bFreshRead = PH_OFF;
pData[wTempIndex] = aData[0];
wTempIndex++;
}
wIndex++;
}
/* Update NDEF length */
*pLength = pDataParams->dwNdefLength;
return PH_ERR_SUCCESS;
}
phStatus_t phalTop_Sw_Int_T1T_WriteNdef(
phalTop_Sw_DataParams_t * pDataParams,
uint8_t * pData,
uint32_t dwLength
)
{
phStatus_t PH_MEMLOC_REM status;
uint8_t PH_MEMLOC_BUF aRxData[11];
uint16_t PH_MEMLOC_REM wRxLength = 0;
uint16_t PH_MEMLOC_COUNT wIndex;
uint32_t PH_MEMLOC_COUNT wTempIndex;
phalTop_T1T_t PH_MEMLOC_REM * pT1T = &pDataParams->ualTop.salTop_T1T;
if((pDataParams->pTopTagsDataParams[pDataParams->bTagType - 1U]) != NULL)
{
pT1T->pAlT1TDataParams = pDataParams->pTopTagsDataParams[pDataParams->bTagType - 1U];
}
else
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_USE_CONDITION, PH_COMP_AL_TOP);
}
/* Check if tag is in valid state */
if(pDataParams->bTagState == PHAL_TOP_STATE_NONE)
{
return PH_ADD_COMPCODE_FIXED(PHAL_TOP_ERR_INVALID_STATE, PH_COMP_AL_TOP);
}
/* Check if tag is read-only */
if(pDataParams->bTagState == PHAL_TOP_STATE_READONLY)
{
return PH_ADD_COMPCODE_FIXED(PHAL_TOP_ERR_READONLY_TAG, PH_COMP_AL_TOP);
}
/* Check NDEF length */
if((dwLength > pDataParams->dwMaxNdefLength) || (dwLength == 0U))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_AL_TOP);
}
/* Make NDEF Magic Number value '0' */
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteEraseByte(
pT1T->pAlT1TDataParams,
pT1T->bUid,
PHAL_TOP_T1T_BLOCK_NMN,
0x00,
aRxData,
&wRxLength));
/* Write NDEF version number */
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteEraseByte(
pT1T->pAlT1TDataParams,
pT1T->bUid,
PHAL_TOP_T1T_BLOCK_VNO,
PHAL_TOP_T1T_NDEF_SUPPORTED_VNO,
aRxData,
&wRxLength));
/* Write Read/Write access byte*/
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteEraseByte(
pT1T->pAlT1TDataParams,
pT1T->bUid,
PHAL_TOP_T1T_BLOCK_RWA,
pT1T->bRwa,
aRxData,
&wRxLength));
/* Calculate NDEF Header Address */
if((pT1T->bLockTlvCount !=0U) && (pT1T->bMemoryTlvCount != 0U))
{
pT1T->wNdefHeaderAddr = ((pT1T->asLockCtrlTlv[pT1T->bLockTlvCount - 1U].wOffset >
pT1T->asMemCtrlTlv[pT1T->bMemoryTlvCount - 1U].wOffset)?
(pT1T->asLockCtrlTlv[pT1T->bLockTlvCount - 1U].wOffset):
((pT1T->asMemCtrlTlv[pT1T->bMemoryTlvCount - 1U].wOffset) + 5U));
}
else if(pT1T->bLockTlvCount !=0U)
{
pT1T->wNdefHeaderAddr = pT1T->asLockCtrlTlv[pT1T->bLockTlvCount - 1U].wOffset + 5U;
}
else if(pT1T->bMemoryTlvCount != 0U)
{
pT1T->wNdefHeaderAddr = pT1T->asMemCtrlTlv[pT1T->bMemoryTlvCount - 1U].wOffset + 5U;
}
else
{
pT1T->wNdefHeaderAddr = 12;
}
/* Write NDEF TLV */
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteEraseByte(
pT1T->pAlT1TDataParams,
pT1T->bUid,
(uint8_t)pT1T->wNdefHeaderAddr,
PHAL_TOP_T1T_NDEF_TLV,
aRxData,
&wRxLength));
/* Write NDEF length */
if(dwLength > 0xFEU)
{
pT1T->wNdefMsgAddr = pT1T->wNdefHeaderAddr + 4U;
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteEraseByte(
pT1T->pAlT1TDataParams,
pT1T->bUid,
(uint8_t)(pT1T->wNdefHeaderAddr + 1U),
0xFF,
aRxData,
&wRxLength));
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteEraseByte(
pT1T->pAlT1TDataParams,
pT1T->bUid,
(uint8_t)(pT1T->wNdefHeaderAddr + 2U),
(uint8_t)(dwLength >> 8U),
aRxData,
&wRxLength));
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteEraseByte(
pT1T->pAlT1TDataParams,
pT1T->bUid,
(uint8_t)(pT1T->wNdefHeaderAddr + 3U),
(uint8_t)dwLength,
aRxData,
&wRxLength));
}
else
{
pT1T->wNdefMsgAddr = pT1T->wNdefHeaderAddr + 2U;
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteEraseByte(
pT1T->pAlT1TDataParams,
pT1T->bUid,
(uint8_t)(pT1T->wNdefHeaderAddr + 1U),
(uint8_t)dwLength,
aRxData,
&wRxLength));
}
/* Update NDEF Length */
pDataParams->dwNdefLength = dwLength;
/* Update Lock/Reserved/OTP presence */
pT1T->sSegment.bAddress = (uint8_t)(pT1T->wNdefMsgAddr / PHAL_TOP_T1T_SEGMENT_SIZE);
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_UpdateLockReservedOtp(pT1T));
/* Write NDEF data */
wIndex = pT1T->wNdefMsgAddr;
wTempIndex = 0;
while(wTempIndex < (pDataParams->dwNdefLength))
{
if((wIndex/PHAL_TOP_T1T_SEGMENT_SIZE) != pT1T->sSegment.bAddress)
{
pT1T->sSegment.bAddress = (uint8_t)(wIndex / PHAL_TOP_T1T_SEGMENT_SIZE);
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_UpdateLockReservedOtp(pT1T));
}
if(0u != (phalTop_Sw_Int_T1T_CheckLockReservedOtp(pT1T, wIndex)))
{
PH_CHECK_SUCCESS_FCT(status, phalTop_Sw_Int_T1T_Write(
pDataParams,
pT1T,
wIndex,
pData,
(uint16_t)wTempIndex));
wTempIndex++;
}
wIndex++;
}
/* Write NDEF Magic Number */
PH_CHECK_SUCCESS_FCT(status, phalT1T_WriteEraseByte(
pT1T->pAlT1TDataParams,
pT1T->bUid,
PHAL_TOP_T1T_BLOCK_NMN,
PHAL_TOP_T1T_NDEF_NMN,
aRxData,
&wRxLength));
pDataParams->bTagState = PHAL_TOP_STATE_READWRITE;
return PH_ERR_SUCCESS;
}
static void phMemCpy(void* dest, void* src, uint16_t wLength)
{
uint32_t dwLength = 0;
dwLength = wLength;
(void)memcpy(dest, src, dwLength);
}
#endif /* NXPBUILD__PHAL_TOP_T1T_SW */
#endif /* NXPBUILD__PHAL_TOP_SW */