Files
NxpNfcRdLib/.svn/pristine/63/63c29999f593f05c91941635e54b424835f1bab1.svn-base
2024-07-08 21:03:06 +08:00

2125 lines
80 KiB
Plaintext

/*----------------------------------------------------------------------------*/
/* Copyright 2010-2020, 2022, 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
* Software ISO18092 passive initiator mode Component of Reader Library Framework.
* $Author$
* $Revision$ (v07.10.00)
* $Date$
*
* History:
* CEn: Generated 07. September 2010
*/
#include <ph_Status.h>
#include <phhalHw.h>
#include <phpalI18092mPI.h>
#include <ph_RefDefs.h>
#ifdef NXPBUILD__PHPAL_I18092MPI_SW
#include "phpalI18092mPI_Sw_Int.h"
#include "phpalI18092mPI_Sw.h"
/* We need to add one because for calculating the maximum payload length, we should have byte for length field
* which will be added as a part of payload...The Lower tester confirms the payload is the string without length
* field.
* */
const uint16_t PH_MEMLOC_CONST_ROM aI18092_mPI_FsTable[4] = {65, 129, 193, 255};
static const uint16_t PH_MEMLOC_CONST_ROM aI18092_DrTable[4] = {PHHAL_HW_RF_DATARATE_106, PHHAL_HW_RF_DATARATE_212, PHHAL_HW_RF_DATARATE_424, PHHAL_HW_RF_DATARATE_848};
phStatus_t phpalI18092mPI_Sw_Init(
phpalI18092mPI_Sw_DataParams_t * pDataParams,
uint16_t wSizeOfDataParams,
void * pHalDataParams
)
{
if (sizeof(phpalI18092mPI_Sw_DataParams_t) != wSizeOfDataParams)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_DATA_PARAMS, PH_COMP_PAL_I18092MPI);
}
PH_ASSERT_NULL (pDataParams);
PH_ASSERT_NULL (pHalDataParams);
/* Init private data */
pDataParams->wId = PH_COMP_PAL_I18092MPI | PHPAL_I18092MPI_SW_ID;
pDataParams->pHalDataParams = pHalDataParams;
/* Reset protocol to defaults */
return phpalI18092mPI_Sw_ResetProtocol(pDataParams);
}
phStatus_t phpalI18092mPI_Sw_ResetProtocol(
phpalI18092mPI_Sw_DataParams_t * pDataParams
)
{
/* Apply default parameters */
pDataParams->bNfcIdValid = PH_OFF;
pDataParams->bStateNow = PHPAL_I18092MPI_SW_STATE_INFORMATION_PDU_TX;
pDataParams->bDid = 0; /* set DID to 0, i.e. disable usage of DID */
pDataParams->bNadEnabled = PH_OFF;
pDataParams->bNad = 0;
pDataParams->bWt = PHPAL_I18092MPI_WT_MAX;
pDataParams->bFsl = PHPAL_I18092MPI_FRAMESIZE_64;
pDataParams->bLri = PHPAL_I18092MPI_FRAMESIZE_64;
pDataParams->bLrt = PHPAL_I18092MPI_FRAMESIZE_64;
pDataParams->bPni = 0; /* NFCForum-TS-DigitalProtocol-1.0 section 14.12.3.1 */
pDataParams->bDsi = 0;
pDataParams->bDri = 0;
pDataParams->bMaxRetryCount = PHPAL_I18092MPI_SW_RETRIES_DEFAULT;
pDataParams->bAtnDisabled = 0;
pDataParams->bActiveMode = 0;
pDataParams->bOpeMode = RD_LIB_MODE_NFC;
pDataParams->bPropPSLMode = PH_OFF;
return PH_ERR_SUCCESS;
}
phStatus_t phpalI18092mPI_Sw_Atr(
phpalI18092mPI_Sw_DataParams_t * pDataParams,
uint8_t * pNfcid3i,
uint8_t bDid,
uint8_t bLri,
uint8_t bNadEnabled,
uint8_t bNad,
uint8_t * pGi,
uint8_t bGiLength,
uint8_t * pAtrRes,
uint8_t * pAtrResLength
)
{
phStatus_t PH_MEMLOC_REM status;
phStatus_t PH_MEMLOC_REM statusTmp;
phStatus_t PH_MEMLOC_REM wPreviousStatus;
uint8_t PH_MEMLOC_REM aCmd[14];
uint8_t PH_MEMLOC_REM bCmdLen;
uint8_t * PH_MEMLOC_REM pResp = NULL;
uint16_t PH_MEMLOC_REM wResponseLength = 0;
uint16_t PH_MEMLOC_REM wFrameLength = 0;
uint8_t * PH_MEMLOC_REM pFrame = NULL;
uint8_t * PH_MEMLOC_REM pPayload = NULL;
uint16_t PH_MEMLOC_REM wPayloadLength = 0;
uint16_t PH_MEMLOC_REM wActiveMode;
uint8_t PH_MEMLOC_REM bRetry;
uint8_t PH_MEMLOC_COUNT bRetryCount;
uint8_t PH_MEMLOC_REM bResponseReceived;
uint8_t PH_MEMLOC_REM bTo;
uint16_t PH_MEMLOC_REM wDsi = 0;
uint16_t PH_MEMLOC_REM wDri;
uint32_t PH_MEMLOC_REM dwRwt;
uint32_t PH_MEMLOC_REM dwShift = 1U;
wPreviousStatus = 0;
bRetryCount = 0;
/* Parameter check */
if ((bDid > PHPAL_I18092MPI_DID_MAX) ||
(bLri > PHPAL_I18092MPI_FRAMESIZE_254) ||
(bGiLength > PHPAL_I18092MPI_MAX_GI_LENGTH))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_PAL_I18092MPI);
}
/* Make NfcID invalid */
pDataParams->bNfcIdValid = PH_OFF;
/* Set new DID */
pDataParams->bDid = bDid;
/* Build up frame data. */
(void)memcpy(aCmd, pNfcid3i, PHPAL_I18092MPI_NFCID3_LENGTH);
bCmdLen = PHPAL_I18092MPI_NFCID3_LENGTH;
aCmd[bCmdLen++] = bDid;
/* Next two fields (BSi and BRi) only used for active mode, so set them to 0. */
aCmd[bCmdLen++] = 0x00;
aCmd[bCmdLen++] = 0x00;
/* Configure PPi field */
aCmd[bCmdLen++] = (bLri << PHPAL_I18092MPI_SW_ATR_PPI_LRI_BIT);
if (0U != (bNadEnabled))
{
aCmd[bCmdLen - 1U] |= 0x01U;
}
/* Get initial set data rate from HAL since NFC allows starting at different data rates. */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_GetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_TXDATARATE_FRAMING, &wDsi));
PH_CHECK_SUCCESS_FCT(statusTmp, phpalI18092mPI_Sw_ConvertDatarate(wDsi, &pDataParams->bDsi));
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_GetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_RXDATARATE_FRAMING, &wDri));
PH_CHECK_SUCCESS_FCT(statusTmp, phpalI18092mPI_Sw_ConvertDatarate(wDri, &pDataParams->bDri));
/* Configure HAL for handling StartByte in case Transmit datarate is 106kbps. */
if (pDataParams->bDsi == PHHAL_HW_RF_DATARATE_106)
{
/* Configure HAL for NFCIP to enable handling StartByte at 106kbps. */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_NFCIP_STARTBYTE, PH_ON));
}
else
{
/* Disabled handling of StartByte if datarate is other than 106kbps. */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_NFCIP_STARTBYTE, PH_OFF));
}
/* Set Activation timeout */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(
pDataParams->pHalDataParams,
PHHAL_HW_CONFIG_TIMEOUT_VALUE_MS,
PHPAL_I18092MPI_SW_RWT_ACTIVATION_MS + PHPAL_I18092MPI_SW_DELTA_T_INITIATOR_MS));
/* Reset response received flag */
bResponseReceived = 0;
/* Retry loop */
do
{
/* Reset retry flag */
bRetry = PH_OFF;
/* Write frame header. */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalI18092mPI_Sw_WriteFrameHeader(pDataParams, PH_EXCHANGE_BUFFER_FIRST, PHPAL_I18092MPI_SW_CMD_ATR_REQ, (bCmdLen + bGiLength)));
/* Append general bytes if present */
if (bGiLength > 0U)
{
/* Mark that general bytes are present */
aCmd[bCmdLen - 1U] |= PHPAL_I18092MPI_SW_ATR_RES_PPT_GT_AVAILABLE;
/* Write data to internal buffer. */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_Exchange(
pDataParams->pHalDataParams,
PH_EXCHANGE_BUFFER_CONT,
aCmd,
(uint16_t)bCmdLen,
NULL,
NULL));
/* Write general bytes, transmit the whole buffer and receive response. */
status = phhalHw_Exchange(pDataParams->pHalDataParams,
PH_EXCHANGE_BUFFER_LAST,
pGi,
bGiLength,
&pResp,
&wResponseLength);
}
else
{
/* No additional general bytes to be sent so transmit the buffer now. */
status = phhalHw_Exchange(pDataParams->pHalDataParams,
PH_EXCHANGE_BUFFER_LAST,
aCmd,
(uint16_t)bCmdLen,
&pResp,
&wResponseLength);
}
/* Get the state of activation mode status either indication active/passive mode. */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_GetConfig(
pDataParams->pHalDataParams,
PHHAL_HW_CONFIG_ACTIVEMODE,
&wActiveMode));
pDataParams->bActiveMode = (uint8_t)wActiveMode;
/* Exchange was successful */
if ((status & PH_ERR_MASK) == PH_ERR_SUCCESS)
{
/* Signal that we've received something */
bResponseReceived = 1;
}
if ((status & PH_ERR_MASK) == PH_ERR_SUCCESS)
{
/* Check for valid response frame and remove start byte if present. */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalI18092mPI_Sw_ValidateAndNormalizeResponseFrame(
pDataParams,
pResp,
wResponseLength,
PHPAL_I18092MPI_SW_CMD_ATR_RES,
&pFrame,
&wFrameLength,
&pPayload,
&wPayloadLength));
/* Ignore length byte */
++pFrame;
--wFrameLength;
/* Check for minimum and maximum frame size. NFCForum-TS-DigitalProtocol-1.0 section 14.6.1.3. */
if ((wFrameLength > PHPAL_I18092MPI_SW_MAX_ACTIVATION_FRAME_LENGTH) ||
(wFrameLength < PHPAL_I18092MPI_SW_MIN_ACTIVATION_FRAME_LENGTH))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_I18092MPI);
}
/* Check Gt presence / absence */
if (0U != (pFrame[PHPAL_I18092MPI_SW_ATR_RES_PPT_POS] & PHPAL_I18092MPI_SW_ATR_RES_PPT_GT_AVAILABLE))
{
/* Gt should be present */
if (wFrameLength <= PHPAL_I18092MPI_SW_MIN_ACTIVATION_FRAME_LENGTH)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_I18092MPI);
}
}
else
{
/* Gt should be absent */
if (wFrameLength > PHPAL_I18092MPI_SW_MIN_ACTIVATION_FRAME_LENGTH)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_I18092MPI);
}
}
/* Protocol error in case DID is not the same. NFCForum-TS-DigitalProtocol-1.0 section 14.6.3.2. */
if (pFrame[PHPAL_I18092MPI_SW_ATR_RES_DID_POS] != bDid)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_I18092MPI);
}
/* Check NadUsed bit */
if (0U != (pFrame[PHPAL_I18092MPI_SW_ATR_RES_PPT_POS] & PHPAL_I18092MPI_SW_ATR_RES_PPT_NAD_USED))
{
/* Protocol error if NAD use is requested to be disabled */
if (bNadEnabled == PH_OFF)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_I18092MPI);
}
pDataParams->bNad = bNad;
pDataParams->bNadEnabled = PH_ON;
}
else
{
pDataParams->bNad = 0x00;
pDataParams->bNadEnabled = PH_OFF;
}
/* Copy ATR_RES to response buffer. */
(void)memcpy(pAtrRes, pFrame, wFrameLength);
*pAtrResLength = (uint8_t)wFrameLength;
/* Update LRi */
pDataParams->bLri = bLri;
/* Retrieve TO */
bTo = pAtrRes[PHPAL_I18092MPI_SW_ATR_RES_TO_POS] & 0xFU;
/* Adjust timeout field if necessary. NFCForum-TS-DigitalProtocol-1.0 section 14.6.3.8. */
if (bTo > PHPAL_I18092MPI_WT_MAX)
{
bTo = PHPAL_I18092MPI_WT_MAX;
}
/* Parse the response to see what frame size the target supports. */
pDataParams->bLrt = (pAtrRes[PHPAL_I18092MPI_SW_ATR_RES_PPT_POS] >> 4U) & 0x3U;
/* Set FSL to the lowest frame size (lowest of LRi and LRt) */
pDataParams->bFsl = (pDataParams->bLrt < pDataParams->bLri) ? pDataParams->bLrt : pDataParams->bLri;
/* Store TO */
pDataParams->bWt = bTo;
/* NfcID is now valid */
pDataParams->bNfcIdValid = PH_ON;
(void)memcpy(pDataParams->aNfcid3i, &pAtrRes[PHPAL_I18092MPI_SW_ATR_RES_NFCID3_POS], PHPAL_I18092MPI_NFCID3_LENGTH);
/* Calculate Response Waiting Time. */
dwShift = 1U;
dwRwt = (uint32_t)(PHPAL_I18092MPI_SW_RWT_MIN_US * ((dwShift << bTo)));
dwRwt += PHPAL_I18092MPI_SW_DELTA_RWT_US;
dwRwt /= 1000U;
dwRwt += 1U;
dwRwt += PHPAL_I18092MPI_SW_DELTA_T_INITIATOR_MS;
/* Set Response Waiting Time. */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(
pDataParams->pHalDataParams,
PHHAL_HW_CONFIG_TIMEOUT_VALUE_MS,
(uint16_t)dwRwt));
}
else
{
/* If HAL returned Integrity Error first time then save and return this status at the end of Retry. */
if (((status & PH_ERR_MASK) == PH_ERR_INTEGRITY_ERROR) && (bRetryCount == 0U))
{
wPreviousStatus = status;
}
/* Retransmit in case of timeout or receive error, ISO/IEC 18092:2004(E) section 12.5.1.3.1. */
if (0u != (PHPAL_I18092MPI_SW_IS_INVALID_BLOCK_STATUS(status)))
{
/* Check if we shall perform another retry. */
if (bRetryCount < pDataParams->bMaxRetryCount)
{
++bRetryCount;
bRetry = PH_ON;
if (wActiveMode == PH_ON)
{
/* Wait for T_IRFG (Initial RF guard time) before ATR retry. */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_Wait(
pDataParams->pHalDataParams,
PHHAL_HW_TIME_MILLISECONDS,
(uint16_t)PHPAL_I18092MPI_SW_TIRFG_MIN_MS));
}
}
else
{
/* Deselect target ISO/IEC 18092:2004(E) section 12.5.1.3.1. */
statusTmp = phpalI18092mPI_Sw_Deselect(pDataParams, PHPAL_I18092MPI_DESELECT_RLS);
/* Return ERR_RECOVERY_FAILED if some response has been received before (bMaxRetryCount = 0 suppresses the retry behaviour) */
if ((pDataParams->bMaxRetryCount > 0U) && (0u != bResponseReceived))
{
status = PH_ADD_COMPCODE_FIXED(PHPAL_I18092MPI_ERR_RECOVERY_FAILED, PH_COMP_PAL_I18092MPI);
}
}
}
}
}
/* Retry loop */
while (bRetry != PH_OFF);
if ((wPreviousStatus != 0U) && (status != PH_ERR_SUCCESS))
{
return wPreviousStatus;
}
return status;
}
phStatus_t phpalI18092mPI_Sw_Psl(
phpalI18092mPI_Sw_DataParams_t * pDataParams,
uint8_t bDsi,
uint8_t bDri,
uint8_t bFsl
)
{
phStatus_t PH_MEMLOC_REM status;
phStatus_t PH_MEMLOC_REM statusTmp;
uint32_t PH_MEMLOC_REM dwTimeout;
uint8_t * PH_MEMLOC_REM pResp = NULL;
uint16_t PH_MEMLOC_REM wResponseLength = 0;
uint16_t PH_MEMLOC_REM wFrameLength = 0;
uint8_t * PH_MEMLOC_REM pFrame = NULL;
uint8_t * PH_MEMLOC_REM pPayload = NULL;
uint16_t PH_MEMLOC_REM wPayloadLength = 0;
uint16_t PH_MEMLOC_REM wTxSettings = 0;
uint16_t PH_MEMLOC_REM wRxSettings = 0;
uint16_t PH_MEMLOC_REM wActiveMode;
uint8_t PH_MEMLOC_REM aCmd[3];
uint8_t PH_MEMLOC_COUNT bRetryCount = 0;
uint8_t PH_MEMLOC_REM bResponseReceived;
uint8_t PH_MEMLOC_REM bRetry;
uint8_t PH_MEMLOC_REM bCheckBaudrate = PHHAL_HW_RF_DATARATE_424;
uint8_t PH_MEMLOC_REM bNFCMode = PH_OFF;
uint32_t PH_MEMLOC_REM dwShift = 1U;
/* Parameter check */
if ((bDsi > bCheckBaudrate) ||
(bDri > bCheckBaudrate) ||
(bFsl > PHPAL_I18092MPI_FRAMESIZE_254))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_PAL_I18092MPI);
}
/* FSL shall be less than or equal to lowest of LRi and LRt */
if((bFsl > pDataParams->bLri) || (bFsl > pDataParams->bLrt))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_PAL_I18092MPI);
}
/* Prepare command */
aCmd[0] = pDataParams->bDid;
aCmd[1] = (bDsi << 3U) | bDri;
aCmd[2] = bFsl;
/* Reset response received flag */
bResponseReceived = 0;
/* Calculate Response Waiting Time. */
dwTimeout = (uint32_t)(PHPAL_I18092MPI_SW_RWT_MIN_US * ((uint32_t)(dwShift << pDataParams->bWt)));
dwTimeout += PHPAL_I18092MPI_SW_DELTA_RWT_US;
dwTimeout /= 1000U;
dwTimeout += 1U;
dwTimeout += PHPAL_I18092MPI_SW_DELTA_T_INITIATOR_MS;
/* Set Response Waiting Time as per NFCForum-TS-DigitalProtocol-1.1 section 16.11.2.3. */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(
pDataParams->pHalDataParams,
PHHAL_HW_CONFIG_TIMEOUT_VALUE_MS,
(uint16_t)dwTimeout));
/* Retry loop */
do
{
/* Reset retry flag */
bRetry = PH_OFF;
/* Write frame header and update length field. */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalI18092mPI_Sw_WriteFrameHeader(pDataParams, PH_EXCHANGE_BUFFER_FIRST, PHPAL_I18092MPI_SW_CMD_PSL_REQ, 3));
/* Write data to internal buffer and start transmission. */
status = phhalHw_Exchange(
pDataParams->pHalDataParams,
PH_EXCHANGE_BUFFER_LAST,
aCmd,
3,
&pResp,
&wResponseLength);
/* Exchange was successful */
if ((status & PH_ERR_MASK) == PH_ERR_SUCCESS)
{
/* Signal that we've received something */
bResponseReceived = 1;
}
if ((status & PH_ERR_MASK) == PH_ERR_SUCCESS)
{
/* Check for valid response frame. */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalI18092mPI_Sw_ValidateAndNormalizeResponseFrame(
pDataParams,
pResp,
wResponseLength,
PHPAL_I18092MPI_SW_CMD_PSL_RES,
&pFrame,
&wFrameLength,
&pPayload,
&wPayloadLength));
/* Protocol error in case DID is not the same. NFCForum-TS-DigitalProtocol-1.0 section 14.7.2.1. */
if ((wPayloadLength != 1U) || (pPayload[0] != pDataParams->bDid))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_I18092MPI);
}
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_GetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_ACTIVEMODE, &wActiveMode));
if (wActiveMode == PH_ON)
{
/* Set the active mode framing */
wTxSettings = aI18092_DrTable[bDsi] | PHHAL_HW_RF_TYPE_ACTIVE_FRAMING;
wRxSettings = aI18092_DrTable[bDri] | PHHAL_HW_RF_TYPE_ACTIVE_FRAMING;
}
/* For Passive Mode Framing set corresponding Technology Framing */
else
{
if (pDataParams->bPropPSLMode == PH_OFF)
{
if (aI18092_DrTable[bDsi] == PHHAL_HW_RF_DATARATE_106)
{
wTxSettings = aI18092_DrTable[bDsi] | PHHAL_HW_RF_TYPE_A_FRAMING;
}
else
{
wTxSettings = aI18092_DrTable[bDsi] | PHHAL_HW_RF_TYPE_F_FRAMING;
}
if (aI18092_DrTable[bDri] == PHHAL_HW_RF_DATARATE_106)
{
wRxSettings = aI18092_DrTable[bDri] | PHHAL_HW_RF_TYPE_A_FRAMING;
}
else
{
wRxSettings = aI18092_DrTable[bDri] | PHHAL_HW_RF_TYPE_F_FRAMING;
}
}
}
/* Apply Tx-datarate to HAL. */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(
pDataParams->pHalDataParams,
PHHAL_HW_CONFIG_TXDATARATE_FRAMING,
wTxSettings));
/* Apply Rx-datarate to HAL. */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(
pDataParams->pHalDataParams,
PHHAL_HW_CONFIG_RXDATARATE_FRAMING,
wRxSettings));
/* Configure HAL for handling StartByte in case Transmit datarate is 106kbps. */
if ((aI18092_DrTable[bDsi] == PHHAL_HW_RF_DATARATE_106) || (bNFCMode == PH_ON))
{
/* Configure HAL for NFCIP to enable handling StartByte at 106kbps. */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_NFCIP_STARTBYTE, PH_ON));
}
else
{
/* Disabled handling of StartByte if datarate is other than 106kbps. */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_NFCIP_STARTBYTE, PH_OFF));
}
/* Store protocol params */
pDataParams->bFsl = bFsl;
pDataParams->bDsi = bDsi;
pDataParams->bDri = bDri;
/* Set LRi and LRt to FSL */
pDataParams->bLri = bFsl;
pDataParams->bLrt = bFsl;
}
else
{
/* Retransmit in case of timeout or receive error, ISO/IEC 18092:2004(E) section 12.5.3.3.1. */
if (0u != (PHPAL_I18092MPI_SW_IS_INVALID_BLOCK_STATUS(status)))
{
/* Check if we shall perform a(nother) retry. */
if (bRetryCount < pDataParams->bMaxRetryCount)
{
++bRetryCount;
bRetry = PH_ON;
}
else
{
/* Deselect target ISO/IEC 18092:2004(E) section 12.5.1.3.1. */
statusTmp = phpalI18092mPI_Sw_Deselect(pDataParams, PHPAL_I18092MPI_DESELECT_RLS);
/* Return ERR_RECOVERY_FAILED if some response has been received before (bMaxRetryCount = 0 suppresses the retry behaviour) */
if ((pDataParams->bMaxRetryCount > 0U) && (0u != bResponseReceived))
{
status = PH_ADD_COMPCODE_FIXED(PHPAL_I18092MPI_ERR_RECOVERY_FAILED, PH_COMP_PAL_I18092MPI);
}
}
}
}
}
/* Retry loop */
while (bRetry != PH_OFF);
return status;
}
phStatus_t phpalI18092mPI_Sw_ActivateCard(
phpalI18092mPI_Sw_DataParams_t * pDataParams,
uint8_t * pNfcid3i,
uint8_t bDid,
uint8_t bNadEnable,
uint8_t bNad,
uint8_t bDsi,
uint8_t bDri,
uint8_t bFsl,
uint8_t * pGi,
uint8_t bGiLength,
uint8_t * pAtrRes,
uint8_t * pAtrResLength
)
{
phStatus_t PH_MEMLOC_REM statusTmp;
/* Parameter check */
if ((bDid > PHPAL_I18092MPI_DID_MAX) ||
(bDsi > PHPAL_I18092MPI_DATARATE_848) ||
(bDri > PHPAL_I18092MPI_DATARATE_848) ||
(bFsl > PHPAL_I18092MPI_FRAMESIZE_254))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_PAL_I18092MPI);
}
/* First, send ATR request command. */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalI18092mPI_Sw_Atr(pDataParams,
pNfcid3i,
bDid,
bFsl,
bNadEnable,
bNad,
pGi,
bGiLength,
pAtrRes,
pAtrResLength));
/* FSL shall be less than or equal to lowest of LRi and LRt */
bFsl = (pDataParams->bLrt < pDataParams->bLri) ? pDataParams->bLrt : pDataParams->bLri;
return phpalI18092mPI_Sw_Psl(pDataParams, bDsi, bDri, bFsl);
}
phStatus_t phpalI18092mPI_Sw_Deselect(
phpalI18092mPI_Sw_DataParams_t * pDataParams,
uint8_t bDeselectCommand
)
{
phStatus_t PH_MEMLOC_REM status;
phStatus_t PH_MEMLOC_REM statusTmp;
uint32_t PH_MEMLOC_REM dwTimeout;
uint8_t PH_MEMLOC_REM aCmd[1];
uint8_t PH_MEMLOC_REM bCmdLen = 0;
uint8_t PH_MEMLOC_REM bExpectedResponse;
uint8_t * PH_MEMLOC_REM pResp = NULL;
uint16_t PH_MEMLOC_REM wResponseLength = 0;
uint8_t * PH_MEMLOC_REM pFrame = NULL;
uint16_t PH_MEMLOC_REM wFrameLength = 0;
uint8_t * PH_MEMLOC_REM pPayload = NULL;
uint16_t PH_MEMLOC_REM wPayloadLength = 0;
uint8_t PH_MEMLOC_COUNT bRetryCount = 0;
uint8_t PH_MEMLOC_REM bResponseReceived;
uint8_t PH_MEMLOC_REM bRetry;
uint32_t PH_MEMLOC_REM dwShift = 1U;
/* Make NfcID invalid */
pDataParams->bNfcIdValid = PH_OFF;
/* Calculate Response Waiting Time. */
dwShift = 1U;
dwTimeout = (uint32_t)(PHPAL_I18092MPI_SW_RWT_MIN_US * ((uint32_t)(dwShift << pDataParams->bWt)));
dwTimeout += PHPAL_I18092MPI_SW_DELTA_RWT_US;
dwTimeout /= 1000U;
dwTimeout += 1U;
dwTimeout += PHPAL_I18092MPI_SW_DELTA_T_INITIATOR_MS;
/* Set Response Waiting Time as per NFCForum-TS-DigitalProtocol-1.1 section 16.11.2.3. */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(
pDataParams->pHalDataParams,
PHHAL_HW_CONFIG_TIMEOUT_VALUE_MS,
(uint16_t)dwTimeout));
/* Append DID if enabled */
if (pDataParams->bDid > 0U)
{
aCmd[bCmdLen++] = pDataParams->bDid;
}
/* Reset response received flag */
bResponseReceived = 0;
/* Retry loop */
do
{
/* Reset retry flag */
bRetry = PH_OFF;
/* Write frame header and update length field. */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalI18092mPI_Sw_WriteFrameHeader(pDataParams,PH_EXCHANGE_BUFFER_FIRST, bDeselectCommand, bCmdLen));
/* Start transmission. */
status = phhalHw_Exchange(pDataParams->pHalDataParams,
PH_EXCHANGE_BUFFER_LAST,
aCmd,
(uint16_t)bCmdLen,
&pResp,
&wResponseLength);
/* Exchange was successful */
if ((status & PH_ERR_MASK) == PH_ERR_SUCCESS)
{
/* Signal that we've received something */
bResponseReceived = 1;
}
/* Exchange was successful */
if ((status & PH_ERR_MASK) == PH_ERR_SUCCESS)
{
if (bDeselectCommand == PHPAL_I18092MPI_DESELECT_DSL)
{
bExpectedResponse = PHPAL_I18092MPI_SW_CMD_DSL_RES;
}
else
{
bExpectedResponse = PHPAL_I18092MPI_SW_CMD_RLS_RES;
}
/* Check for valid response frame. */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalI18092mPI_Sw_ValidateAndNormalizeResponseFrame(
pDataParams,
pResp,
wResponseLength,
bExpectedResponse,
&pFrame,
&wFrameLength,
&pPayload,
&wPayloadLength));
/* Check DID */
if (pDataParams->bDid > 0U)
{
/* Protocol error in case DID is not the same. NFCForum-TS-DigitalProtocol-1.0 section 14.9.2.1. */
if ((wPayloadLength != 1U) || (pPayload[0] != pDataParams->bDid))
{
status = PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_I18092MPI);
}
}
else
{
/* DID must not be present in response. NFCForum-TS-DigitalProtocol-1.0 section 14.9.2.1. */
if (wPayloadLength != 0U)
{
status = PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_I18092MPI);
}
}
}
else
{
/* Check if we shall perform a(nother) retry. */
if (bRetryCount < pDataParams->bMaxRetryCount)
{
++bRetryCount;
bRetry = PH_ON;
}
else
{
/* Return ERR_RECOVERY_FAILED if some response has been received before (bMaxRetryCount = 0 suppresses the retry behaviour) */
if ((pDataParams->bMaxRetryCount > 0U) && (0u != bResponseReceived))
{
status = PH_ADD_COMPCODE_FIXED(PHPAL_I18092MPI_ERR_RECOVERY_FAILED, PH_COMP_PAL_I18092MPI);
}
}
}
}
/* Retry loop */
while (bRetry != PH_OFF);
return status;
}
phStatus_t phpalI18092mPI_Sw_PresCheck(
phpalI18092mPI_Sw_DataParams_t * pDataParams
)
{
phStatus_t PH_MEMLOC_REM status;
phStatus_t PH_MEMLOC_REM statusTmp;
uint32_t PH_MEMLOC_REM dwTimeout;
uint8_t * PH_MEMLOC_REM pResp = NULL;
uint16_t PH_MEMLOC_REM wResponseLength = 0;
uint8_t * PH_MEMLOC_REM pFrame = NULL;
uint16_t PH_MEMLOC_REM wFrameLength = 0;
uint8_t * PH_MEMLOC_REM pPayload = NULL;
uint16_t PH_MEMLOC_REM wPayloadLength = 0;
uint8_t PH_MEMLOC_COUNT bRetryCount = 0;
uint8_t PH_MEMLOC_REM bResponseReceived;
uint8_t PH_MEMLOC_REM bRetry;
uint32_t PH_MEMLOC_REM dwShift = 1U;
/* Reset response received flag */
bResponseReceived = 0;
/* Calculate Response Waiting Time. */
dwTimeout = (uint32_t)(PHPAL_I18092MPI_SW_RWT_MIN_US * ((uint32_t)(dwShift << pDataParams->bWt)));
dwTimeout += PHPAL_I18092MPI_SW_DELTA_RWT_US;
dwTimeout /= 1000U;
dwTimeout += 1U;
dwTimeout += PHPAL_I18092MPI_SW_DELTA_T_INITIATOR_MS;
/* Set Response Waiting Time as per NFCForum-TS-DigitalProtocol-1.1 section 16.11.2.3. */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(
pDataParams->pHalDataParams,
PHHAL_HW_CONFIG_TIMEOUT_VALUE_MS,
(uint16_t)dwTimeout));
/* Retry loop. */
do
{
/* Reset retry flag */
bRetry = PH_OFF;
/* Write Attention PDU header. */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalI18092mPI_Sw_WritePduHeader(
pDataParams,
PHPAL_I18092MPI_SW_PFB_SUPERVISORY_PDU_MASK,
PH_OFF,
0));
/* Start transmission. */
status = phhalHw_Exchange(
pDataParams->pHalDataParams,
PH_EXCHANGE_BUFFER_LAST,
NULL,
0,
&pResp,
&wResponseLength);
/* Exchange was successful */
if ((status & PH_ERR_MASK) == PH_ERR_SUCCESS)
{
/* Signal that we've received something */
bResponseReceived = 1;
}
if ((status & PH_ERR_MASK) == PH_ERR_SUCCESS)
{
/* Check for valid response frame. */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalI18092mPI_Sw_ValidateAndNormalizeResponseFrame(
pDataParams,
pResp,
wResponseLength,
PHPAL_I18092MPI_SW_CMD_DEP_RES,
&pFrame,
&wFrameLength,
&pPayload,
&wPayloadLength));
/* Check for attention bit set. */
if ((PHPAL_I18092MPI_SW_IS_ATTENTION(pFrame[3])) == 0U)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_I18092MPI);
}
}
else
{
if (0u != (PHPAL_I18092MPI_SW_IS_INVALID_BLOCK_STATUS(status)))
{
/* Check if we shall perform a(nother) retry. */
if (bRetryCount < pDataParams->bMaxRetryCount)
{
++bRetryCount;
bRetry = PH_ON;
}
else
{
/* Return ERR_RECOVERY_FAILED if some response has been received before (bMaxRetryCount = 0 suppresses the retry behaviour) */
if ((pDataParams->bMaxRetryCount > 0U) && (0u != bResponseReceived))
{
status = PH_ADD_COMPCODE_FIXED(PHPAL_I18092MPI_ERR_RECOVERY_FAILED, PH_COMP_PAL_I18092MPI);
}
}
}
}
}
while (bRetry != PH_OFF);
return status;
}
phStatus_t phpalI18092mPI_Sw_Exchange(
phpalI18092mPI_Sw_DataParams_t * pDataParams,
uint16_t wOption,
uint8_t * pTxBuffer,
uint16_t wTxLength,
uint8_t ** ppRxBuffer,
uint16_t * pRxLength
)
{
phStatus_t PH_MEMLOC_REM status;
phStatus_t PH_MEMLOC_REM statusTmp;
/* Used to build block frames */
uint16_t PH_MEMLOC_REM wTxBufferSize;
uint16_t PH_MEMLOC_REM wTxBufferLen = 0;
uint16_t PH_MEMLOC_REM wMaxFrameSize;
uint16_t PH_MEMLOC_REM wBytesToSend;
uint8_t PH_MEMLOC_REM bHeaderLength;
/* Used for Exchange */
uint16_t PH_MEMLOC_REM wHalExchangeOption;
uint16_t PH_MEMLOC_REM wRxBufferSize;
uint16_t PH_MEMLOC_REM wRxOverlappedStartPos;
uint8_t PH_MEMLOC_REM aRxOverlapped[7];
uint8_t PH_MEMLOC_REM bBufferOverflow;
uint8_t * PH_MEMLOC_REM pRawResponse = NULL;
uint16_t PH_MEMLOC_REM wRawResponseLength = 0;
uint8_t * PH_MEMLOC_REM pNormalizedResponse = NULL;
uint16_t PH_MEMLOC_REM wNormalizedResponseLength = 0;
uint8_t * PH_MEMLOC_REM pPayloadResponse = NULL;
uint16_t PH_MEMLOC_REM wPayloadLength = 0;
/* Option parameter check */
if (0u != (wOption & (uint16_t)~(uint16_t)
(
PH_EXCHANGE_BUFFERED_BIT | PH_EXCHANGE_LEAVE_BUFFER_BIT |
PH_EXCHANGE_TXCHAINING | PH_EXCHANGE_RXCHAINING | PH_EXCHANGE_RXCHAINING_BUFSIZE
)))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_PAL_I18092MPI);
}
/* Retrieve HAL buffer sizes. */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_GetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_RXBUFFER_BUFSIZE, &wRxBufferSize));
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_GetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_TXBUFFER_BUFSIZE, &wTxBufferSize));
/* Find the biggest possible frame size before chaining is needed. */
wMaxFrameSize = (wTxBufferSize < aI18092_mPI_FsTable[pDataParams->bLrt]) ? wTxBufferSize : aI18092_mPI_FsTable[pDataParams->bLrt];
/* ACK transmission in case of Rx-Chaining */
if (((wOption & PH_EXCHANGE_MODE_MASK) == PH_EXCHANGE_RXCHAINING) ||
((wOption & PH_EXCHANGE_MODE_MASK) == PH_EXCHANGE_RXCHAINING_BUFSIZE))
{
pDataParams->bStateNow = PHPAL_I18092MPI_SW_STATE_ACK_PDU_TX | PHPAL_I18092MPI_SW_STATE_CHAINING_BIT;
}
/* PDU transmission */
else
{
/* Reset to default state if not in Tx-Mode */
if ((pDataParams->bStateNow & PHPAL_I18092MPI_SW_STATE_MASK) != PHPAL_I18092MPI_SW_STATE_INFORMATION_PDU_TX)
{
pDataParams->bStateNow = PHPAL_I18092MPI_SW_STATE_INFORMATION_PDU_TX;
}
/* Reset Retransmission requested state. */
pDataParams->bStateNow &= (uint8_t)~(uint8_t)PHPAL_I18092MPI_SW_STATE_RETRANSMIT_BIT;
}
/* Reset receive length */
*pRxLength = 0;
/* Reset Header length */
bHeaderLength = 0;
/* Reset BufferOverflow flag */
bBufferOverflow = 0;
/* ******************************** */
/* PDU TRANSMISSION LOOP */
/* ******************************** */
do
{
/* Set exchange option */
wHalExchangeOption = (uint16_t)(wOption & (uint16_t)~(uint16_t)PH_EXCHANGE_MODE_MASK);
/* Init. number of bytes to send */
wBytesToSend = wTxLength;
switch (pDataParams->bStateNow & PHPAL_I18092MPI_SW_STATE_MASK)
{
case PHPAL_I18092MPI_SW_STATE_INFORMATION_PDU_TX:
/* Forecast header length */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalI18092mPI_Sw_GetPduHeaderLength(pDataParams, &bHeaderLength));
/* Retrieve Number of preloaded bytes */
if (0U != (wOption & PH_EXCHANGE_LEAVE_BUFFER_BIT))
{
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_GetConfig(
pDataParams->pHalDataParams,
PHHAL_HW_CONFIG_TXBUFFER_LENGTH,
&wTxBufferLen));
/* Header is already included in TxBufferLen, so subtract it */
wTxBufferLen = wTxBufferLen - (uint16_t)bHeaderLength;
}
else
{
/* Nothing has been buffered */
wTxBufferLen = 0;
}
/* Check if we need to chain -> Data to be sent exceeds maximum frame size or HAL buffer */
if (((uint16_t)bHeaderLength + wTxBufferLen + wBytesToSend) > wMaxFrameSize)
{
/* If this is the first frame */
if ((0U == ((wOption & PH_EXCHANGE_LEAVE_BUFFER_BIT))))
{
/* TxBuffer needs space for at least the header */
if ((bHeaderLength + wTxBufferLen + /* */ 1U) > wMaxFrameSize)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_BUFFER_OVERFLOW, PH_COMP_PAL_I18092MPI);
}
/* Limit bytes to send */
wBytesToSend = wMaxFrameSize - (uint16_t)(wTxBufferLen + bHeaderLength);
}
/* Else send the buffered frame and transmit this frame afterwards */
else
{
wBytesToSend = 0;
}
/* If there was no chaining indicate that this is the first chain */
if ((0U == ((pDataParams->bStateNow & PHPAL_I18092MPI_SW_STATE_CHAINING_BIT))))
{
/* Indicate first chaining */
pDataParams->bStateNow |= (PHPAL_I18092MPI_SW_STATE_CHAINING_BIT | PHPAL_I18092MPI_SW_STATE_CHAINING_FIRST_BIT);
}
/* Force sending. */
wHalExchangeOption = PH_EXCHANGE_BUFFER_LAST;
}
/* Check if we are forced to chain */
if ((wOption & PH_EXCHANGE_MODE_MASK) == PH_EXCHANGE_TXCHAINING)
{
/* If there was no chaining indicate that this is the first chain */
if ((0U == ((pDataParams->bStateNow & PHPAL_I18092MPI_SW_STATE_CHAINING_BIT))))
{
/* Indicate first chaining */
pDataParams->bStateNow |= (PHPAL_I18092MPI_SW_STATE_CHAINING_BIT | PHPAL_I18092MPI_SW_STATE_CHAINING_FIRST_BIT);
}
/* Force sending. */
wHalExchangeOption = PH_EXCHANGE_BUFFER_LAST;
}
/* We are not forced to chain */
else
{
/* Nor do we need to chain */
if ((wBytesToSend == wTxLength) && (0U == ((wOption & PH_EXCHANGE_BUFFERED_BIT))))
{
/* But chaining has been performed -> this is the last chain */
if (0U != (pDataParams->bStateNow & PHPAL_I18092MPI_SW_STATE_CHAINING_BIT))
{
pDataParams->bStateNow &= (uint8_t)~(uint8_t)PHPAL_I18092MPI_SW_STATE_CHAINING_BIT;
pDataParams->bStateNow |= PHPAL_I18092MPI_SW_STATE_CHAINING_LAST_BIT;
}
}
}
/* Write PDU header */
if ((0U == ((wOption & PH_EXCHANGE_LEAVE_BUFFER_BIT))))
{
PH_CHECK_SUCCESS_FCT(statusTmp, phpalI18092mPI_Sw_WritePduHeader(
pDataParams,
PHPAL_I18092MPI_SW_PFB_INFORMATION_PDU_MASK,
((pDataParams->bStateNow & PHPAL_I18092MPI_SW_STATE_CHAINING_BIT) > 0U) ? PH_ON : PH_OFF,
(uint8_t)(wBytesToSend + wTxBufferLen)));
/* Preserve buffered data from now on */
wHalExchangeOption |= PH_EXCHANGE_LEAVE_BUFFER_BIT;
}
/* PDU Header has already been written */
else
{
/* Exchange is imminent, update length byte in HAL buffer */
if ((0U == ((wHalExchangeOption & PH_EXCHANGE_BUFFERED_BIT))))
{
PH_CHECK_SUCCESS_FCT(statusTmp, phpalI18092mPI_Sw_UpdatePduHeader(pDataParams, (uint8_t)(wBytesToSend + wTxBufferLen)));
}
}
break;
case PHPAL_I18092MPI_SW_STATE_ACK_PDU_TX:
/* Write PDU header to internal HAL buffer. Don't set the option bit (timeout in this case). */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalI18092mPI_Sw_WritePduHeader(
pDataParams,
PHPAL_I18092MPI_SW_PFB_ACK_PDU_MASK,
PH_OFF,
0));
/* No additional data */
wBytesToSend = 0;
/* Force sending. */
wHalExchangeOption = PH_EXCHANGE_BUFFER_LAST;
break;
default:
return PH_ADD_COMPCODE_FIXED(PH_ERR_INTERNAL_ERROR, PH_COMP_PAL_I18092MPI);
}
/* Transmit and receive data. */
status = phpalI18092mPI_Sw_TransceivePdu(
pDataParams,
wHalExchangeOption,
pTxBuffer,
wBytesToSend,
&pRawResponse,
&wRawResponseLength,
&pNormalizedResponse,
&wNormalizedResponseLength,
&pPayloadResponse,
&wPayloadLength);
/* Complete chaining if buffer is full */
if (((status & PH_ERR_MASK) == PH_ERR_BUFFER_OVERFLOW) &&
((wOption & PH_EXCHANGE_MODE_MASK) == PH_EXCHANGE_RXCHAINING_BUFSIZE))
{
/* Indicate Buffer Overflow */
bBufferOverflow = 1;
/* Valid information PDU received, increment PNI. NFCForum-TS-DigitalProtocol-1.0 section 14.12.3.3. */
pDataParams->bPni = PHPAL_I18092MPI_SW_INCREMENT_PNI(pDataParams->bPni);
}
/* Else bail out on error */
else
{
PH_CHECK_SUCCESS(status);
}
if (0U != (pDataParams->bStateNow & PHPAL_I18092MPI_SW_STATE_RETRANSMIT_BIT))
{
/* Retransmission requested. */
pDataParams->bStateNow &= (uint8_t)~(uint8_t)PHPAL_I18092MPI_SW_STATE_RETRANSMIT_BIT;
}
else
{
/* Advance input data buffer. */
pTxBuffer = pTxBuffer + wBytesToSend;
/* below if condition is added to make QAC compliant */
if(wTxLength > 0U)
{
wTxLength = wTxLength - wBytesToSend;
}
/* Clean-up state */
pDataParams->bStateNow &= (uint8_t)~(uint8_t)(PHPAL_I18092MPI_SW_STATE_CHAINING_FIRST_BIT | PHPAL_I18092MPI_SW_STATE_CHAINING_LAST_BIT);
/* TX is finished if no data is left to send */
if (wTxLength == 0U)
{
/* Buffered / TxChaining mode -> finished after sending */
if (((wOption & PH_EXCHANGE_BUFFERED_BIT) != 0U) ||
((wOption & PH_EXCHANGE_MODE_MASK) == PH_EXCHANGE_TXCHAINING))
{
return PH_ERR_SUCCESS;
}
/* Advance to RX state */
pDataParams->bStateNow &= (uint8_t)~(uint8_t)PHPAL_I18092MPI_SW_STATE_MASK;
pDataParams->bStateNow |= PHPAL_I18092MPI_SW_STATE_INFORMATION_PDU_RX;
/* Chained frame received, set first-chain bit */
if (0U != (pDataParams->bStateNow & PHPAL_I18092MPI_SW_STATE_CHAINING_BIT))
{
pDataParams->bStateNow |= PHPAL_I18092MPI_SW_STATE_CHAINING_FIRST_BIT;
}
}
/* TX is not finished -> reset leave-buffer bit */
else
{
wOption &= (uint16_t)~(uint16_t)PH_EXCHANGE_LEAVE_BUFFER_BIT;
}
}
}
/* Loop as long as the state does not transit to RX mode. */
while ((pDataParams->bStateNow & PHPAL_I18092MPI_SW_STATE_MASK) != PHPAL_I18092MPI_SW_STATE_INFORMATION_PDU_RX);
/* Get the biggest possible frame size we'll receive. */
wMaxFrameSize = aI18092_mPI_FsTable[pDataParams->bLri];
/* Set RxBuffer pointer to start at first received PDU */
*ppRxBuffer = pPayloadResponse;
*pRxLength = wPayloadLength;
/* Calculate overlapped byte count */
bHeaderLength = (uint8_t)(wRawResponseLength - wPayloadLength);
if (((wOption & PH_EXCHANGE_MODE_MASK) != PH_EXCHANGE_RXCHAINING) &&
((wOption & PH_EXCHANGE_MODE_MASK) != PH_EXCHANGE_RXCHAINING_BUFSIZE))
{
if ((0U !=(pDataParams->bNadEnabled)) && (bHeaderLength != 0U))
{
--bHeaderLength;
}
}
/* Init RxStartPos */
wRxOverlappedStartPos = 0;
/* ******************************** */
/* PDU RECEPTION LOOP */
/* ******************************** */
do
{
/* Only allow receive state at this point */
if ((pDataParams->bStateNow & PHPAL_I18092MPI_SW_STATE_MASK) != PHPAL_I18092MPI_SW_STATE_INFORMATION_PDU_RX)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INTERNAL_ERROR, PH_COMP_PAL_I18092MPI);
}
/* Retransmission requested. */
if (0U != (pDataParams->bStateNow & PHPAL_I18092MPI_SW_STATE_RETRANSMIT_BIT))
{
pDataParams->bStateNow &= (uint8_t)~(uint8_t)PHPAL_I18092MPI_SW_STATE_RETRANSMIT_BIT;
}
/* We're not done yet, chaining is in progress */
else if (0U != (pDataParams->bStateNow & PHPAL_I18092MPI_SW_STATE_CHAINING_BIT))
{
/* Skip overlapping / SUCCESS_CHAINING checks in case of BufferOverflow */
if (0U == (bBufferOverflow))
{
/* Skip SUCCESS_CHAINING check for RXCHAINING_BUFSIZE mode */
if ((wOption & PH_EXCHANGE_MODE_MASK) != PH_EXCHANGE_RXCHAINING_BUFSIZE)
{
/* Return with chaining status if the next chain may not fit into our buffer */
if ((*pRxLength + wMaxFrameSize) > wRxBufferSize)
{
/* Reset RxBuffer Start Position */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_RXBUFFER_STARTPOS, 0));
return PH_ADD_COMPCODE_FIXED(PH_ERR_SUCCESS_CHAINING, PH_COMP_PAL_I18092MPI);
}
}
/* Calculate start-position for overlapping */
wRxOverlappedStartPos = wRawResponseLength - (uint16_t)bHeaderLength;
if (bHeaderLength <= sizeof(aRxOverlapped))
{
/* Backup overlapped bytes */
(void)memcpy(aRxOverlapped, &pRawResponse[wRxOverlappedStartPos], bHeaderLength);
}
else
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_I18092MPI);
}
/* Adjust RX buffer start position. */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(
pDataParams->pHalDataParams,
PHHAL_HW_CONFIG_RXBUFFER_STARTPOS,
wRxOverlappedStartPos));
}
/* Chaining information PDU received, send ACK. */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalI18092mPI_Sw_WritePduHeader(
pDataParams,
PHPAL_I18092MPI_SW_PFB_ACK_PDU_MASK,
PH_OFF,
0));
/* Perform actual exchange */
status = phpalI18092mPI_Sw_TransceivePdu(
pDataParams,
PH_EXCHANGE_BUFFER_LAST,
NULL,
0,
&pRawResponse,
&wRawResponseLength,
&pNormalizedResponse,
&wNormalizedResponseLength,
&pPayloadResponse,
&wPayloadLength);
/* Complete chaining if buffer is full */
if (((status & PH_ERR_MASK) == PH_ERR_BUFFER_OVERFLOW) &&
((wOption & PH_EXCHANGE_MODE_MASK) == PH_EXCHANGE_RXCHAINING_BUFSIZE))
{
/* Reset wRxStartPos */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(
pDataParams->pHalDataParams,
PHHAL_HW_CONFIG_RXBUFFER_STARTPOS,
0));
/* Indicate Buffer Overflow */
bBufferOverflow = 1;
/* Valid information PDU received, increment PNI. NFCForum-TS-DigitalProtocol-1.0 section 14.12.3.3. */
pDataParams->bPni = PHPAL_I18092MPI_SW_INCREMENT_PNI(pDataParams->bPni);
}
/* Next chunk of PDU has been received */
else
{
/* Bail out on error */
if ((status & PH_ERR_MASK) != PH_ERR_SUCCESS)
{
/* Reset output length */
*pRxLength = 0;
/* Reset RxBuffer Start Position */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_RXBUFFER_STARTPOS, 0));
return status;
}
if (0U == (bBufferOverflow))
{
/* Restore overlapped bytes */
(void)memcpy(&pRawResponse[wRxOverlappedStartPos], aRxOverlapped, bHeaderLength); /* PRQA S 3354 */
/* Increment length */
*pRxLength = *pRxLength + wPayloadLength;
}
}
}
/* No chaining -> reception finished */
else
{
/* Reset RxBuffer Start Position */
if (wRxOverlappedStartPos != 0U)
{
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_RXBUFFER_STARTPOS, 0));
}
/* Return data */
if (0U == (bBufferOverflow))
{
pDataParams->bStateNow = PHPAL_I18092MPI_SW_STATE_FINISHED;
}
/* do not return any data in case of Buffer Overflow */
else
{
*pRxLength = 0;
return PH_ADD_COMPCODE_FIXED(PH_ERR_BUFFER_OVERFLOW, PH_COMP_PAL_I18092MPI);
}
}
}
while (pDataParams->bStateNow != PHPAL_I18092MPI_SW_STATE_FINISHED);
return PH_ERR_SUCCESS;
}
phStatus_t phpalI18092mPI_Sw_Transmit(
phpalI18092mPI_Sw_DataParams_t * pDataParams,
uint16_t wOption,
uint8_t * pTxBuffer,
uint16_t wTxLength
)
{
phStatus_t PH_MEMLOC_REM statusTmp;
/* Used to build block frames */
uint16_t PH_MEMLOC_REM wTxBufferSize;
uint16_t PH_MEMLOC_REM wTxBufferLen = 0;
uint16_t PH_MEMLOC_REM wMaxFrameSize;
uint16_t PH_MEMLOC_REM wBytesToSend;
uint8_t PH_MEMLOC_REM bHeaderLength;
/* Used for Exchange */
uint32_t PH_MEMLOC_REM dwTimeout;
uint8_t * PH_MEMLOC_REM pRawResponse = NULL;
uint8_t * PH_MEMLOC_REM pNormalizedResponse = NULL;
uint8_t * PH_MEMLOC_REM pPayloadResponse = NULL;
uint16_t PH_MEMLOC_REM wRawResponseLength = 0;
uint16_t PH_MEMLOC_REM wNormalizedResponseLength = 0;
uint16_t PH_MEMLOC_REM wPayloadLength = 0;
uint16_t PH_MEMLOC_REM wHalExchangeOption;
uint32_t PH_MEMLOC_REM dwShift = 1U;
/* Option parameter check */
if (0u != (wOption & (uint16_t)~(uint16_t)
(
PH_TRANSMIT_BUFFERED_BIT | PH_TRANSMIT_LEAVE_BUFFER_BIT | PH_TRANSMIT_TXCHAINING
)))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_PAL_I18092MPI);
}
/* Retrieve HAL buffer sizes. */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_GetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_TXBUFFER_BUFSIZE, &wTxBufferSize));
/* Find the biggest possible frame size before chaining is needed. */
wMaxFrameSize = (wTxBufferSize < aI18092_mPI_FsTable[pDataParams->bLrt]) ? wTxBufferSize : aI18092_mPI_FsTable[pDataParams->bLrt];
/* PDU transmission : Reset to default state if not in Tx-Mode */
if ((pDataParams->bStateNow & PHPAL_I18092MPI_SW_STATE_MASK) != PHPAL_I18092MPI_SW_STATE_INFORMATION_PDU_TX)
{
pDataParams->bStateNow = PHPAL_I18092MPI_SW_STATE_INFORMATION_PDU_TX;
}
/* Reset Header length */
bHeaderLength = 0;
/* ******************************** */
/* PDU TRANSMISSION LOOP */
/* ******************************** */
do
{
/* Set exchange option */
wHalExchangeOption = (uint16_t)(wOption & (uint16_t)~(uint16_t)PH_TRANSMIT_MODE_MASK);
/* Init. number of bytes to send */
wBytesToSend = wTxLength;
switch (pDataParams->bStateNow & PHPAL_I18092MPI_SW_STATE_MASK)
{
case PHPAL_I18092MPI_SW_STATE_INFORMATION_PDU_TX:
/* Forecast header length */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalI18092mPI_Sw_GetPduHeaderLength(pDataParams, &bHeaderLength));
/* Retrieve Number of preloaded bytes */
if (0U != (wOption & PH_EXCHANGE_LEAVE_BUFFER_BIT))
{
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_GetConfig(
pDataParams->pHalDataParams,
PHHAL_HW_CONFIG_TXBUFFER_LENGTH,
&wTxBufferLen));
/* Header is already included in TxBufferLen, so subtract it */
wTxBufferLen = wTxBufferLen - (uint16_t)bHeaderLength;
}
else
{
/* Nothing has been buffered */
wTxBufferLen = 0;
}
/* Check if we need to chain -> Data to be sent exceeds maximum frame size or HAL buffer */
if (((uint16_t)bHeaderLength + wTxBufferLen + wBytesToSend) > wMaxFrameSize)
{
/* If this is the first frame */
if ((0U == ((wOption & PH_EXCHANGE_LEAVE_BUFFER_BIT))))
{
/* TxBuffer needs space for at least the header */
if ((bHeaderLength + wTxBufferLen + /* */ 1U) > wMaxFrameSize)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_BUFFER_OVERFLOW, PH_COMP_PAL_I18092MPI);
}
}
/* Limit bytes to send. Send Buffered Frame + New Data that can fit into One Frame. */
wBytesToSend = wMaxFrameSize - (uint16_t)(wTxBufferLen + bHeaderLength);
/* If there was no chaining indicate that this is the first chain */
if ((0U == ((pDataParams->bStateNow & PHPAL_I18092MPI_SW_STATE_CHAINING_BIT))))
{
/* Indicate first chaining */
pDataParams->bStateNow |= (PHPAL_I18092MPI_SW_STATE_CHAINING_BIT | PHPAL_I18092MPI_SW_STATE_CHAINING_FIRST_BIT);
}
/* Force sending. */
wHalExchangeOption = PH_EXCHANGE_BUFFER_LAST;
}
/* Check if we are forced to chain */
if ((wOption & PH_EXCHANGE_MODE_MASK) == PH_EXCHANGE_TXCHAINING)
{
/* If there was no chaining indicate that this is the first chain */
if ((0U == ((pDataParams->bStateNow & PHPAL_I18092MPI_SW_STATE_CHAINING_BIT))))
{
/* Indicate first chaining */
pDataParams->bStateNow |= (PHPAL_I18092MPI_SW_STATE_CHAINING_BIT | PHPAL_I18092MPI_SW_STATE_CHAINING_FIRST_BIT);
}
/* Force sending. */
wHalExchangeOption = PH_EXCHANGE_BUFFER_LAST;
}
/* We are not forced to chain */
else
{
/* Nor do we need to chain */
if ((wBytesToSend == wTxLength) && (0U == ((wOption & PH_EXCHANGE_BUFFERED_BIT))))
{
/* But chaining has been performed -> this is the last chain */
if (0U != (pDataParams->bStateNow & PHPAL_I18092MPI_SW_STATE_CHAINING_BIT))
{
pDataParams->bStateNow &= (uint8_t)~(uint8_t)PHPAL_I18092MPI_SW_STATE_CHAINING_BIT;
pDataParams->bStateNow |= PHPAL_I18092MPI_SW_STATE_CHAINING_LAST_BIT;
}
}
}
/* Write PDU header */
if ((0U == ((wOption & PH_EXCHANGE_LEAVE_BUFFER_BIT))))
{
PH_CHECK_SUCCESS_FCT(statusTmp, phpalI18092mPI_Sw_WritePduHeader(
pDataParams,
PHPAL_I18092MPI_SW_PFB_INFORMATION_PDU_MASK,
((pDataParams->bStateNow & PHPAL_I18092MPI_SW_STATE_CHAINING_BIT) != 0U) ? PH_ON : PH_OFF,
(uint8_t)(wBytesToSend + wTxBufferLen)));
/* Preserve buffered data from now on */
wHalExchangeOption |= PH_EXCHANGE_LEAVE_BUFFER_BIT;
}
/* PDU Header has already been written */
else
{
/* Exchange is imminent, update length byte in HAL buffer */
if ((0U == ((wHalExchangeOption & PH_EXCHANGE_BUFFERED_BIT))))
{
PH_CHECK_SUCCESS_FCT(statusTmp, phpalI18092mPI_Sw_UpdatePduHeader(pDataParams, (uint8_t)(wBytesToSend + wTxBufferLen)));
}
}
break;
default:
return PH_ADD_COMPCODE_FIXED(PH_ERR_INTERNAL_ERROR, PH_COMP_PAL_I18092MPI);
}
/* If no chaining and wOption doesn't suggest Tx Buffering, then just do a transmit */
if (((0U == ((pDataParams->bStateNow & PHPAL_I18092MPI_SW_STATE_CHAINING_BIT)))) && ((0U == ((wOption & PH_TRANSMIT_BUFFERED_BIT)))) && (wBytesToSend == wTxLength))
{
/* Update Backup length with Last Bytes that will be sent. */
pDataParams->wLastTxLen = wBytesToSend + wTxBufferLen + bHeaderLength;
/* Calculate Response Waiting Time. */
dwTimeout = (uint32_t)(PHPAL_I18092MPI_SW_RWT_MIN_US * ((uint32_t)(dwShift << pDataParams->bWt)));
dwTimeout += PHPAL_I18092MPI_SW_DELTA_RWT_US;
dwTimeout /= 1000U;
dwTimeout += 1U;
dwTimeout += PHPAL_I18092MPI_SW_DELTA_T_INITIATOR_MS;
/* Set Response Waiting Time. */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(
pDataParams->pHalDataParams,
PHHAL_HW_CONFIG_TIMEOUT_VALUE_MS,
(uint16_t)dwTimeout));
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_Transmit(
pDataParams->pHalDataParams,
wHalExchangeOption,
pTxBuffer,
wBytesToSend
));
/* Advance to RX state */
pDataParams->bStateNow = PHPAL_I18092MPI_SW_STATE_INFORMATION_PDU_RX;
}
else
{
/* Send Transmit Chaining data. */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalI18092mPI_Sw_TransceivePdu(
pDataParams,
wHalExchangeOption,
pTxBuffer,
wBytesToSend,
&pRawResponse,
&wRawResponseLength,
&pNormalizedResponse,
&wNormalizedResponseLength,
&pPayloadResponse,
&wPayloadLength));
if (0U != (pDataParams->bStateNow & PHPAL_I18092MPI_SW_STATE_RETRANSMIT_BIT))
{
/* Retransmission requested. */
pDataParams->bStateNow &= (uint8_t)~(uint8_t)PHPAL_I18092MPI_SW_STATE_RETRANSMIT_BIT;
}
else
{
/* Advance input data buffer. */
pTxBuffer = pTxBuffer + wBytesToSend;
/* below if condition is added to make QAC compliant */
if(wTxLength > 0U)
{
wTxLength = wTxLength - wBytesToSend;
}
/* Clean-up state */
pDataParams->bStateNow &= (uint8_t)~(uint8_t)(PHPAL_I18092MPI_SW_STATE_CHAINING_FIRST_BIT | PHPAL_I18092MPI_SW_STATE_CHAINING_LAST_BIT);
/* TX is finished if no data is left to send */
if (wTxLength == 0U)
{
/* Buffered / TxChaining mode -> finished after sending */
if (((wOption & PH_EXCHANGE_BUFFERED_BIT) != 0U) ||
((wOption & PH_EXCHANGE_MODE_MASK) == PH_EXCHANGE_TXCHAINING))
{
return PH_ERR_SUCCESS;
}
/* Advance to RX state */
pDataParams->bStateNow &= (uint8_t)~(uint8_t)PHPAL_I18092MPI_SW_STATE_MASK;
pDataParams->bStateNow |= PHPAL_I18092MPI_SW_STATE_INFORMATION_PDU_RX;
/* State should not be set as Chaining, because Tx operation should only performed. */
if (0U != (pDataParams->bStateNow & PHPAL_I18092MPI_SW_STATE_CHAINING_BIT))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INTERNAL_ERROR, PH_COMP_PAL_I18092MPI);
}
}
/* TX is not finished -> reset leave-buffer bit */
else
{
wOption &= (uint16_t)~(uint16_t)PH_EXCHANGE_LEAVE_BUFFER_BIT;
}
}
}
}
/* Loop as long as the state does not transit to RX mode. */
while ((pDataParams->bStateNow & PHPAL_I18092MPI_SW_STATE_MASK) != PHPAL_I18092MPI_SW_STATE_INFORMATION_PDU_RX);
return PH_ERR_SUCCESS;
}
phStatus_t phpalI18092mPI_Sw_Receive(
phpalI18092mPI_Sw_DataParams_t * pDataParams,
uint16_t wOption,
uint8_t ** ppRxBuffer,
uint16_t * pRxLength
)
{
phStatus_t PH_MEMLOC_REM status;
phStatus_t PH_MEMLOC_REM statusTmp;
/* Used to build block frames */
uint16_t PH_MEMLOC_REM wMaxFrameSize;
uint16_t PH_MEMLOC_REM wBytesToSend;
uint8_t PH_MEMLOC_REM bHeaderLength;
/* Used for Exchange */
uint16_t PH_MEMLOC_REM wHalExchangeOption;
uint8_t PH_MEMLOC_REM aRxOverlapped[7];
uint16_t PH_MEMLOC_REM wRxOverlappedStartPos;
uint16_t PH_MEMLOC_REM wRxBufferSize;
uint8_t PH_MEMLOC_REM bBufferOverflow;
uint8_t * PH_MEMLOC_REM pRawResponse = NULL;
uint16_t PH_MEMLOC_REM wRawResponseLength = 0;
uint8_t * PH_MEMLOC_REM pNormalizedResponse = NULL;
uint16_t PH_MEMLOC_REM wNormalizedResponseLength = 0;
uint8_t * PH_MEMLOC_REM pPayloadResponse = NULL;
uint16_t PH_MEMLOC_REM wPayloadLength = 0;
/* Option parameter check */
if ((uint16_t)0U != (wOption & (uint16_t)~((uint16_t)PH_RECEIVE_CHAINING | (uint16_t)PH_RECEIVE_CHAINING_BUFSIZE)))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_PAL_I18092MPI);
}
/* Only allow receive state at this point */
if ((pDataParams->bStateNow & PHPAL_I18092MPI_SW_STATE_MASK) != PHPAL_I18092MPI_SW_STATE_INFORMATION_PDU_RX)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INTERNAL_ERROR, PH_COMP_PAL_I18092MPI);
}
/* Retrieve HAL buffer sizes. */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_GetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_RXBUFFER_BUFSIZE, &wRxBufferSize));
/* Reset BufferOverflow flag */
bBufferOverflow = 0;
/* Get the biggest possible frame size we'll receive. */
wMaxFrameSize = aI18092_mPI_FsTable[pDataParams->bLri];
switch(wOption)
{
case PH_RECEIVE_DEFAULT:
/* First Receive the Packet in-case Chaining is not indicated. */
statusTmp = phhalHw_Receive(
pDataParams->pHalDataParams,
PH_RECEIVE_DEFAULT,
&pRawResponse,
&wRawResponseLength);
/* Validate and update status. */
status = phpalI18092mPI_Sw_ValidateReceivedPdu(
pDataParams,
statusTmp,
&pRawResponse,
&wRawResponseLength,
&pNormalizedResponse,
&wNormalizedResponseLength,
&pPayloadResponse,
&wPayloadLength);
break;
case PH_RECEIVE_CHAINING:
case PH_RECEIVE_CHAINING_BUFSIZE:
/* Update state based on the Option. */
pDataParams->bStateNow = PHPAL_I18092MPI_SW_STATE_ACK_PDU_TX | PHPAL_I18092MPI_SW_STATE_CHAINING_BIT;
/* Write PDU header to internal HAL buffer. Don't set the option bit (timeout in this case). */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalI18092mPI_Sw_WritePduHeader(
pDataParams,
PHPAL_I18092MPI_SW_PFB_ACK_PDU_MASK,
PH_OFF,
0));
/* No additional data */
wBytesToSend = 0;
/* Force sending. */
wHalExchangeOption = PH_EXCHANGE_BUFFER_LAST;
/* Transmit and receive data. */
status = phpalI18092mPI_Sw_TransceivePdu(
pDataParams,
wHalExchangeOption,
NULL,
wBytesToSend,
&pRawResponse,
&wRawResponseLength,
&pNormalizedResponse,
&wNormalizedResponseLength,
&pPayloadResponse,
&wPayloadLength);
break;
default:
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_PAL_I18092MPI);
}
/* Complete chaining if buffer is full */
if (((status & PH_ERR_MASK) == PH_ERR_BUFFER_OVERFLOW) &&
(wOption == PH_RECEIVE_CHAINING_BUFSIZE))
{
/* Indicate Buffer Overflow */
bBufferOverflow = 1;
/* Valid information PDU received, increment PNI. NFCForum-TS-DigitalProtocol-1.0 section 14.12.3.3. */
pDataParams->bPni = PHPAL_I18092MPI_SW_INCREMENT_PNI(pDataParams->bPni);
}
/* Else bail out on error */
else
{
if ((status & PH_ERR_MASK) != PH_ERR_SUCCESS)
{
/* Reset output length */
*pRxLength = 0;
/* Reset RxBuffer Start Position */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_RXBUFFER_STARTPOS, 0));
return status;
}
}
/* Set RxBuffer pointer to start at first received PDU. */
*ppRxBuffer = pPayloadResponse;
*pRxLength = wPayloadLength;
/* Calculate overlapped byte count */
bHeaderLength = (uint8_t)(wRawResponseLength - wPayloadLength);
if ((wOption != PH_RECEIVE_CHAINING) &&
(wOption != PH_RECEIVE_CHAINING_BUFSIZE))
{
if (0U != (pDataParams->bNadEnabled))
{
--bHeaderLength;
}
}
/* Init RxStartPos */
wRxOverlappedStartPos = 0;
/* ******************************** */
/* PDU RECEPTION LOOP */
/* ******************************** */
do
{
/* Retransmission requested. */
if (0U != (pDataParams->bStateNow & PHPAL_I18092MPI_SW_STATE_RETRANSMIT_BIT))
{
pDataParams->bStateNow &= (uint8_t)~(uint8_t)PHPAL_I18092MPI_SW_STATE_RETRANSMIT_BIT;
}
/* We're not done yet, chaining is in progress */
if (0U != (pDataParams->bStateNow & PHPAL_I18092MPI_SW_STATE_CHAINING_BIT))
{
/* Skip overlapping / SUCCESS_CHAINING checks in case of BufferOverflow */
if (0U == (bBufferOverflow))
{
/* Skip SUCCESS_CHAINING check for RXCHAINING_BUFSIZE mode */
if (wOption != PH_RECEIVE_CHAINING_BUFSIZE)
{
/* Return with chaining status if the next chain may not fit into our buffer */
if ((*pRxLength + wMaxFrameSize) > wRxBufferSize)
{
/* Reset RxBuffer Start Position */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_RXBUFFER_STARTPOS, 0));
return PH_ADD_COMPCODE_FIXED(PH_ERR_SUCCESS_CHAINING, PH_COMP_PAL_I18092MPI);
}
}
/* Calculate start-position for overlapping */
wRxOverlappedStartPos = wRawResponseLength - (uint16_t)bHeaderLength;
/* Backup overlapped bytes */
(void)memcpy(aRxOverlapped, &pRawResponse[wRxOverlappedStartPos], bHeaderLength);
/* Adjust RX buffer start position. */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(
pDataParams->pHalDataParams,
PHHAL_HW_CONFIG_RXBUFFER_STARTPOS,
wRxOverlappedStartPos));
}
/* Chaining information PDU received, send ACK. */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalI18092mPI_Sw_WritePduHeader(
pDataParams,
PHPAL_I18092MPI_SW_PFB_ACK_PDU_MASK,
PH_OFF,
0));
/* Perform actual exchange */
status = phpalI18092mPI_Sw_TransceivePdu(
pDataParams,
PH_EXCHANGE_BUFFER_LAST,
NULL,
0,
&pRawResponse,
&wRawResponseLength,
&pNormalizedResponse,
&wNormalizedResponseLength,
&pPayloadResponse,
&wPayloadLength);
/* Complete chaining if buffer is full */
if (((status & PH_ERR_MASK) == PH_ERR_BUFFER_OVERFLOW) &&
(wOption == PH_RECEIVE_CHAINING_BUFSIZE))
{
/* Reset wRxStartPos */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(
pDataParams->pHalDataParams,
PHHAL_HW_CONFIG_RXBUFFER_STARTPOS,
0));
/* Indicate Buffer Overflow */
bBufferOverflow = 1;
/* Valid information PDU received, increment PNI. NFCForum-TS-DigitalProtocol-1.0 section 14.12.3.3. */
pDataParams->bPni = PHPAL_I18092MPI_SW_INCREMENT_PNI(pDataParams->bPni);
}
/* Next chunk of PDU has been received */
else
{
/* Bail out on error */
if ((status & PH_ERR_MASK) != PH_ERR_SUCCESS)
{
/* Reset output length */
*pRxLength = 0;
/* Reset RxBuffer Start Position */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_RXBUFFER_STARTPOS, 0));
return status;
}
if (0U == (bBufferOverflow))
{
/* Restore overlapped bytes */
(void)memcpy(&pRawResponse[wRxOverlappedStartPos], aRxOverlapped, bHeaderLength); /* PRQA S 3354 */
/* Increment length */
*pRxLength = *pRxLength + wPayloadLength;
}
}
}
/* No chaining -> reception finished */
else
{
/* Reset RxBuffer Start Position */
if (wRxOverlappedStartPos != 0U)
{
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_RXBUFFER_STARTPOS, 0));
}
/* Return data */
if (0U == (bBufferOverflow))
{
pDataParams->bStateNow = PHPAL_I18092MPI_SW_STATE_FINISHED;
}
/* do not return any data in case of Buffer Overflow */
else
{
*pRxLength = 0;
return PH_ADD_COMPCODE_FIXED(PH_ERR_BUFFER_OVERFLOW, PH_COMP_PAL_I18092MPI);
}
}
}
while (pDataParams->bStateNow != PHPAL_I18092MPI_SW_STATE_FINISHED);
return PH_ERR_SUCCESS;
}
phStatus_t phpalI18092mPI_Sw_SetConfig(
phpalI18092mPI_Sw_DataParams_t * pDataParams,
uint16_t wConfig,
uint16_t wValue
)
{
switch (wConfig)
{
case PHPAL_I18092MPI_CONFIG_PACKETNO:
if (wValue > PHPAL_I18092MPI_PNI_MAX)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_PAL_I18092MPI);
}
pDataParams->bPni = (uint8_t)wValue;
break;
case PHPAL_I18092MPI_CONFIG_DID:
if (wValue > PHPAL_I18092MPI_DID_MAX)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_PAL_I18092MPI);
}
pDataParams->bDid = (uint8_t)wValue;
break;
case PHPAL_I18092MPI_CONFIG_NAD:
if (0U != (wValue & 0xFF00U))
{
pDataParams->bNadEnabled = 1;
pDataParams->bNad = (uint8_t)wValue;
}
else
{
pDataParams->bNadEnabled = 0;
pDataParams->bNad = 0;
}
break;
case PHPAL_I18092MPI_CONFIG_WT:
if (wValue > PHPAL_I18092MPI_WT_MAX)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_PAL_I18092MPI);
}
pDataParams->bWt = (uint8_t)wValue;
break;
case PHPAL_I18092MPI_CONFIG_MAXRETRYCOUNT:
pDataParams->bMaxRetryCount = (uint8_t)wValue;
break;
case PHPAL_I18092MPI_CONFIG_ATN:
if((wValue != PH_ON) && (wValue != PH_OFF))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_PAL_I18092MPI);
}
pDataParams->bAtnDisabled = (uint8_t)(wValue ^ 0x0001U);
break;
default:
return PH_ADD_COMPCODE_FIXED(PH_ERR_UNSUPPORTED_PARAMETER, PH_COMP_PAL_I18092MPI);
}
return PH_ERR_SUCCESS;
}
phStatus_t phpalI18092mPI_Sw_GetConfig(
phpalI18092mPI_Sw_DataParams_t * pDataParams,
uint16_t wConfig,
uint16_t * pValue
)
{
switch (wConfig)
{
case PHPAL_I18092MPI_CONFIG_PACKETNO:
*pValue = (uint16_t)pDataParams->bPni;
break;
case PHPAL_I18092MPI_CONFIG_DID:
*pValue = (uint16_t)pDataParams->bDid;
break;
case PHPAL_I18092MPI_CONFIG_NAD:
if (0U != (pDataParams->bNadEnabled))
{
*pValue = (uint16_t)(0x0100u | pDataParams->bNad);
}
else
{
*pValue = (uint16_t)pDataParams->bNad;
}
break;
case PHPAL_I18092MPI_CONFIG_WT:
*pValue = (uint16_t)pDataParams->bWt;
break;
case PHPAL_I18092MPI_CONFIG_FSL:
*pValue = (uint16_t)pDataParams->bFsl;
break;
case PHPAL_I18092MPI_CONFIG_MAXRETRYCOUNT:
*pValue = (uint16_t)pDataParams->bMaxRetryCount;
break;
case PHPAL_I18092MPI_CONFIG_ATN:
*pValue = (uint16_t)(((uint16_t)(pDataParams->bAtnDisabled)) ^ 0x01U);
break;
case PHPAL_I18092MPI_CONFIG_ACTIVEMODE:
*pValue = (uint16_t)pDataParams->bActiveMode;
break;
default:
return PH_ADD_COMPCODE_FIXED(PH_ERR_UNSUPPORTED_PARAMETER, PH_COMP_PAL_I18092MPI);
}
return PH_ERR_SUCCESS;
}
phStatus_t phpalI18092mPI_Sw_GetSerialNo(
phpalI18092mPI_Sw_DataParams_t * pDataParams,
uint8_t * pNfcId3Out
)
{
if (pDataParams->bNfcIdValid != PH_OFF)
{
(void)memcpy(pNfcId3Out, pDataParams->aNfcid3i, PHPAL_I18092MPI_NFCID3_LENGTH);
return PH_ERR_SUCCESS;
}
else
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_USE_CONDITION, PH_COMP_PAL_I18092MPI);
}
}
phStatus_t phpalI18092mPI_Sw_Wakeup(phpalI18092mPI_Sw_DataParams_t * pDataParams)
{
phStatus_t PH_MEMLOC_REM status;
phStatus_t PH_MEMLOC_REM statusTmp;
uint16_t PH_MEMLOC_REM wResponseLength = 0;
uint8_t PH_MEMLOC_REM aCmd[11];
uint8_t PH_MEMLOC_REM bCmdLen;
uint8_t * PH_MEMLOC_REM pResp = NULL;
uint8_t * PH_MEMLOC_REM pFrame = NULL;
uint16_t PH_MEMLOC_REM wFrameLength = 0;
uint16_t PH_MEMLOC_REM wPayloadLength = 0;
uint8_t * PH_MEMLOC_REM pPayload = NULL;
uint8_t PH_MEMLOC_COUNT bRetryCount = 0;
uint8_t PH_MEMLOC_REM bResponseReceived;
uint8_t PH_MEMLOC_REM bRetry;
/* Build up frame data. */
(void)memcpy(aCmd, pDataParams->aNfcid3i, PHPAL_I18092MPI_NFCID3_LENGTH);
bCmdLen = PHPAL_I18092MPI_NFCID3_LENGTH;
aCmd[bCmdLen++] = pDataParams->bDid;
/* Reset response received flag */
bResponseReceived = 0;
/* Retry loop */
do
{
/* Reset retry flag */
bRetry = PH_OFF;
/* Write frame header and update length field. */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalI18092mPI_Sw_WriteFrameHeader(pDataParams,
PH_EXCHANGE_BUFFER_FIRST,
PHPAL_I18092MPI_SW_CMD_WUP_REQ,
bCmdLen));
/* Start transmission. */
status = phhalHw_Exchange(pDataParams->pHalDataParams,
PH_EXCHANGE_BUFFER_LAST,
aCmd,
(uint16_t)bCmdLen,
&pResp,
&wResponseLength);
/* Exchange was successful */
if ((status & PH_ERR_MASK) == PH_ERR_SUCCESS)
{
/* Signal that we've received something */
bResponseReceived = 1;
}
/* Exchange was successful */
if ((status & PH_ERR_MASK) == PH_ERR_SUCCESS)
{
/* Check for valid response frame. */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalI18092mPI_Sw_ValidateAndNormalizeResponseFrame(
pDataParams,
pResp,
wResponseLength,
PHPAL_I18092MPI_SW_CMD_WUP_RES,
&pFrame,
&wFrameLength,
&pPayload,
&wPayloadLength));
/* Protocol error in case DID is not the same. NFCForum-TS-DigitalProtocol-1.0 section 14.6.3.2. */
if ((wPayloadLength != 1U) || (pPayload[0] != pDataParams->bDid))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_I18092MPI);
}
}
else
{
/* Check if we shall perform a(nother) retry. */
if (bRetryCount < pDataParams->bMaxRetryCount)
{
++bRetryCount;
bRetry = PH_ON;
}
else
{
/* Return ERR_RECOVERY_FAILED if some response has been received before (bMaxRetryCount = 0 suppresses the retry behaviour) */
if ((pDataParams->bMaxRetryCount > 0U) && (0u != bResponseReceived))
{
status = PH_ADD_COMPCODE_FIXED(PHPAL_I18092MPI_ERR_RECOVERY_FAILED, PH_COMP_PAL_I18092MPI);
}
}
}
}
/* Retry loop */
while (bRetry != PH_OFF);
return status;
}
#endif /* NXPBUILD__PHPAL_I18092MPI_SW */