Files
NxpNfcRdLib/.svn/pristine/17/17027d3ca797352debf775f04b72179f7ecd80d0.svn-base
2024-07-08 21:03:06 +08:00

785 lines
28 KiB
Plaintext

/*----------------------------------------------------------------------------*/
/* Copyright 2010-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 FeliCa Component of Reader Library Framework.
* $Author$
* $Revision$ (v07.10.00)
* $Date$
*
*/
#include <ph_Status.h>
#include <phhalHw.h>
#include <phpalFelica.h>
#include <ph_RefDefs.h>
#ifdef NXPBUILD__PHPAL_FELICA_SW
#include "phpalFelica_Sw.h"
#include "phpalFelica_Sw_Int.h"
/* Table for 4^E evaluation (E is only 2 bits, so more values are not possible). */
static const uint8_t PH_MEMLOC_CONST_ROM aFelica_E_Table[] = {1, 4, 16, 64};
#define FDTF_LISTEN_SENSF_REQ(x, y) ((PHPAL_FELICA_SW_T_DELAY_US + ((x) * PHPAL_FELICA_SW_T_TIMESLOT_US)) + y) /**< NFC Forum Digital Protocol Technical Specification v1.1 : 8.7.1 : FDTF,LISTEN,SENSF_REQ */
static const uint16_t PH_MEMLOC_CONST_ROM aFelica_TR1_Value_Us[][2] = {
{PHPAL_FELICA_SW_TR1_48BITS_AT212_US, PHPAL_FELICA_SW_TR1_48BITS_AT424_US},
{PHPAL_FELICA_SW_TR1_56BITS_AT212_US, PHPAL_FELICA_SW_TR1_56BITS_AT424_US},
{PHPAL_FELICA_SW_TR1_64BITS_AT212_US, PHPAL_FELICA_SW_TR1_64BITS_AT424_US},
{PHPAL_FELICA_SW_TR1_72BITS_AT212_US, PHPAL_FELICA_SW_TR1_72BITS_AT424_US},
};
phStatus_t phpalFelica_Sw_Init(
phpalFelica_Sw_DataParams_t * pDataParams,
uint16_t wSizeOfDataParams,
void * pHalDataParams
)
{
/* parameter structure length check */
if (sizeof(phpalFelica_Sw_DataParams_t) != wSizeOfDataParams)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_DATA_PARAMS, PH_COMP_PAL_FELICA);
}
PH_ASSERT_NULL (pDataParams);
PH_ASSERT_NULL (pHalDataParams);
/* init private data */
pDataParams->wId = PH_COMP_PAL_FELICA | PHPAL_FELICA_SW_ID;
pDataParams->pHalDataParams = pHalDataParams;
pDataParams->bIDmPMmValid = PHPAL_FELICA_SW_IDMPMM_INVALID;
pDataParams->bLength = 0x00;
pDataParams->bRequestCode = 0x00;
pDataParams->bPreambleLen = PHPAL_FELICA_PREAMBLE_LEN_48BITS;
return PH_ERR_SUCCESS;
}
phStatus_t phpalFelica_Sw_ReqC(
phpalFelica_Sw_DataParams_t* pDataParams,
uint8_t * pSystemCode,
uint8_t bNumTimeSlots,
uint8_t ** ppRxBuffer,
uint16_t * pRxLength
)
{
phStatus_t PH_MEMLOC_REM status;
phStatus_t PH_MEMLOC_REM statusTmp;
uint8_t PH_MEMLOC_REM aCmd[6];
uint8_t * PH_MEMLOC_REM pRxBufferTmp = NULL;
uint16_t PH_MEMLOC_REM wRxLengthTmp = 0;
uint16_t PH_MEMLOC_REM wTimeOutUs;
uint16_t PH_MEMLOC_REM wCardType = 0;
uint16_t PH_MEMLOC_REM wTR1ValueUs;
/* reset validity of stored card IDs */
pDataParams->bIDmPMmValid = PHPAL_FELICA_SW_IDMPMM_INVALID;
/* Reset received frame count */
pDataParams->bTotalFrames = 0;
/* parameter check and timeout setting */
if(!((bNumTimeSlots == PHPAL_FELICA_NUMSLOTS_1) ||
(bNumTimeSlots == PHPAL_FELICA_NUMSLOTS_2) ||
(bNumTimeSlots == PHPAL_FELICA_NUMSLOTS_4) ||
(bNumTimeSlots == PHPAL_FELICA_NUMSLOTS_8) ||
(bNumTimeSlots == PHPAL_FELICA_NUMSLOTS_16))
)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_PAL_FELICA);
}
else
{
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_GetConfig(
pDataParams->pHalDataParams,
PHHAL_HW_CONFIG_CARD_TYPE,
&wCardType));
/* NFC Forum Digital Protocol Technical Specification v2.3
* 8.7.1.3 : wTimeOutUs = FDTF,LISTEN,SENSF_REQ(TSN+1U) - TR1 + (delta)TF,POLL
* Using TR1 value @212kbps */
if ((wCardType != PHHAL_HW_CARDTYPE_FELICA_212) && (wCardType != PHHAL_HW_CARDTYPE_FELICA_424))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_USE_CONDITION, PH_COMP_PAL_FELICA);
}
if (wCardType == PHHAL_HW_CARDTYPE_FELICA_212)
{
wTR1ValueUs = aFelica_TR1_Value_Us[pDataParams->bPreambleLen][0];
}
else
{
wTR1ValueUs = aFelica_TR1_Value_Us[pDataParams->bPreambleLen][1];
}
wTimeOutUs = FDTF_LISTEN_SENSF_REQ((((uint16_t)bNumTimeSlots) + 1U), wTR1ValueUs) - wTR1ValueUs + PHPAL_FELICA_SW_T_DELTA_F_POLL_US;
}
/* build the command frame */
aCmd[0] = 6;
aCmd[1] = PHPAL_FELICA_SW_CMD_REQC;
aCmd[2] = pSystemCode[0];
aCmd[3] = pSystemCode[1];
aCmd[4] = pDataParams->bRequestCode;
aCmd[5] = bNumTimeSlots;
/* Set ReqC timeout according to the number of slots */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(
pDataParams->pHalDataParams,
PHHAL_HW_CONFIG_TIMEOUT_VALUE_US,
wTimeOutUs));
if(bNumTimeSlots > PHPAL_FELICA_NUMSLOTS_1)
{
/* Set RX Multiple feature of HW */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(
pDataParams->pHalDataParams,
PHHAL_HW_CONFIG_RXMULTIPLE,
PH_ON));
}
/* Exchange command */
status = phhalHw_Exchange(
pDataParams->pHalDataParams,
PH_EXCHANGE_DEFAULT,
aCmd,
6,
&pRxBufferTmp,
&wRxLengthTmp);
if(bNumTimeSlots > PHPAL_FELICA_NUMSLOTS_1)
{
/* Re-Set RX Multiple feature of HW */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(
pDataParams->pHalDataParams,
PHHAL_HW_CONFIG_RXMULTIPLE,
PH_OFF));
}
/* Error check */
PH_CHECK_SUCCESS(status);
/* Check length and update info*/
if(bNumTimeSlots > PHPAL_FELICA_NUMSLOTS_1)
{
/* Rx Length should be multiple of response frame size */
if(0U != (wRxLengthTmp % PHPAL_FELICA_SW_RESP_FRAME_SIZE))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_FELICA);
}
/* assign and update IDm and PMm and length */
*ppRxBuffer = pRxBufferTmp;
*pRxLength = wRxLengthTmp;
pDataParams->bTotalFrames = (uint8_t)(wRxLengthTmp / PHPAL_FELICA_SW_RESP_FRAME_SIZE);
}
else
{
if (((wRxLengthTmp != (PHPAL_FELICA_ATQC_LENGTH + 1U)) &&
(wRxLengthTmp != (PHPAL_FELICA_ATQC_LENGTH + PHPAL_FELICA_RD_LENGTH + 1U))) ||
(pRxBufferTmp[0] != wRxLengthTmp) ||
(pRxBufferTmp[1] != PHPAL_FELICA_SW_RSP_REQC))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_FELICA);
}
/* RC = 0 and card response with RD information */
if((wRxLengthTmp == (PHPAL_FELICA_ATQC_LENGTH + PHPAL_FELICA_RD_LENGTH + 1U)) && (pDataParams->bRequestCode == 0U))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_FELICA);
}
/* Store IDm and PMm */
(void)memcpy(pDataParams->aIDmPMm, &pRxBufferTmp[2], (((uint32_t)(pRxBufferTmp[0])) - 2U));
pDataParams->bIDmPMmValid = PHPAL_FELICA_SW_IDMPMM_VALID;
/* Remove LEN Byte and Response Byte from response and assign start position of ID */
*ppRxBuffer = &pRxBufferTmp[PHPAL_FELICA_SW_LEN_BYTE_SIZE + PHPAL_FELICA_SW_RESP_REQC_SIZE];
*pRxLength = (uint16_t)(((uint16_t)pRxBufferTmp[0]) - (PHPAL_FELICA_SW_LEN_BYTE_SIZE + PHPAL_FELICA_SW_RESP_REQC_SIZE));
pDataParams->bTotalFrames = 1;
}
pDataParams->bIDmPMmValid = PHPAL_FELICA_SW_IDMPMM_VALID;
return PH_ERR_SUCCESS;
}
phStatus_t phpalFelica_Sw_GetFrameInfo(
phpalFelica_Sw_DataParams_t* pDataParams,
uint8_t bFrameNum,
uint8_t * pResponseBuffer,
uint16_t *pwStatus,
uint8_t** ppID,
uint8_t * pLen
)
{
uint8_t PH_MEMLOC_REM bError;
uint8_t PH_MEMLOC_REM bStartPos;
/* check frame number */
if((bFrameNum > pDataParams->bTotalFrames) || (bFrameNum == 0U))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_PAL_FELICA);
}
*pwStatus = PH_ERR_SUCCESS;
/* get start position of frame */
bStartPos = (uint8_t)(PHPAL_FELICA_SW_RESP_FRAME_SIZE * (bFrameNum - 1U));
/* Check length */
if( ((pResponseBuffer[bStartPos + PHHAL_HW_STATUS_FRAME_LEN_BYTE_POS] != (PHPAL_FELICA_ATQC_LENGTH + PHPAL_FELICA_SW_LEN_BYTE_SIZE)) &&
(pResponseBuffer[bStartPos + PHHAL_HW_STATUS_FRAME_LEN_BYTE_POS] != (PHPAL_FELICA_ATQC_LENGTH + PHPAL_FELICA_RD_LENGTH + PHPAL_FELICA_SW_LEN_BYTE_SIZE))) ||
(pResponseBuffer[bStartPos + 1U] != PHPAL_FELICA_SW_RSP_REQC))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_FELICA);
}
/* RC = 0 and card response with RD information */
if((pResponseBuffer[bStartPos + PHHAL_HW_STATUS_FRAME_LEN_BYTE_POS] == (PHPAL_FELICA_ATQC_LENGTH + PHPAL_FELICA_RD_LENGTH + PHPAL_FELICA_SW_LEN_BYTE_SIZE)) && (pDataParams->bRequestCode == 0U))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_FELICA);
}
/* Extract error from Status byte */
bError = pResponseBuffer[(bStartPos) + PHHAL_HW_STATUS_FRAME_ERR_BYTE_POS ] & PHHAL_HW_STATUS_FRAME_ERR_MASK;
if(bError != 0x00U)
{
/* check for contact less error */
if(0U != (bError & PHHAL_HW_STATUS_FRAME_CL_ERR_POS))
{
/* check for protocol error */
if(0U != (bError & PHHAL_HW_STATUS_FRAME_PROT_ERR_POS))
{
*pwStatus = PH_ERR_PROTOCOL_ERROR;
}
/* check for collision error */
else if(0U != (bError & PHHAL_HW_STATUS_FRAME_COLL_ERR_POS))
{
*pwStatus = PH_ERR_COLLISION_ERROR;
}
/* check for Integrity error */
else if(0U != (bError & PHHAL_HW_STATUS_FRAME_DATA_ERR_POS))
{
*pwStatus = PH_ERR_INTEGRITY_ERROR;
}
else
{
/* If CL Error is set and no Protocol, Collision, Integrity flag is set */
return (PH_ERR_PROTOCOL_ERROR | PH_COMP_PAL_FELICA);
}
}
else
{ /* Length error */
*pwStatus = PH_ERR_LENGTH_ERROR;
}
}
else
{
/* Remove LEN Byte and Response Byte (0x01) from response and assign start position of ID */
*ppID = &pResponseBuffer[bStartPos + (PHPAL_FELICA_SW_LEN_BYTE_SIZE + PHPAL_FELICA_SW_RESP_REQC_SIZE)];
*pLen = pResponseBuffer[bStartPos + PHHAL_HW_STATUS_FRAME_LEN_BYTE_POS] - (PHPAL_FELICA_SW_LEN_BYTE_SIZE + PHPAL_FELICA_SW_RESP_REQC_SIZE);
}
return PH_ERR_SUCCESS;
}
phStatus_t phpalFelica_Sw_SetSerialNo(
phpalFelica_Sw_DataParams_t * pDataParams,
uint8_t * pIDmPMm
)
{
pDataParams->bIDmPMmValid = PHPAL_FELICA_SW_IDMPMM_VALID;
/* copy IDm and PMm */
(void)memcpy(pDataParams->aIDmPMm, pIDmPMm, (PHPAL_FELICA_IDM_LENGTH + PHPAL_FELICA_PMM_LENGTH));
return PH_ERR_SUCCESS;
}
phStatus_t phpalFelica_Sw_ActivateCard(
phpalFelica_Sw_DataParams_t* pDataParams,
uint8_t* pIDmPMm,
uint8_t bIDmPMmLength,
uint8_t * pSystemCode,
uint8_t bNumTimeSlots,
uint8_t * pRxBuffer,
uint8_t * pRxLength,
uint8_t * pMoreCardsAvailable
)
{
phStatus_t PH_MEMLOC_REM status;
uint8_t * PH_MEMLOC_REM pId = NULL;
uint8_t * PH_MEMLOC_REM pRxBuff = NULL;
uint16_t PH_MEMLOC_REM wRxLen = 0;
uint8_t PH_MEMLOC_REM bTemp;
uint16_t PH_MEMLOC_REM wFrameStatus;
*pRxLength = 0;
*pMoreCardsAvailable = 0;
/* if serial number is given only store it */
if (0U != (bIDmPMmLength))
{
/* check if IDm length is valid. */
if (bIDmPMmLength != (PHPAL_FELICA_IDM_LENGTH + PHPAL_FELICA_PMM_LENGTH))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_PAL_FELICA);
}
/* Store IDm/PMm */
(void)memcpy(pDataParams->aIDmPMm, pIDmPMm, bIDmPMmLength);
pDataParams->bIDmPMmValid = PHPAL_FELICA_SW_IDMPMM_VALID;
return PH_ERR_SUCCESS;
}
do{
/* RequestC == ReqC command (not requesting the system code) */
status = phpalFelica_Sw_ReqC(
pDataParams,
pSystemCode,
bNumTimeSlots,
&pRxBuff,
&wRxLen);
if(bNumTimeSlots > PHPAL_FELICA_NUMSLOTS_1)
{
if(pDataParams->bTotalFrames > 1U)
{
*pMoreCardsAvailable = 1;
}
/* get total number of response frame */
bTemp = pDataParams->bTotalFrames;
while(0U != bTemp)
{
*pRxLength = 0x00;
wFrameStatus = 0x00;
/* retrieve IDmPMm one by one for all frames */
PH_CHECK_SUCCESS_FCT(status, phpalFelica_Sw_GetFrameInfo(
pDataParams,
bTemp,
pRxBuff,
&wFrameStatus,
&pId,
pRxLength));
status = wFrameStatus;
/* store only one valid response and return */
if(wFrameStatus == PH_ERR_SUCCESS)
{
*pRxLength = PHPAL_FELICA_IDM_LENGTH + PHPAL_FELICA_PMM_LENGTH;
(void)memcpy(pRxBuffer, pId, (PHPAL_FELICA_IDM_LENGTH + PHPAL_FELICA_PMM_LENGTH));
(void)memcpy(pDataParams->aIDmPMm, pId, (PHPAL_FELICA_IDM_LENGTH + PHPAL_FELICA_PMM_LENGTH));
pDataParams->bIDmPMmValid = PHPAL_FELICA_SW_IDMPMM_VALID;
return status;
}
bTemp--;
}
}
else
{
if ((status & PH_ERR_MASK) == PH_ERR_SUCCESS)
{
*pRxLength = PHPAL_FELICA_IDM_LENGTH + PHPAL_FELICA_PMM_LENGTH;
(void)memcpy(pRxBuffer, pRxBuff, (PHPAL_FELICA_IDM_LENGTH + PHPAL_FELICA_PMM_LENGTH));
(void)memcpy(pDataParams->aIDmPMm, pRxBuff, (PHPAL_FELICA_IDM_LENGTH + PHPAL_FELICA_PMM_LENGTH));
pDataParams->bIDmPMmValid = PHPAL_FELICA_SW_IDMPMM_VALID;
return status;
}
}
/* check for availability of more card */
if((status & PH_ERR_MASK) == PH_ERR_COLLISION_ERROR)
{
*pMoreCardsAvailable = 1;
bNumTimeSlots = (bNumTimeSlots << 1U) + 1U;
}
else
{
return status;
}
}while (bNumTimeSlots <= PHPAL_FELICA_NUMSLOTS_16);
return status;
}
phStatus_t phpalFelica_Sw_Exchange(
phpalFelica_Sw_DataParams_t* pDataParams,
uint16_t wOption,
uint16_t wN,
uint8_t* pTxBuffer,
uint16_t wTxLength,
uint8_t ** ppRxBuffer,
uint16_t * pRxLength
)
{
phStatus_t PH_MEMLOC_REM statusTmp;
uint8_t PH_MEMLOC_REM aHeader[2];
uint16_t PH_MEMLOC_REM wCmd;
uint32_t PH_MEMLOC_REM dwTimeoutUs;
uint8_t PH_MEMLOC_REM bTparam;
uint8_t PH_MEMLOC_REM bA;
uint8_t PH_MEMLOC_REM bB;
uint8_t PH_MEMLOC_REM bE;
uint8_t * PH_MEMLOC_REM pPMm = NULL;
uint32_t PH_MEMLOC_REM dwTOut;
/* [len][cmd] [IDm ... 8 bytes] [cmd parameters ...] */
/* Check if we do have an IDm */
if (pDataParams->bIDmPMmValid == PHPAL_FELICA_SW_IDMPMM_INVALID)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_FELICA);
}
/* Parameter check */
if ((wTxLength + /* */ 2U) > PHPAL_FELICA_TXLENGTH_MAX)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_PAL_FELICA);
}
/* If the PH_EXCHANGE_LEAVE_BUFFER_BIT is NOT set, wOption is:
~ PH_EXCHANGE_DEFAULT: we have the command byte and eventually parameter bytes (data),
how ever, we already have all data to exchange the complete frame.
~ PH_EXCHANGE_BUFFER_FIRST: we have the command byte and eventually parameter bytes (data),
but the callee wants to transmit some more.
pDataParams->bLength < 2 -> the cmd byte was not transmitted yet
*/
if ((0U == ((wOption & PH_EXCHANGE_LEAVE_BUFFER_BIT))) || (pDataParams->bLength < 2U))
{
/* If there is nothing to transmit, we are done. */
if (wTxLength == 0U)
{
return PH_ERR_SUCCESS;
}
/* Prepare header */
aHeader[0] = 0x00; /* This is just a dummy which is updated with the correct value later on,
when the last chunk is ready to transmit. */
aHeader[1] = pTxBuffer[0];
/* Buffer the header */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_Exchange(
pDataParams->pHalDataParams,
PH_EXCHANGE_BUFFER_FIRST,
aHeader,
2,
ppRxBuffer,
pRxLength));
/* until now, we have transmitted 2 bytes: */
pDataParams->bLength = 2;
/* following Hw_Echange calls shall not overwrite already buffered data */
wOption |= PH_EXCHANGE_LEAVE_BUFFER_BIT;
/* Check if IDm has to be send */
wCmd = (uint16_t)pTxBuffer[0];
switch (wCmd)
{
case PHPAL_FELICA_SW_CMD_REQ_RESP:
case PHPAL_FELICA_SW_CMD_REQ_SERVICE:
case PHPAL_FELICA_SW_CMD_READ:
case PHPAL_FELICA_SW_CMD_WRITE:
case PHPAL_FELICA_SW_CMD_AUTH1:
case PHPAL_FELICA_SW_CMD_AUTH2:
/* If there is no more parameter bytes (data) to send, we adjust pointer and length
for the LAST Exchange, the IDm */
if (wTxLength == 1U)
{
pTxBuffer = pDataParams->aIDmPMm;
wTxLength = PHPAL_FELICA_IDM_LENGTH;
}
else
{
/* Set pointer and length for the LAST exchange. */
pTxBuffer++;
wTxLength = wTxLength - 1u;
/* Transmit the IDm */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_Exchange(
pDataParams->pHalDataParams,
PH_EXCHANGE_BUFFER_CONT,
pDataParams->aIDmPMm,
PHPAL_FELICA_IDM_LENGTH,
ppRxBuffer,
pRxLength));
pDataParams->bLength = pDataParams->bLength + PHPAL_FELICA_IDM_LENGTH;
}
break;
default:
/* Set pointer and length for the LAST exchange. */
pTxBuffer++;
wTxLength = wTxLength - 1u;
break;
}
}
else
{
/* command byte already buffered */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_TXBUFFER_OFFSET, 0x01));
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_GetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_TXBUFFER, &wCmd));
}
/* Length check */
if ((pDataParams->bLength + wTxLength) > PHPAL_FELICA_TXLENGTH_MAX)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_LENGTH_ERROR, PH_COMP_PAL_FELICA);
}
/* If the PH_EXCHANGE_BUFFERED_BIT IS set, wOption is:
~ PH_EXCHANGE_BUFFER_FIRST, or
~ PH_EXCHANGE_BUFFER_CONT: This means that there is data which shall be put into the
buffer but not to be sent yet since more data will follow. */
if (0U != (wOption & PH_EXCHANGE_BUFFERED_BIT))
{
if (wTxLength > 0U)
{
/* Exchange command */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_Exchange(
pDataParams->pHalDataParams,
wOption,
pTxBuffer,
wTxLength,
ppRxBuffer,
pRxLength));
pDataParams->bLength = pDataParams->bLength + (uint8_t)wTxLength;
}
return PH_ERR_SUCCESS;
}
/* If the PH_EXCHANGE_BUFFERED_BIT is NOT set, wOption is:
~ PH_EXCHANGE_DEFAULT, or
~ PH_EXCHANGE_BUFFER_LAST: This means that either this is the last (or only) chunk
of command parameters (data), which also could be of zero bytes.
So this is the last chunk and we should received a response,
which we extrakt the IDm bytes from and also check them. */
pDataParams->bLength = pDataParams->bLength + (uint8_t)(wTxLength);
/* Update the length byte which had been sent before */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_TXBUFFER_OFFSET, 0x00));
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_TXBUFFER, (uint16_t)pDataParams->bLength));
/* Reset precached length */
pDataParams->bLength = 0x00;
/* Get stored PMm */
pPMm = &pDataParams->aIDmPMm[PHPAL_FELICA_IDM_LENGTH];
/* Command and PMm evaluation */
switch(wCmd)
{
case PHPAL_FELICA_SW_CMD_REQ_SERVICE:
bTparam = pPMm[2];
break;
case PHPAL_FELICA_SW_CMD_REQ_RESP:
bTparam = pPMm[3];
break;
case PHPAL_FELICA_SW_CMD_AUTH1:
case PHPAL_FELICA_SW_CMD_AUTH2:
bTparam = pPMm[4];
break;
case PHPAL_FELICA_SW_CMD_READ:
case PHPAL_FELICA_SW_CMD_READ_SECF:
bTparam = pPMm[5];
break;
case PHPAL_FELICA_SW_CMD_WRITE:
case PHPAL_FELICA_SW_CMD_WRITE_SECF:
bTparam = pPMm[6];
break;
default:
bTparam = pPMm[7];
break;
}
/* Get timing parameters */
bA = bTparam & 0x07U;
bB = (bTparam >> 3U) & 0x07U;
bE = (bTparam >> 6U) & 0x03U;
/* Timeout calculation */
/* Response time = T x [(B + 1U) x n + (A + 1U)] x 4^E */
dwTOut = ((((uint32_t)bB + 1U) * (uint32_t)wN) + ((uint32_t)bA + 1U));
dwTimeoutUs = (uint32_t)(PHPAL_FELICA_SW_TIME_T_US * dwTOut * aFelica_E_Table[bE]);
dwTimeoutUs = dwTimeoutUs + PHPAL_FELICA_SW_DELTA_TIME_T_US;
/* Timeout setting in Milliseconds */
if (dwTimeoutUs > 0xFFFFU)
{
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(
pDataParams->pHalDataParams,
PHHAL_HW_CONFIG_TIMEOUT_VALUE_MS,
(uint16_t)(dwTimeoutUs / 1000U)));
}
/* Timeout setting in Microseconds */
else
{
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(
pDataParams->pHalDataParams,
PHHAL_HW_CONFIG_TIMEOUT_VALUE_US,
(uint16_t)dwTimeoutUs));
}
/* Exchange command */
PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_Exchange(
pDataParams->pHalDataParams,
PH_EXCHANGE_BUFFER_LAST,
pTxBuffer,
wTxLength,
ppRxBuffer,
pRxLength));
/* Check length */
if ((*pRxLength < 1U) || ((*ppRxBuffer)[0] != *pRxLength))
{
*pRxLength = 0;
return PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_FELICA);
}
/* Skip length */
--(*pRxLength);
++(*ppRxBuffer);
/* Check response code */
if ((*pRxLength < 1U) || ((*ppRxBuffer)[0] != (wCmd + 1U)))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_FELICA);
}
/* Skip response code */
--(*pRxLength);
++(*ppRxBuffer);
/* Check and skip IDm if received */
switch (wCmd)
{
case PHPAL_FELICA_SW_CMD_REQ_RESP:
case PHPAL_FELICA_SW_CMD_REQ_SERVICE:
case PHPAL_FELICA_SW_CMD_READ:
case PHPAL_FELICA_SW_CMD_WRITE:
case PHPAL_FELICA_SW_CMD_AUTH1:
/* Protocol error check */
if (*pRxLength < PHPAL_FELICA_IDM_LENGTH)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_FELICA);
}
/* We can only check the IDm if we have a valid one stored */
if (memcmp(*ppRxBuffer, pDataParams->aIDmPMm, PHPAL_FELICA_IDM_LENGTH) != 0)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_FELICA);
}
/* Skip IDm */
*pRxLength = *pRxLength - PHPAL_FELICA_IDM_LENGTH;
*ppRxBuffer = *ppRxBuffer + PHPAL_FELICA_IDM_LENGTH;
break;
default:
break;
}
return PH_ERR_SUCCESS;
}
phStatus_t phpalFelica_Sw_SetConfig(
phpalFelica_Sw_DataParams_t* pDataParams,
uint16_t wConfig,
uint16_t wValue
)
{
switch(wConfig)
{
case PHPAL_FELICA_CONFIG_RC:
if(((uint8_t)wValue != 0x00U) && ((uint8_t)wValue != 0x01U))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_PAL_FELICA);
}
pDataParams->bRequestCode = (uint8_t)(wValue);
break;
case PHPAL_FELICA_PREAMBLE_LENGTH:
if(!((wValue == PHPAL_FELICA_PREAMBLE_LEN_48BITS) ||
(wValue == PHPAL_FELICA_PREAMBLE_LEN_56BITS) ||
(wValue == PHPAL_FELICA_PREAMBLE_LEN_64BITS) ||
(wValue == PHPAL_FELICA_PREAMBLE_LEN_72BITS))
)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_PAL_FELICA);
}
pDataParams->bPreambleLen = (uint8_t)(wValue);
break;
default:
return PH_ADD_COMPCODE_FIXED(PH_ERR_UNSUPPORTED_PARAMETER, PH_COMP_PAL_FELICA);
}
return PH_ERR_SUCCESS;
}
phStatus_t phpalFelica_Sw_GetConfig(
phpalFelica_Sw_DataParams_t* pDataParams,
uint16_t wConfig,
uint16_t * pValue
)
{
switch(wConfig)
{
case PHPAL_FELICA_CONFIG_RC:
*pValue = (uint16_t)pDataParams->bRequestCode;
break;
case PH_PALFELICA_CONFIG_NUM_RESPONSE_FRAMES:
*pValue = (uint16_t)pDataParams->bTotalFrames;
break;
default:
return PH_ADD_COMPCODE_FIXED(PH_ERR_UNSUPPORTED_PARAMETER, PH_COMP_PAL_FELICA);
}
return PH_ERR_SUCCESS;
}
phStatus_t phpalFelica_Sw_GetSerialNo(
phpalFelica_Sw_DataParams_t* pDataParams,
uint8_t * pIDmPMmOut,
uint8_t * pLenIDmPMmOut
)
{
/* Return an error if IDm and PMm are not valid */
if (pDataParams->bIDmPMmValid == PHPAL_FELICA_SW_IDMPMM_INVALID)
{
*pLenIDmPMmOut = 0;
return PH_ADD_COMPCODE_FIXED(PH_ERR_USE_CONDITION, PH_COMP_PAL_FELICA);
}
/* copy the IDm and PMm */
(void)memcpy(pIDmPMmOut, pDataParams->aIDmPMm, PHPAL_FELICA_IDM_LENGTH + PHPAL_FELICA_PMM_LENGTH);
*pLenIDmPMmOut = PHPAL_FELICA_IDM_LENGTH + PHPAL_FELICA_PMM_LENGTH;
return PH_ERR_SUCCESS;
}
#endif /* NXPBUILD__PHPAL_FELICA_SW */