1005 lines
43 KiB
Plaintext
1005 lines
43 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
|
|
* NFC Library Top Level API of Reader Library Framework.
|
|
* $Author: jenkins_ cm (nxp92197) $
|
|
* $Revision: 4184 $ (v07.10.00)
|
|
* $Date: 2016-08-30 18:04:59 +0530 (Fri, 30 Aug 2016) $
|
|
*
|
|
* History:
|
|
* KK: Generated 30. Aug 2016
|
|
*/
|
|
|
|
#include <ph_Status.h>
|
|
|
|
#ifdef NXPBUILD__PH_NFCLIB_ISO_18000
|
|
|
|
#include "phNfcLib_Initialization.h"
|
|
#include "phNfcLib_Int.h"
|
|
|
|
#define PH_NFCLIB_18000P3M3_CMD_REQ_RN 0xC1U /**< ReqRn command code. */
|
|
#define PH_NFCLIB_18000P3M3_CMD_READ 0xC2U /**< Read command code. */
|
|
#define PH_NFCLIB_18000P3M3_CMD_WRITE 0xC3U /**< Write command code. */
|
|
#define PH_NFCLIB_18000P3M3_CMD_KILL 0xC4U /**< Kill command code. */
|
|
#define PH_NFCLIB_18000P3M3_CMD_LOCK 0xC5U /**< Lock command code. */
|
|
#define PH_NFCLIB_18000P3M3_CMD_ACCESS 0xC6U /**< Access command code. */
|
|
#define PH_NFCLIB_18000P3M3_CMD_BLOCKWRITE 0xC7U /**< BlockWrite command code. */
|
|
#define PH_NFCLIB_18000P3M3_CMD_BLOCKERASE 0xC8U /**< BlockErase command code. */
|
|
#define PH_NFCLIB_18000P3M3_CMD_BLOCKPERMALOCK 0xC9U /**< BlockPermaLock command code. */
|
|
#define PH_NFCLIB_18000P3M3_CMD_ACK 0x01U /**< ACK command code. */
|
|
|
|
#define PH_NFCLIB_18000P3M3_SW_T2_MIN_US 151U /* T2 Time for 18000p3m3 */
|
|
#define PH_NFCLIB_18000P3M3_SW_TIMEOUT 113U /* Timeout for 18000p3m3 */
|
|
|
|
#define PH_NFCLIB_18000P3M3_SKIP_COMMAND 0xFFU /**< Skip the command */
|
|
|
|
static phStatus_t phNfcLib_18000p3m3_ReqRN(void);
|
|
static phStatus_t phNfcLib_18000p3m3_Exchange(uint8_t bSymbol, uint8_t bTxLastBits, uint16_t wTimeout, uint8_t* pCmd, uint16_t wCmdLength, uint16_t *pRxLastBits);
|
|
|
|
phStatus_t phNfcLib_ISO18000_Transmit(void * const pTxBuffer, uint16_t wTxBufferLength)
|
|
{
|
|
uint8_t bCmd[10] = {0};
|
|
uint16_t wCmdLength = 0;
|
|
phStatus_t statusTmp = PH_ERR_INVALID_PARAMETER;
|
|
phStatus_t wStatus = PH_ERR_INVALID_PARAMETER;
|
|
uint8_t bIndex;
|
|
uint8_t bUiiMaskBytes = 0;
|
|
uint8_t bHandle[2] = {0};
|
|
uint16_t wRxLastBits = 0;
|
|
uint8_t aSelectCmd[39] = {0};
|
|
uint8_t wSelectCmdLen;
|
|
uint8_t bSelectCmdValidBits;
|
|
uint8_t aBeginRoundCmd[3] = {0};
|
|
uint8_t bUiiStartAddress = 0x20;
|
|
|
|
if ((((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.wUiiMaskLength % 8U) != 0U)
|
|
{
|
|
bUiiMaskBytes = (((((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.wUiiMaskLength)/8U) + 1U);
|
|
}
|
|
else
|
|
{
|
|
bUiiMaskBytes = (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.wUiiMaskLength)/8U;
|
|
}
|
|
|
|
#if 0
|
|
((((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.wUiiMaskLength % 8U) != 0U) ? (bUiiMaskBytes = (((((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.wUiiMaskLength)/8U) + 1U)) : (bUiiMaskBytes = (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.wUiiMaskLength)/8U);
|
|
|
|
/* Since truncation option is not set thus logically the chance of it getting non complete bytes is very rare */
|
|
bUiiMaskBytes = ((((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.wUiiMaskLength % 8U) ?
|
|
((((((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.wUiiMaskLength)/8U) + 1U)) :
|
|
((((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.wUiiMaskLength)/8U));
|
|
#endif
|
|
|
|
if(0 != (memcmp(gphNfcLib_State.pActivatedUid, ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pUii, bUiiMaskBytes)))
|
|
{
|
|
/* Create select command frame (with selected UII in mask) */
|
|
PH_CHECK_SUCCESS_FCT(statusTmp, phpalI18000p3m3_CreateSelectCmd(
|
|
gphNfcLib_Params.sDiscLoop.pPal18000p3m3DataParams,
|
|
PHPAL_I18000P3M3_TARGET_INVENTORIED_S0,
|
|
0,
|
|
PHPAL_I18000P3M3_MEMBANK_UII,
|
|
&bUiiStartAddress,
|
|
0,
|
|
((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pUii,
|
|
(uint8_t)((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.wUiiMaskLength,
|
|
0,
|
|
aSelectCmd,
|
|
&wSelectCmdLen,
|
|
&bSelectCmdValidBits));
|
|
|
|
/* Create BeginRound command frame */
|
|
PH_CHECK_SUCCESS_FCT(statusTmp, phpalI18000p3m3_CreateBeginRoundCmd(
|
|
gphNfcLib_Params.sDiscLoop.pPal18000p3m3DataParams,
|
|
gphNfcLib_Params.sDiscLoop.sI18000p3m3TargetInfo.bDr,
|
|
gphNfcLib_Params.sDiscLoop.sI18000p3m3TargetInfo.bM,
|
|
(uint8_t)PH_OFF,
|
|
PHPAL_I18000P3M3_SEL_ALL_00,
|
|
PHPAL_I18000P3M3_SESSION_S0,
|
|
0,
|
|
0,
|
|
aBeginRoundCmd));
|
|
|
|
/* Activate tag with specified UII */
|
|
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_I18000p3m3Inventory(
|
|
gphNfcLib_Params.sDiscLoop.pHalDataParams,
|
|
aSelectCmd,
|
|
(uint8_t)wSelectCmdLen,
|
|
bSelectCmdValidBits,
|
|
aBeginRoundCmd,
|
|
PHHAL_HW_I18000P3M3_GET_TAG_HANDLE,
|
|
&gphNfcLib_State.pRxBuffer,
|
|
&gphNfcLib_State.wRxLength));
|
|
|
|
/* Update handle */
|
|
/* Update the activated UII here */
|
|
gphNfcLib_State.pActivatedUid = ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pUii;
|
|
(void)memcpy(&gphNfcLib_Params.salI18000p3m3.abHandle[0], &gphNfcLib_State.pRxBuffer[gphNfcLib_State.wRxLength - 2u], 2);
|
|
gphNfcLib_Params.salI18000p3m3.bHandleValid = PH_ON;
|
|
}
|
|
|
|
/* TODO: If ever the handle concept changes the check has to be performed here */
|
|
/* Valid Handle is mandatory */
|
|
if (gphNfcLib_Params.salI18000p3m3.bHandleValid == PH_OFF)
|
|
{
|
|
return PH_ERR_USE_CONDITION;
|
|
}
|
|
|
|
switch(((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bCommand)
|
|
{
|
|
case ISO18000_Ack:
|
|
|
|
/* Build Command frame */
|
|
bCmd[0] = (PH_NFCLIB_18000P3M3_CMD_ACK << 6U) | (gphNfcLib_Params.salI18000p3m3.abHandle[0] >> 2U); /* 0 bits left */
|
|
bCmd[1] = (gphNfcLib_Params.salI18000p3m3.abHandle[0] << 6U) | (gphNfcLib_Params.salI18000p3m3.abHandle[1] >> 2U); /* 0 bits left */
|
|
bCmd[2] = (gphNfcLib_Params.salI18000p3m3.abHandle[1] << 6U); /* 6 bits left */
|
|
|
|
/* Set frame-sync as start symbol */
|
|
PH_CHECK_SUCCESS_FCT(wStatus, phhalHw_SetConfig(
|
|
gphNfcLib_Params.sDiscLoop.pHalDataParams,
|
|
PHHAL_HW_CONFIG_SYMBOL_START,
|
|
PHHAL_HW_SYMBOL_I18000P3M3_FSYNC));
|
|
|
|
/* Set TxWait to T2 */
|
|
PH_CHECK_SUCCESS_FCT(wStatus, phhalHw_SetConfig(
|
|
gphNfcLib_Params.sDiscLoop.pHalDataParams,
|
|
PHHAL_HW_CONFIG_TXWAIT_US,
|
|
PH_NFCLIB_18000P3M3_SW_T2_MIN_US));
|
|
|
|
/* Set T1+T3 Timeout */
|
|
PH_CHECK_SUCCESS_FCT(wStatus, phhalHw_SetConfig(
|
|
gphNfcLib_Params.sDiscLoop.pHalDataParams,
|
|
PHHAL_HW_CONFIG_TIMEOUT_VALUE_US,
|
|
PH_NFCLIB_18000P3M3_SW_TIMEOUT));
|
|
|
|
/* Switch off HAL-CRC */
|
|
PH_CHECK_SUCCESS_FCT(wStatus, phhalHw_SetConfig(gphNfcLib_Params.sDiscLoop.pHalDataParams, PHHAL_HW_CONFIG_TXCRC, PH_OFF));
|
|
PH_CHECK_SUCCESS_FCT(wStatus, phhalHw_SetConfig(gphNfcLib_Params.sDiscLoop.pHalDataParams, PHHAL_HW_CONFIG_RXCRC, PH_OFF));
|
|
|
|
statusTmp = phNfcLib_18000p3m3_Exchange(PH_NFCLIB_18000P3M3_SKIP_COMMAND, 0x02, PH_NFCLIB_18000P3M3_SKIP_COMMAND, &bCmd[0], 3, &wRxLastBits);
|
|
|
|
/* Switch on HAL-CRC from now on */
|
|
PH_CHECK_SUCCESS_FCT(wStatus, phhalHw_SetConfig(gphNfcLib_Params.sDiscLoop.pHalDataParams, PHHAL_HW_CONFIG_TXCRC, PH_ON));
|
|
PH_CHECK_SUCCESS_FCT(wStatus, phhalHw_SetConfig(gphNfcLib_Params.sDiscLoop.pHalDataParams, PHHAL_HW_CONFIG_RXCRC, PH_ON));
|
|
|
|
/* set Tx-CRC as CRC16 */
|
|
PH_CHECK_SUCCESS_FCT(wStatus, phhalHw_SetConfig(gphNfcLib_Params.sDiscLoop.pHalDataParams, PHHAL_HW_CONFIG_CRCTYPE, PHHAL_HW_CRCTYPE_CRC16|PHHAL_HW_CRCOPTION_INVERTED));
|
|
|
|
if(statusTmp == PH_ERR_SUCCESS)
|
|
{
|
|
|
|
/* Get bit length */
|
|
if (0U != (wRxLastBits & 0x07U))
|
|
{
|
|
--gphNfcLib_State.wRxLength;
|
|
}
|
|
wRxLastBits = (uint16_t)((gphNfcLib_State.wRxLength << 3U) + wRxLastBits);
|
|
|
|
/* Check response length */
|
|
if ((wRxLastBits < 5U) || (wRxLastBits > 528U))
|
|
{
|
|
return PH_ERR_PROTOCOL_ERROR;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ISO18000_ReqRn:
|
|
|
|
statusTmp = phNfcLib_18000p3m3_ReqRN();
|
|
|
|
break;
|
|
|
|
case ISO18000_Read:
|
|
|
|
/* Parameter check */
|
|
if ((((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bMemBank > 0x03U) || (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bWordPtrLength > 3U))
|
|
{
|
|
return PH_ERR_INVALID_PARAMETER;
|
|
}
|
|
|
|
PH_CHECK_SUCCESS_FCT(wStatus, phhalHw_SetConfig(
|
|
gphNfcLib_Params.sDiscLoop.pHalDataParams,
|
|
PHHAL_HW_CONFIG_TIMEOUT_VALUE_US,
|
|
(uint16_t)0x158));
|
|
|
|
/* prepare command header */
|
|
bCmd[wCmdLength++] = PH_NFCLIB_18000P3M3_CMD_READ;
|
|
bCmd[wCmdLength] = (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bMemBank << 6U) | (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bWordPtrLength << 4U); /* 4 bits left */
|
|
|
|
/* append pointer */
|
|
for (bIndex = 0; bIndex < (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bWordPtrLength + 1U); ++bIndex)
|
|
{
|
|
bCmd[wCmdLength++] |= (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pWordPtr[bIndex]) >> 4U;
|
|
bCmd[wCmdLength] = (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pWordPtr[bIndex]) << 4U;
|
|
}
|
|
/* 4 bits left */
|
|
|
|
/* append word-count */
|
|
bCmd[wCmdLength++] |= ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bWordCount >> 4U; /* 0 bits left */
|
|
bCmd[wCmdLength] = ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bWordCount << 4U; /* 4 bits left */
|
|
|
|
/* TODO: if ever the handle concept changes the change has to be done here */
|
|
/* append handle */
|
|
bCmd[wCmdLength++] |= gphNfcLib_Params.salI18000p3m3.abHandle[0] >> 4U; /* 0 bits left */
|
|
bCmd[wCmdLength] = gphNfcLib_Params.salI18000p3m3.abHandle[0] << 4U; /* 4 bits left */
|
|
bCmd[wCmdLength++] |= gphNfcLib_Params.salI18000p3m3.abHandle[1] >> 4U; /* 0 bits left */
|
|
bCmd[wCmdLength++] = gphNfcLib_Params.salI18000p3m3.abHandle[1] << 4U; /* 4 bits left */
|
|
|
|
PH_CHECK_SUCCESS_FCT(statusTmp, phNfcLib_18000p3m3_Exchange(PH_OFF, 0x04, PH_NFCLIB_18000P3M3_SKIP_COMMAND, &bCmd[0], wCmdLength, &wRxLastBits));
|
|
|
|
/* Check received length and header bit */
|
|
if (((((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bWordCount != 0x00U) &&
|
|
(gphNfcLib_State.wRxLength != ((((uint16_t)(((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bWordCount)) << 1U) + 3U))) ||
|
|
(wRxLastBits != 1U) || ((gphNfcLib_State.pRxBuffer[0] & 0x80U) != 0U))
|
|
{
|
|
return PH_ERR_PROTOCOL_ERROR;
|
|
}
|
|
|
|
for (bIndex = 0; bIndex < (gphNfcLib_State.wRxLength - 1U); bIndex++)
|
|
{
|
|
gphNfcLib_State.pRxBuffer[bIndex] = (gphNfcLib_State.pRxBuffer[bIndex] << 1U) |
|
|
(gphNfcLib_State.pRxBuffer[bIndex + 1U] >> 7U);
|
|
}
|
|
|
|
/* Status byte is removed */
|
|
gphNfcLib_State.wRxLength--;
|
|
|
|
/* TODO: if ever the handle concept changes the change has to be done here */
|
|
/* Check Handle */
|
|
if ((gphNfcLib_State.pRxBuffer[gphNfcLib_State.wRxLength - 2u] != gphNfcLib_Params.salI18000p3m3.abHandle[0]) ||
|
|
(gphNfcLib_State.pRxBuffer[gphNfcLib_State.wRxLength - 1u] != gphNfcLib_Params.salI18000p3m3.abHandle[1]))
|
|
{
|
|
return PH_ERR_PROTOCOL_ERROR;
|
|
}
|
|
|
|
/* Handle is not part of data */
|
|
gphNfcLib_State.wRxLength -= 2u;
|
|
|
|
break;
|
|
|
|
case ISO18000_Write:
|
|
|
|
/* Parameter check */
|
|
if ((((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bMemBank > 0x03U) ||
|
|
(((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bWordPtrLength > 3U) ||
|
|
((((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bOption != PH_NFCLIB_18000P3M3_AC_NO_COVER_CODING) &&
|
|
(((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bOption != PH_NFCLIB_18000P3M3_AC_USE_COVER_CODING)))
|
|
{
|
|
return PH_ERR_INVALID_PARAMETER;
|
|
}
|
|
|
|
/* prepare command header */
|
|
wCmdLength = 0;
|
|
bCmd[wCmdLength++] = PH_NFCLIB_18000P3M3_CMD_WRITE;
|
|
bCmd[wCmdLength] = (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bMemBank << 6U) |
|
|
(((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bWordPtrLength << 4U); /* 4 bits left */
|
|
|
|
/* append pointer */
|
|
for (bIndex = 0; bIndex < (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bWordPtrLength + 1U); ++bIndex)
|
|
{
|
|
bCmd[wCmdLength++] |= (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pWordPtr[bIndex]) >> 4U;
|
|
bCmd[wCmdLength] = (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pWordPtr[bIndex]) << 4U;
|
|
}
|
|
/* 4 bits left */
|
|
|
|
/* append data */
|
|
bCmd[wCmdLength++] |= ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pBuffer[0] >> 4U; /* 0 bits left */
|
|
bCmd[wCmdLength++] = (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pBuffer[0] << 4U) |
|
|
(((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pBuffer[1] >> 4U); /* 0 bits left */
|
|
bCmd[wCmdLength] = ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pBuffer[1] << 4U; /* 4 bits left */
|
|
|
|
/* perform cover-coding if neccessary */
|
|
if (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bOption == PH_NFCLIB_18000P3M3_AC_USE_COVER_CODING)
|
|
{
|
|
/* New RN16 needs to be obtained for cover coding */
|
|
(void)phNfcLib_18000p3m3_ReqRN();
|
|
|
|
/* perform XOR operation */
|
|
bCmd[wCmdLength - 2u] ^= gphNfcLib_State.pRxBuffer[0] >> 4U;
|
|
bCmd[wCmdLength - 1u] ^= (gphNfcLib_State.pRxBuffer[0] << 4U) | (gphNfcLib_State.pRxBuffer[1] >> 4U);
|
|
bCmd[wCmdLength] ^= gphNfcLib_State.pRxBuffer[1] << 4U;
|
|
}
|
|
|
|
/* append handle */
|
|
bCmd[wCmdLength++] |= gphNfcLib_Params.salI18000p3m3.abHandle[0] >> 4U; /* 0 bits left */
|
|
bCmd[wCmdLength] = gphNfcLib_Params.salI18000p3m3.abHandle[0] << 4U; /* 4 bits left */
|
|
bCmd[wCmdLength++] |= gphNfcLib_Params.salI18000p3m3.abHandle[1] >> 4U; /* 0 bits left */
|
|
bCmd[wCmdLength++] = gphNfcLib_Params.salI18000p3m3.abHandle[1] << 4U; /* 4 bits left */
|
|
|
|
PH_CHECK_SUCCESS_FCT(statusTmp, phNfcLib_18000p3m3_Exchange(PH_OFF, 0x04, 5, &bCmd[0], wCmdLength, &wRxLastBits));
|
|
|
|
/* Check header bit */
|
|
if ((gphNfcLib_State.wRxLength != 3U) || (wRxLastBits != 1U) || ((gphNfcLib_State.pRxBuffer[0] & 0x80U) != 0U))
|
|
{
|
|
return PH_ERR_PROTOCOL_ERROR;
|
|
}
|
|
|
|
/* Check Handle */
|
|
bHandle[0] = (uint8_t)((gphNfcLib_State.pRxBuffer[0] << 1U) | (gphNfcLib_State.pRxBuffer[1] >> 7U));
|
|
bHandle[1] = (uint8_t)((gphNfcLib_State.pRxBuffer[1] << 1U) | (gphNfcLib_State.pRxBuffer[2] >> 7U));
|
|
if ((bHandle[0] != gphNfcLib_Params.salI18000p3m3.abHandle[0]) ||
|
|
(bHandle[1] != gphNfcLib_Params.salI18000p3m3.abHandle[1]))
|
|
{
|
|
return PH_ERR_PROTOCOL_ERROR;
|
|
}
|
|
|
|
/* Making Received length as 0 since no user data has been received */
|
|
gphNfcLib_State.wRxLength = 0;
|
|
break;
|
|
|
|
case ISO18000_Kill:
|
|
|
|
/* Parameter check */
|
|
if (((((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bOption != PH_NFCLIB_18000P3M3_AC_NO_COVER_CODING) &&
|
|
(((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bOption != PH_NFCLIB_18000P3M3_AC_USE_COVER_CODING)) ||
|
|
(((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bRecom > 0x07U))
|
|
{
|
|
return PH_ERR_INVALID_PARAMETER;
|
|
}
|
|
|
|
/* */
|
|
/* Perform FIRST PART of KILL command */
|
|
/* */
|
|
|
|
/* prepare command header */
|
|
bCmd[0] = PH_NFCLIB_18000P3M3_CMD_KILL;
|
|
bCmd[1] = ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pPassword[0];
|
|
bCmd[2] = ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pPassword[1];
|
|
|
|
/* perform cover-coding if necessary */
|
|
if (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bOption == PHAL_I18000P3M3_AC_USE_COVER_CODING)
|
|
{
|
|
/* retrieve RN16 */
|
|
PH_CHECK_SUCCESS_FCT(statusTmp,phNfcLib_18000p3m3_ReqRN());
|
|
|
|
/* perform XOR operation */
|
|
bCmd[1] ^= gphNfcLib_State.pRxBuffer[0];
|
|
bCmd[2] ^= gphNfcLib_State.pRxBuffer[1];
|
|
}
|
|
|
|
/* append RFU/Recom bits (000) and handle */
|
|
bCmd[3] = 0x00; /* 5 bits left */
|
|
bCmd[3] |= gphNfcLib_Params.salI18000p3m3.abHandle[0] >> 3U; /* 0 bits left */
|
|
bCmd[4] = gphNfcLib_Params.salI18000p3m3.abHandle[0] << 5U; /* 5 bits left */
|
|
bCmd[4] |= gphNfcLib_Params.salI18000p3m3.abHandle[1] >> 3U; /* 0 bits left */
|
|
bCmd[5] = gphNfcLib_Params.salI18000p3m3.abHandle[1] << 5U; /* 5 bits left */
|
|
|
|
PH_CHECK_SUCCESS_FCT(statusTmp, phNfcLib_18000p3m3_Exchange(PH_OFF, 0x03, 500, &bCmd[0], 6, NULL));
|
|
|
|
/* Check received length */
|
|
if (gphNfcLib_State.wRxLength != 2U)
|
|
{
|
|
return PH_ERR_PROTOCOL_ERROR;
|
|
}
|
|
|
|
/* Check Handle */
|
|
if ((gphNfcLib_State.pRxBuffer[0] != gphNfcLib_Params.salI18000p3m3.abHandle[0]) ||
|
|
(gphNfcLib_State.pRxBuffer[1] != gphNfcLib_Params.salI18000p3m3.abHandle[1]))
|
|
{
|
|
return PH_ERR_PROTOCOL_ERROR;
|
|
}
|
|
|
|
/*
|
|
* Perform second part of kill command
|
|
*/
|
|
|
|
/* prepare command header */
|
|
bCmd[0] = PH_NFCLIB_18000P3M3_CMD_KILL;
|
|
bCmd[1] = ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pPassword[2];
|
|
bCmd[2] = ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pPassword[3];
|
|
|
|
/* perform cover-coding if neccessary */
|
|
if (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bOption == PHAL_I18000P3M3_AC_USE_COVER_CODING)
|
|
{
|
|
/* retrieve RN16 */
|
|
/* retrieve RN16 */
|
|
PH_CHECK_SUCCESS_FCT(statusTmp,phNfcLib_18000p3m3_ReqRN());
|
|
|
|
/* perform XOR operation */
|
|
bCmd[1] ^= gphNfcLib_State.pRxBuffer[0];
|
|
bCmd[2] ^= gphNfcLib_State.pRxBuffer[1];
|
|
}
|
|
|
|
/* append RFU/Recom bits (000) and handle */
|
|
bCmd[3] = ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bRecom << 5U; /* 5 bits left */
|
|
bCmd[3] |= gphNfcLib_Params.salI18000p3m3.abHandle[0] >> 3U; /* 0 bits left */
|
|
bCmd[4] = gphNfcLib_Params.salI18000p3m3.abHandle[0] << 5U; /* 5 bits left */
|
|
bCmd[4] |= gphNfcLib_Params.salI18000p3m3.abHandle[1] >> 3U; /* 0 bits left */
|
|
bCmd[5] = gphNfcLib_Params.salI18000p3m3.abHandle[1] << 5U; /* 5 bits left */
|
|
|
|
PH_CHECK_SUCCESS_FCT(statusTmp, phNfcLib_18000p3m3_Exchange(PH_OFF, 0x03, PH_NFCLIB_18000P3M3_SKIP_COMMAND, &bCmd[0], 6, &wRxLastBits));
|
|
|
|
/* Check received length and header */
|
|
if ((gphNfcLib_State.wRxLength != 3U) ||
|
|
(wRxLastBits != 1U) ||
|
|
((gphNfcLib_State.pRxBuffer[0] & 0x80U) != 0U))
|
|
{
|
|
return PH_ERR_PROTOCOL_ERROR;
|
|
}
|
|
|
|
/* Check Handle */
|
|
bHandle[0] = (uint8_t)((gphNfcLib_State.pRxBuffer[0] << 1U) | (gphNfcLib_State.pRxBuffer[1] >> 7U));
|
|
bHandle[1] = (uint8_t)((gphNfcLib_State.pRxBuffer[1] << 1U) | (gphNfcLib_State.pRxBuffer[2] >> 7U));
|
|
if ((bHandle[0] != gphNfcLib_Params.salI18000p3m3.abHandle[0]) ||
|
|
(bHandle[1] != gphNfcLib_Params.salI18000p3m3.abHandle[1]))
|
|
{
|
|
return PH_ERR_PROTOCOL_ERROR;
|
|
}
|
|
|
|
/* Making Received length as 0 since no user data has been received */
|
|
gphNfcLib_State.wRxLength = 0;
|
|
break;
|
|
|
|
case ISO18000_Lock:
|
|
|
|
/* prepare command header */
|
|
bCmd[0] = PH_NFCLIB_18000P3M3_CMD_LOCK; /* 0 bits left */
|
|
bCmd[1] = ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pMask[0]; /* 0 bits left */
|
|
bCmd[2] = (uint8_t)((((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pMask[1] & 0xC0U) | (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pAction[0] >> 2U)); /* 0 bits left */
|
|
bCmd[3] = (uint8_t)((((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pAction[0] << 6U) | ((((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pAction[1] & 0xC0U) >> 2U)); /* 4 bits left */
|
|
|
|
/* append handle */
|
|
bCmd[3] |= gphNfcLib_Params.salI18000p3m3.abHandle[0] >> 4U; /* 0 bits left */
|
|
bCmd[4] = gphNfcLib_Params.salI18000p3m3.abHandle[0] << 4U; /* 4 bits left */
|
|
bCmd[4] |= gphNfcLib_Params.salI18000p3m3.abHandle[1] >> 4U; /* 0 bits left */
|
|
bCmd[5] = gphNfcLib_Params.salI18000p3m3.abHandle[1] << 4U; /* 4 bits left */
|
|
|
|
PH_CHECK_SUCCESS_FCT(statusTmp, phNfcLib_18000p3m3_Exchange(PH_OFF, 0x04, 5, &bCmd[0], 6, &wRxLastBits));
|
|
|
|
/* Check received length and header */
|
|
if ((gphNfcLib_State.wRxLength != 3U) ||
|
|
(wRxLastBits != 1U) ||
|
|
((gphNfcLib_State.pRxBuffer[0] & 0x80U) != 0U))
|
|
{
|
|
return PH_ERR_PROTOCOL_ERROR;
|
|
}
|
|
|
|
/* Check Handle */
|
|
bHandle[0] = (uint8_t)((gphNfcLib_State.pRxBuffer[0] << 1U) | (gphNfcLib_State.pRxBuffer[1] >> 7U));
|
|
bHandle[1] = (uint8_t)((gphNfcLib_State.pRxBuffer[1] << 1U) | (gphNfcLib_State.pRxBuffer[2] >> 7U));
|
|
if ((bHandle[0] != gphNfcLib_Params.salI18000p3m3.abHandle[0]) ||
|
|
(bHandle[1] != gphNfcLib_Params.salI18000p3m3.abHandle[1]))
|
|
{
|
|
return PH_ERR_PROTOCOL_ERROR;
|
|
}
|
|
/* Making Received length as 0 since no user data has been received */
|
|
gphNfcLib_State.wRxLength = 0;
|
|
break;
|
|
|
|
case ISO18000_Access:
|
|
|
|
/* Parameter check */
|
|
if ((((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bOption != PH_NFCLIB_18000P3M3_AC_NO_COVER_CODING) &&
|
|
(((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bOption != PH_NFCLIB_18000P3M3_AC_USE_COVER_CODING))
|
|
{
|
|
return PH_ERR_INVALID_PARAMETER;
|
|
}
|
|
|
|
/* */
|
|
/* Perform FIRST PART of ACCESS command */
|
|
/* */
|
|
|
|
/* prepare command header */
|
|
bCmd[0] = PH_NFCLIB_18000P3M3_CMD_ACCESS;
|
|
bCmd[1] = ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pPassword[0];
|
|
bCmd[2] = ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pPassword[1];
|
|
|
|
/* perform cover-coding if neccessary */
|
|
if (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bOption == PH_NFCLIB_18000P3M3_AC_USE_COVER_CODING)
|
|
{
|
|
/* New RN16 needs to be obtained for cover coding */
|
|
(void)phNfcLib_18000p3m3_ReqRN();
|
|
|
|
/* perform XOR operation */
|
|
bCmd[1] ^= gphNfcLib_State.pRxBuffer[0];
|
|
bCmd[2] ^= gphNfcLib_State.pRxBuffer[1];
|
|
|
|
}
|
|
|
|
/* append handle */
|
|
bCmd[3] = gphNfcLib_Params.salI18000p3m3.abHandle[0];
|
|
bCmd[4] = gphNfcLib_Params.salI18000p3m3.abHandle[1];
|
|
|
|
PH_CHECK_SUCCESS_FCT(statusTmp, phNfcLib_18000p3m3_Exchange(PH_OFF, PH_NFCLIB_18000P3M3_SKIP_COMMAND, PH_NFCLIB_18000P3M3_SKIP_COMMAND, &bCmd[0], 5, NULL));
|
|
|
|
/* Check received length */
|
|
if (gphNfcLib_State.wRxLength != 2U)
|
|
{
|
|
return PH_ERR_PROTOCOL_ERROR;
|
|
}
|
|
|
|
/* Check Handle */
|
|
if ((gphNfcLib_State.pRxBuffer[0] != gphNfcLib_Params.salI18000p3m3.abHandle[0]) ||
|
|
(gphNfcLib_State.pRxBuffer[1] != gphNfcLib_Params.salI18000p3m3.abHandle[1]))
|
|
{
|
|
return PH_ERR_PROTOCOL_ERROR;
|
|
}
|
|
|
|
/* */
|
|
/* Perform SECOND PART of ACCESS command */
|
|
/* */
|
|
|
|
/* prepare command header */
|
|
bCmd[0] = PH_NFCLIB_18000P3M3_CMD_ACCESS;
|
|
bCmd[1] = ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pPassword[2];
|
|
bCmd[2] = ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pPassword[3];
|
|
|
|
/* perform cover-coding if neccessary */
|
|
if (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bOption == PH_NFCLIB_18000P3M3_AC_USE_COVER_CODING)
|
|
{
|
|
/* New RN16 needs to be obtained for cover coding */
|
|
(void)phNfcLib_18000p3m3_ReqRN();
|
|
|
|
/* perform XOR operation */
|
|
bCmd[1] ^= gphNfcLib_State.pRxBuffer[0];
|
|
bCmd[2] ^= gphNfcLib_State.pRxBuffer[1];
|
|
}
|
|
|
|
/* append handle */
|
|
bCmd[3] = gphNfcLib_Params.salI18000p3m3.abHandle[0];
|
|
bCmd[4] = gphNfcLib_Params.salI18000p3m3.abHandle[1];
|
|
|
|
/* perform the exchange */
|
|
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_Exchange(
|
|
gphNfcLib_Params.sDiscLoop.pHalDataParams,
|
|
PH_EXCHANGE_DEFAULT,
|
|
bCmd,
|
|
5,
|
|
&gphNfcLib_State.pRxBuffer,
|
|
&gphNfcLib_State.wRxLength));
|
|
|
|
/* Check received length */
|
|
if (gphNfcLib_State.wRxLength != 2U)
|
|
{
|
|
return PH_ERR_PROTOCOL_ERROR;
|
|
}
|
|
|
|
/* Check Handle */
|
|
if ((gphNfcLib_State.pRxBuffer[0] != gphNfcLib_Params.salI18000p3m3.abHandle[0]) ||
|
|
(gphNfcLib_State.pRxBuffer[1] != gphNfcLib_Params.salI18000p3m3.abHandle[1]))
|
|
{
|
|
return PH_ERR_PROTOCOL_ERROR;
|
|
}
|
|
/* Making Received length as 0 since no user data has been received */
|
|
gphNfcLib_State.wRxLength = 0;
|
|
break;
|
|
|
|
case ISO18000_BlockWrite:
|
|
|
|
/* Parameter check */
|
|
if ((((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bMemBank > 0x03U) || (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bWordPtrLength > 3U))
|
|
{
|
|
return PH_ERR_INVALID_PARAMETER;
|
|
}
|
|
|
|
/* prepare command header */
|
|
bCmd[wCmdLength++] = PH_NFCLIB_18000P3M3_CMD_BLOCKWRITE;
|
|
bCmd[wCmdLength] = (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bMemBank << 6U) | (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bWordPtrLength << 4U); /* 4 bits left */
|
|
|
|
/* append pointer */
|
|
for (bIndex = 0; bIndex < (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bWordPtrLength + 1U); ++bIndex)
|
|
{
|
|
bCmd[wCmdLength++] |= (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pWordPtr[bIndex]) >> 4U;
|
|
bCmd[wCmdLength] = (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pWordPtr[bIndex]) << 4U;
|
|
}
|
|
/* 4 bits left */
|
|
|
|
/* append (4bits) of Word-Count */
|
|
bCmd[wCmdLength++] |= ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bWordCount >> 4U; /* 0 bits left */
|
|
|
|
(void)phNfcLib_18000p3m3_Exchange(PH_OFF, 0x04, 20, NULL, PH_NFCLIB_18000P3M3_SKIP_COMMAND, NULL);
|
|
|
|
/* buffer the current contents */
|
|
statusTmp = phhalHw_Exchange(
|
|
gphNfcLib_Params.sDiscLoop.pHalDataParams,
|
|
PH_EXCHANGE_BUFFER_FIRST,
|
|
bCmd,
|
|
wCmdLength,
|
|
&gphNfcLib_State.pRxBuffer,
|
|
&gphNfcLib_State.wRxLength);
|
|
|
|
/* reset command length*/
|
|
wCmdLength = 0;
|
|
|
|
/* append the rest bits of block-range*/
|
|
bCmd[wCmdLength] = ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bWordCount << 4U; /* 4 bits left */
|
|
|
|
/* append data */
|
|
for (bIndex = 0; bIndex < (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bWordCount << 1U); ++bIndex)
|
|
{
|
|
bCmd[wCmdLength++] |= ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pBuffer[bIndex] >> 4U; /* 0 bits left */
|
|
|
|
/* buffer the current contents if command buffer is full */
|
|
if (wCmdLength == 7U)
|
|
{
|
|
/* buffer the current contents */
|
|
statusTmp = phhalHw_Exchange(
|
|
gphNfcLib_Params.sDiscLoop.pHalDataParams,
|
|
PH_EXCHANGE_BUFFER_CONT,
|
|
bCmd,
|
|
wCmdLength,
|
|
&gphNfcLib_State.pRxBuffer,
|
|
&gphNfcLib_State.wRxLength);
|
|
|
|
/* reset command length*/
|
|
wCmdLength = 0;
|
|
}
|
|
|
|
bCmd[wCmdLength] = ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pBuffer[bIndex] << 4U; /* 4 bits left */
|
|
}
|
|
|
|
/* append handle */
|
|
bCmd[wCmdLength++] |= gphNfcLib_Params.salI18000p3m3.abHandle[0] >> 4U; /* 0 bits left */
|
|
|
|
/* buffer the current contents if command buffer is full */
|
|
if (wCmdLength == 7U)
|
|
{
|
|
statusTmp = phhalHw_Exchange(
|
|
gphNfcLib_Params.sDiscLoop.pHalDataParams,
|
|
PH_EXCHANGE_BUFFER_CONT,
|
|
bCmd,
|
|
wCmdLength,
|
|
&gphNfcLib_State.pRxBuffer,
|
|
&gphNfcLib_State.wRxLength);
|
|
|
|
/* reset command length*/
|
|
wCmdLength = 0;
|
|
}
|
|
|
|
bCmd[wCmdLength] = gphNfcLib_Params.salI18000p3m3.abHandle[0] << 4U; /* 4 bits left */
|
|
bCmd[wCmdLength++] |= gphNfcLib_Params.salI18000p3m3.abHandle[1] >> 4U; /* 0 bits left */
|
|
bCmd[wCmdLength++] = gphNfcLib_Params.salI18000p3m3.abHandle[1] << 4U; /* 4 bits left */
|
|
|
|
/* perform the exchange */
|
|
statusTmp = phhalHw_Exchange(
|
|
gphNfcLib_Params.sDiscLoop.pHalDataParams,
|
|
PH_EXCHANGE_BUFFER_LAST,
|
|
bCmd,
|
|
wCmdLength,
|
|
&gphNfcLib_State.pRxBuffer,
|
|
&gphNfcLib_State.wRxLength);
|
|
|
|
/* Ignore incomplete byte status, bail out on error */
|
|
if ((statusTmp & PH_ERR_MASK) == PH_ERR_SUCCESS_INCOMPLETE_BYTE)
|
|
{
|
|
PH_CHECK_SUCCESS_FCT(wStatus, phhalHw_GetConfig(
|
|
gphNfcLib_Params.sDiscLoop.pHalDataParams,
|
|
PHHAL_HW_CONFIG_RXLASTBITS,
|
|
&wRxLastBits));
|
|
statusTmp = PH_ERR_SUCCESS;
|
|
|
|
}
|
|
|
|
if(statusTmp == PH_ERR_SUCCESS)
|
|
{
|
|
/* Check header bit */
|
|
if ((gphNfcLib_State.wRxLength != 3U) || (wRxLastBits != 1U) || ((gphNfcLib_State.pRxBuffer[0] & 0x80U) != 0U))
|
|
{
|
|
return PH_ERR_PROTOCOL_ERROR;
|
|
}
|
|
|
|
/* Check Handle */
|
|
bHandle[0] = (uint8_t)((gphNfcLib_State.pRxBuffer[0] << 1U) | (gphNfcLib_State.pRxBuffer[1] >> 7U));
|
|
bHandle[1] = (uint8_t)((gphNfcLib_State.pRxBuffer[1] << 1U) | (gphNfcLib_State.pRxBuffer[2] >> 7U));
|
|
if ((bHandle[0] != gphNfcLib_Params.salI18000p3m3.abHandle[0]) ||
|
|
(bHandle[1] != gphNfcLib_Params.salI18000p3m3.abHandle[1]))
|
|
{
|
|
return PH_ERR_PROTOCOL_ERROR;
|
|
}
|
|
/* Making Received length as 0 since no user data has been received */
|
|
gphNfcLib_State.wRxLength = 0;
|
|
}
|
|
break;
|
|
|
|
case ISO18000_BlockErase:
|
|
|
|
/* Parameter check */
|
|
if ((((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bMemBank > 0x03U) || (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bWordPtrLength > 3U))
|
|
{
|
|
return PH_ERR_INVALID_PARAMETER;
|
|
}
|
|
|
|
/* prepare command header */
|
|
wCmdLength = 0;
|
|
bCmd[wCmdLength++] = PH_NFCLIB_18000P3M3_CMD_BLOCKERASE;
|
|
bCmd[wCmdLength] = (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bMemBank << 6U) | (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bWordPtrLength << 4U); /* 4 bits left */
|
|
|
|
/* append pointer */
|
|
for (bIndex = 0; bIndex < (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bWordPtrLength + 1U); ++bIndex)
|
|
{
|
|
bCmd[wCmdLength++] |= (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pWordPtr[bIndex]) >> 4U;
|
|
bCmd[wCmdLength] = (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pWordPtr[bIndex]) << 4U;
|
|
}
|
|
/* 4 bits left */
|
|
|
|
/* append word-count */
|
|
bCmd[wCmdLength++] |= ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bWordCount >> 4U; /* 0 bits left */
|
|
bCmd[wCmdLength] = ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bWordCount << 4U; /* 4 bits left */
|
|
|
|
/* append handle */
|
|
bCmd[wCmdLength++] |= gphNfcLib_Params.salI18000p3m3.abHandle[0] >> 4U; /* 0 bits left */
|
|
bCmd[wCmdLength] = gphNfcLib_Params.salI18000p3m3.abHandle[0] << 4U; /* 4 bits left */
|
|
bCmd[wCmdLength++] |= gphNfcLib_Params.salI18000p3m3.abHandle[1] >> 4U; /* 0 bits left */
|
|
bCmd[wCmdLength++] = gphNfcLib_Params.salI18000p3m3.abHandle[1] << 4U; /* 4 bits left */
|
|
|
|
PH_CHECK_SUCCESS_FCT(statusTmp, phNfcLib_18000p3m3_Exchange(PH_ON, 0x04, 20, &bCmd[0], wCmdLength, &wRxLastBits));
|
|
|
|
/* Check received length and header bit */
|
|
if ((gphNfcLib_State.wRxLength != 3U) || (wRxLastBits != 1U) || ((gphNfcLib_State.pRxBuffer[0] & 0x80U) != 0U))
|
|
{
|
|
return PH_ERR_PROTOCOL_ERROR;
|
|
}
|
|
|
|
/* Check Handle */
|
|
bHandle[0] = (uint8_t)((gphNfcLib_State.pRxBuffer[0] << 1U) | (gphNfcLib_State.pRxBuffer[1] >> 7U));
|
|
bHandle[1] = (uint8_t)((gphNfcLib_State.pRxBuffer[1] << 1U) | (gphNfcLib_State.pRxBuffer[2] >> 7U));
|
|
if ((bHandle[0] != gphNfcLib_Params.salI18000p3m3.abHandle[0]) ||
|
|
(bHandle[1] != gphNfcLib_Params.salI18000p3m3.abHandle[1]))
|
|
{
|
|
return PH_ERR_PROTOCOL_ERROR;
|
|
}
|
|
/* Making Received length as 0 since no user data has been received */
|
|
gphNfcLib_State.wRxLength = 0;
|
|
break;
|
|
|
|
case ISO18000_BlockPermaLock:
|
|
/* Parameter check */
|
|
if ((((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bReadLock > 0x01U) || (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bMemBank > 0x03U) || (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bBlockPtrLength > 3U))
|
|
{
|
|
return PH_ERR_INVALID_PARAMETER;
|
|
}
|
|
|
|
/* prepare command header */
|
|
wCmdLength = 0;
|
|
bCmd[wCmdLength++] = PH_NFCLIB_18000P3M3_CMD_BLOCKPERMALOCK;
|
|
bCmd[wCmdLength++] = ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bRFU;
|
|
bCmd[wCmdLength] = (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bReadLock << 7U) | (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bMemBank << 5U) | (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bBlockPtrLength << 3U); /* 3 bits left */
|
|
|
|
/* append pointer */
|
|
for (bIndex = 0; bIndex < (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bBlockPtrLength + 1U); ++bIndex)
|
|
{
|
|
bCmd[wCmdLength++] |= (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pBlockPtr[bIndex]) >> 5U;
|
|
bCmd[wCmdLength] = (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pBlockPtr[bIndex]) << 3U;
|
|
}
|
|
/* 3 bits left */
|
|
|
|
/* append (3bits) of block-range */
|
|
bCmd[wCmdLength++] |= ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bBlockRange >> 5U; /* 0 bits left */
|
|
|
|
/* buffer the current contents */
|
|
statusTmp = phhalHw_Exchange(
|
|
gphNfcLib_Params.sDiscLoop.pHalDataParams,
|
|
PH_EXCHANGE_BUFFER_FIRST,
|
|
bCmd,
|
|
wCmdLength,
|
|
&gphNfcLib_State.pRxBuffer,
|
|
&gphNfcLib_State.wRxLength);
|
|
|
|
/* reset command length*/
|
|
wCmdLength = 0;
|
|
|
|
/* append the rest bits of block-range*/
|
|
bCmd[wCmdLength] = ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bBlockRange << 3U; /* 3 bits left */
|
|
|
|
/* append mask */
|
|
if (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bReadLock == 0x01U)
|
|
{
|
|
for (bIndex = 0; bIndex < (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bBlockRange << 1U); ++bIndex)
|
|
{
|
|
bCmd[wCmdLength++] |= ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pMask[bIndex] >> 5U; /* 0 bits left */
|
|
|
|
/* buffer the current contents if command buffer is full */
|
|
if (wCmdLength == 7U)
|
|
{
|
|
/* buffer the current contents */
|
|
statusTmp = phhalHw_Exchange(
|
|
gphNfcLib_Params.sDiscLoop.pHalDataParams,
|
|
PH_EXCHANGE_BUFFER_CONT,
|
|
bCmd,
|
|
wCmdLength,
|
|
&gphNfcLib_State.pRxBuffer,
|
|
&gphNfcLib_State.wRxLength);
|
|
|
|
/* reset command length*/
|
|
wCmdLength = 0;
|
|
}
|
|
|
|
bCmd[wCmdLength] = ((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pMask[bIndex] << 3U; /* 3 bits left */
|
|
}
|
|
}
|
|
|
|
/* append handle */
|
|
bCmd[wCmdLength++] |= gphNfcLib_Params.salI18000p3m3.abHandle[0] >> 5U; /* 0 bits left */
|
|
|
|
/* buffer the current contents if command buffer is full */
|
|
if (wCmdLength == 7U)
|
|
{
|
|
|
|
statusTmp = phhalHw_Exchange(
|
|
gphNfcLib_Params.sDiscLoop.pHalDataParams,
|
|
PH_EXCHANGE_BUFFER_CONT,
|
|
bCmd,
|
|
wCmdLength,
|
|
&gphNfcLib_State.pRxBuffer,
|
|
&gphNfcLib_State.wRxLength);
|
|
|
|
/* reset command length*/
|
|
wCmdLength = 0;
|
|
}
|
|
|
|
bCmd[wCmdLength] = gphNfcLib_Params.salI18000p3m3.abHandle[0] << 3U; /* 3 bits left */
|
|
bCmd[wCmdLength++] |= gphNfcLib_Params.salI18000p3m3.abHandle[1] >> 5U; /* 0 bits left */
|
|
bCmd[wCmdLength++] = gphNfcLib_Params.salI18000p3m3.abHandle[1] << 3U; /* 3 bits left */
|
|
|
|
(void)phNfcLib_18000p3m3_Exchange(PH_OFF, 0x05, 500, NULL, PH_NFCLIB_18000P3M3_SKIP_COMMAND, NULL);
|
|
|
|
/* perform the exchange */
|
|
statusTmp = phhalHw_Exchange(
|
|
gphNfcLib_Params.sDiscLoop.pHalDataParams,
|
|
PH_EXCHANGE_BUFFER_LAST,
|
|
bCmd,
|
|
wCmdLength,
|
|
&gphNfcLib_State.pRxBuffer,
|
|
&gphNfcLib_State.wRxLength);
|
|
|
|
/* Ignore incomplete byte status, bail out on error */
|
|
if ((statusTmp & PH_ERR_MASK) == PH_ERR_SUCCESS_INCOMPLETE_BYTE)
|
|
{
|
|
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_GetConfig(
|
|
gphNfcLib_Params.sDiscLoop.pHalDataParams,
|
|
PHHAL_HW_CONFIG_RXLASTBITS,
|
|
&wRxLastBits));
|
|
statusTmp = PH_ERR_SUCCESS;
|
|
}
|
|
|
|
if(statusTmp == PH_ERR_SUCCESS)
|
|
{
|
|
/* Check header bit */
|
|
if ((gphNfcLib_State.wRxLength < 3U) || (wRxLastBits != 1U) || ((gphNfcLib_State.pRxBuffer[0] & 0x80U) != 0U))
|
|
{
|
|
return PH_ERR_PROTOCOL_ERROR;
|
|
}
|
|
|
|
/* Check data length */
|
|
if (((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bReadLock == 0x00U)
|
|
{
|
|
if (gphNfcLib_State.wRxLength != (3u + (((uint16_t)(((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.bBlockRange)) << 1U)))
|
|
{
|
|
return PH_ERR_PROTOCOL_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (gphNfcLib_State.wRxLength != 3U)
|
|
{
|
|
return PH_ERR_PROTOCOL_ERROR;
|
|
}
|
|
}
|
|
|
|
for (bIndex = 0; bIndex < (gphNfcLib_State.wRxLength - 1U); bIndex++)
|
|
{
|
|
gphNfcLib_State.pRxBuffer[bIndex] = (gphNfcLib_State.pRxBuffer[bIndex] << 1U) | (gphNfcLib_State.pRxBuffer[bIndex + 1U] >> 7U);
|
|
}
|
|
|
|
/* Status byte is removed */
|
|
gphNfcLib_State.wRxLength--;
|
|
|
|
/* Check Handle */
|
|
if ((gphNfcLib_State.pRxBuffer[gphNfcLib_State.wRxLength - 2u] != gphNfcLib_Params.salI18000p3m3.abHandle[0]) ||
|
|
(gphNfcLib_State.pRxBuffer[gphNfcLib_State.wRxLength - 1u] != gphNfcLib_Params.salI18000p3m3.abHandle[1]))
|
|
{
|
|
return PH_ERR_PROTOCOL_ERROR;
|
|
}
|
|
|
|
/* Handle is not part of data */
|
|
gphNfcLib_State.wRxLength -= 2u;
|
|
}
|
|
break;
|
|
|
|
case ISO18000_SetHandle:
|
|
(void)memcpy(&gphNfcLib_Params.salI18000p3m3.abHandle[0], &((phNfcLib_Transmit_t *)pTxBuffer)->phNfcLib_ISO18000.pHandle[0], 2);
|
|
gphNfcLib_Params.salI18000p3m3.bHandleValid = PH_ON;
|
|
statusTmp = PH_ERR_SUCCESS;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
PH_UNUSED_VARIABLE(wTxBufferLength);
|
|
return statusTmp;
|
|
}
|
|
|
|
static phStatus_t phNfcLib_18000p3m3_ReqRN(void)
|
|
{
|
|
phStatus_t statusTmp;
|
|
uint8_t bCmd[3] = {0};
|
|
|
|
/* Prepare and buffer command header */
|
|
bCmd[0] = PH_NFCLIB_18000P3M3_CMD_REQ_RN;
|
|
bCmd[1] = gphNfcLib_Params.salI18000p3m3.abHandle[0];
|
|
bCmd[2] = gphNfcLib_Params.salI18000p3m3.abHandle[1];
|
|
|
|
statusTmp = phhalHw_Exchange(
|
|
gphNfcLib_Params.sDiscLoop.pHalDataParams,
|
|
PH_EXCHANGE_DEFAULT,
|
|
bCmd,
|
|
3,
|
|
&gphNfcLib_State.pRxBuffer,
|
|
&gphNfcLib_State.wRxLength);
|
|
return statusTmp;
|
|
|
|
}
|
|
|
|
static phStatus_t phNfcLib_18000p3m3_Exchange(uint8_t bSymbol, uint8_t bTxLastBits, uint16_t wTimeout, uint8_t* pCmd, uint16_t wCmdLength, uint16_t *pRxLastBits)
|
|
{
|
|
phStatus_t statusTmp = PH_ERR_SUCCESS;
|
|
phStatus_t wStatus = PH_ERR_INVALID_PARAMETER;
|
|
|
|
if(bSymbol != PH_NFCLIB_18000P3M3_SKIP_COMMAND)
|
|
{
|
|
/* Setting the Symbol send. */
|
|
PH_CHECK_SUCCESS_FCT(wStatus, phhalHw_SetConfig(
|
|
gphNfcLib_Params.sDiscLoop.pHalDataParams,
|
|
PHHAL_HW_CONFIG_SET_SYMBOL_SEND,
|
|
(uint16_t)bSymbol));
|
|
}
|
|
|
|
if(bTxLastBits != PH_NFCLIB_18000P3M3_SKIP_COMMAND)
|
|
{
|
|
/* Setting the TxLastbits. */
|
|
PH_CHECK_SUCCESS_FCT(wStatus, phhalHw_SetConfig(
|
|
gphNfcLib_Params.sDiscLoop.pHalDataParams,
|
|
PHHAL_HW_CONFIG_TXLASTBITS,
|
|
(uint16_t)bTxLastBits));
|
|
}
|
|
|
|
if(wTimeout != PH_NFCLIB_18000P3M3_SKIP_COMMAND)
|
|
{
|
|
/* Set config for timeout */
|
|
PH_CHECK_SUCCESS_FCT(wStatus, phhalHw_SetConfig(
|
|
gphNfcLib_Params.sDiscLoop.pHalDataParams,
|
|
PHHAL_HW_CONFIG_TIMEOUT_VALUE_MS,
|
|
(uint16_t)wTimeout));
|
|
}
|
|
|
|
if(wCmdLength != PH_NFCLIB_18000P3M3_SKIP_COMMAND)
|
|
{
|
|
/* Perform HAL exchange. */
|
|
statusTmp = phhalHw_Exchange(
|
|
gphNfcLib_Params.sDiscLoop.pHalDataParams,
|
|
PH_EXCHANGE_DEFAULT,
|
|
pCmd,
|
|
wCmdLength,
|
|
&gphNfcLib_State.pRxBuffer,
|
|
&gphNfcLib_State.wRxLength);
|
|
}
|
|
|
|
if(pRxLastBits != NULL)
|
|
{
|
|
/* Ignore incomplete byte status, bail out on error */
|
|
if ((statusTmp & PH_ERR_MASK) == PH_ERR_SUCCESS_INCOMPLETE_BYTE)
|
|
{
|
|
PH_CHECK_SUCCESS_FCT(wStatus, phhalHw_GetConfig(
|
|
gphNfcLib_Params.sDiscLoop.pHalDataParams,
|
|
PHHAL_HW_CONFIG_RXLASTBITS,
|
|
pRxLastBits));
|
|
|
|
statusTmp = PH_ERR_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return statusTmp;
|
|
}
|
|
|
|
#endif /* NXPBUILD__PH_NFCLIB_ISO_18000 */
|