phStatus_t phpalMifare_Sw_ExchangeL3( phpalMifare_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; uint16_t PH_MEMLOC_REM wValidBits; uint16_t PH_MEMLOC_REM wCrcIn; uint16_t PH_MEMLOC_REM wCrcCalc; uint16_t PH_MEMLOC_REM RxLength; uint8_t * PH_MEMLOC_REM pRxBuffer; /* Check if caller has provided valid RxBuffer */ if (ppRxBuffer == NULL) { ppRxBuffer = &pRxBuffer; } if (pRxLength == NULL) { pRxLength = &RxLength; } /* Switch CRC modes in case of first part of exchange. */ if (!(wOption & PH_EXCHANGE_BUFFERED_BIT)) { /* Enable TxCrc */ PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_TXCRC, PH_ON)); /* Disable RxCrc */ PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_RXCRC, PH_OFF)); } /* Perform Exchange */ status = phhalHw_Exchange( pDataParams->pHalDataParams, wOption, pTxBuffer, wTxLength, ppRxBuffer, pRxLength); /* Return if no real exchange is done */ if (wOption & PH_EXCHANGE_BUFFERED_BIT) { return status; } /* ACK/NAK Handling */ if ((status & PH_ERR_MASK) == PH_ERR_SUCCESS_INCOMPLETE_BYTE) { /* Check for protocol error */ if (*pRxLength != 1) { return PH_ADD_COMPCODE(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_MIFARE); } /* Retrieve bitcount */ PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_GetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_RXLASTBITS, &wValidBits)); /* Check for protocol error */ if (wValidBits != 4) { return PH_ADD_COMPCODE(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_MIFARE); } /* ACK/NAK Mapping */ switch ((*ppRxBuffer)[0]) { /* ACK -> everything OK */ case PHPAL_MIFARE_RESP_ACK: status = PH_ERR_SUCCESS; break; /* Mapping of NAK codes: */ case PHPAL_MIFARE_RESP_NAK0: status = PHPAL_MIFARE_ERR_NAK0; break; case PHPAL_MIFARE_RESP_NAK1: status = PHPAL_MIFARE_ERR_NAK1; break; case PHPAL_MIFARE_RESP_NAK4: status = PHPAL_MIFARE_ERR_NAK4; break; case PHPAL_MIFARE_RESP_NAK5: status = PHPAL_MIFARE_ERR_NAK5; break; default: status = PH_ERR_PROTOCOL_ERROR; break; } } /* Normal data stream with CRC */ else { /* Check status */ PH_CHECK_SUCCESS(status); /* Check length (min. 1 byte + 2 byte CRC) */ if (*pRxLength < 3) { return PH_ADD_COMPCODE(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_MIFARE); } /* Retrieve CRC */ wCrcIn = (uint16_t)(((uint16_t)(*ppRxBuffer)[(*pRxLength) - 1]) << 8); wCrcIn |= (uint16_t)((*ppRxBuffer)[(*pRxLength) - 2]); /* Remove CRC from input data */ *pRxLength -= 2; /* Calculate CRC */ PH_CHECK_SUCCESS_FCT(statusTmp, phTools_CalculateCrc16( PH_TOOLS_CRC_OPTION_DEFAULT, PH_TOOLS_CRC16_PRESET_ISO14443A, PH_TOOLS_CRC16_POLY_ISO14443, *ppRxBuffer, *pRxLength, &wCrcCalc)); /* CRC Check -> Compare input and calculated crc */ if (wCrcIn == wCrcCalc) { status = PH_ERR_SUCCESS; } else { status = PH_ERR_INTEGRITY_ERROR; } } return PH_ADD_COMPCODE(status, PH_COMP_PAL_MIFARE); }
phStatus_t phpalMifare_Sw_ExchangePc( phpalMifare_Sw_DataParams_t * pDataParams, uint16_t wOption, uint8_t * pTxBuffer, uint16_t wTxLength, uint8_t ** ppRxBuffer, uint16_t * pRxLength ) { #ifdef NXPBUILD__PHPAL_I14443P4 phStatus_t PH_MEMLOC_REM status; phStatus_t PH_MEMLOC_REM statusTmp; uint8_t PH_MEMLOC_REM bIsoFrame[3]; uint16_t PH_MEMLOC_REM wIsoFrameLen; uint16_t PH_MEMLOC_REM wBlockNo; uint16_t PH_MEMLOC_REM wCidConfig; uint16_t PH_MEMLOC_REM wNadConfig; uint16_t PH_MEMLOC_REM wCrcIn; uint16_t PH_MEMLOC_REM wCrcCalc; uint16_t PH_MEMLOC_REM RxLength; uint8_t * PH_MEMLOC_REM pRxBuffer; /* Not available if no Layer4 has been set */ if (pDataParams->pPalI14443p4DataParams == NULL) { return PH_ADD_COMPCODE(PH_ERR_UNSUPPORTED_COMMAND, PH_COMP_PAL_MIFARE); } /* Ignore wOption byte */ wOption = PH_EXCHANGE_DEFAULT; /* Check if caller has provided valid RxBuffer */ if (ppRxBuffer == NULL) { ppRxBuffer = &pRxBuffer; } if (pRxLength == NULL) { pRxLength = &RxLength; } /* Retrieve ISO 14443-4 Protocol Parameters */ PH_CHECK_SUCCESS_FCT(statusTmp, phpalI14443p4_GetConfig(pDataParams->pPalI14443p4DataParams, PHPAL_I14443P4_CONFIG_BLOCKNO, &wBlockNo)); PH_CHECK_SUCCESS_FCT(statusTmp, phpalI14443p4_GetConfig(pDataParams->pPalI14443p4DataParams, PHPAL_I14443P4_CONFIG_CID, &wCidConfig)); PH_CHECK_SUCCESS_FCT(statusTmp, phpalI14443p4_GetConfig(pDataParams->pPalI14443p4DataParams, PHPAL_I14443P4_CONFIG_NAD, &wNadConfig)); /* Build ISO 14443-4 I-Block Frame */ bIsoFrame[0] = (uint8_t)(0x02 | wBlockNo); wIsoFrameLen = 1; /* Append CID if needed */ if (wCidConfig & 0xFF00) { bIsoFrame[0] |= 0x08; bIsoFrame[wIsoFrameLen++] = (uint8_t)(wCidConfig & 0x00FF); } /* Append NAD if needed */ if (wNadConfig & 0xFF00) { bIsoFrame[0] |= 0x04; bIsoFrame[wIsoFrameLen++] = (uint8_t)(wNadConfig & 0x00FF); } /* Calculate CRC over the frame */ PH_CHECK_SUCCESS_FCT(statusTmp, phTools_CalculateCrc16( PH_TOOLS_CRC_OPTION_DEFAULT, PH_TOOLS_CRC16_PRESET_ISO14443A, PH_TOOLS_CRC16_POLY_ISO14443, bIsoFrame, wIsoFrameLen, &wCrcCalc)); /* Calculate CRC over the data to send */ PH_CHECK_SUCCESS_FCT(statusTmp, phTools_CalculateCrc16( PH_TOOLS_CRC_OPTION_DEFAULT, wCrcCalc, PH_TOOLS_CRC16_POLY_ISO14443, pTxBuffer, wTxLength, &wCrcCalc)); /* Preload the frame */ PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_Exchange( pDataParams->pHalDataParams, PH_EXCHANGE_BUFFER_FIRST, bIsoFrame, wIsoFrameLen, NULL, NULL)); /* Disable Tx-/RxCRC */ PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_TXCRC, PH_OFF)); PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_RXCRC, PH_OFF)); /* Perform Exchange */ status = phhalHw_Exchange( pDataParams->pHalDataParams, PH_EXCHANGE_BUFFER_LAST, pTxBuffer, wTxLength, ppRxBuffer, pRxLength); /* Enable Tx-/RxCRC again */ PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_TXCRC, PH_ON)); PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_RXCRC, PH_ON)); /* Check for Exchange Error */ PH_CHECK_SUCCESS(status); /* Response length check */ if (*pRxLength < 2) { return PH_ADD_COMPCODE(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_MIFARE); } /* Retrieve CRC */ wCrcIn = (uint16_t)(((uint16_t)(*ppRxBuffer)[(*pRxLength) - 1]) << 8); wCrcIn |= (uint16_t)((*ppRxBuffer)[(*pRxLength) - 2]); /* Remove CRC from input data */ *pRxLength -= 2; /* Calculate CRC over the received data */ PH_CHECK_SUCCESS_FCT(statusTmp, phTools_CalculateCrc16( PH_TOOLS_CRC_OPTION_DEFAULT, wCrcCalc, PH_TOOLS_CRC16_POLY_ISO14443, *ppRxBuffer, *pRxLength, &wCrcCalc)); /* CRC Check -> Compare input and calculated crc */ if (wCrcIn != wCrcCalc) { return PH_ADD_COMPCODE(PH_ERR_INTEGRITY_ERROR, PH_COMP_PAL_MIFARE); } /* Update ISO14443-4 Block Number */ PH_CHECK_SUCCESS_FCT(statusTmp, phpalI14443p4_SetConfig(pDataParams->pPalI14443p4DataParams, PHPAL_I14443P4_CONFIG_BLOCKNO, (uint16_t)(wBlockNo ^ 0x01))); return PH_ADD_COMPCODE(PH_ERR_SUCCESS, PH_COMP_PAL_MIFARE); #else /* satisfy compiler */ if (pDataParams || wOption || pTxBuffer || wTxLength || ppRxBuffer || pRxLength); return PH_ADD_COMPCODE(PH_ERR_UNSUPPORTED_COMMAND, PH_COMP_PAL_MIFARE); #endif }
phStatus_t phpalMifare_Sw_ExchangeRaw( phpalMifare_Sw_DataParams_t * pDataParams, uint16_t wOption, uint8_t * pTxBuffer, uint16_t wTxLength, uint8_t bTxLastBits, uint8_t ** ppRxBuffer, uint16_t * pRxLength, uint8_t * pRxLastBits ) { phStatus_t PH_MEMLOC_REM status; phStatus_t PH_MEMLOC_REM statusTmp; uint16_t PH_MEMLOC_REM wValue = 0; /* Do not switch Parity / CRC modes if no real exchange is done */ if (!(wOption & PH_EXCHANGE_BUFFERED_BIT)) { /* TxLastBits > 7 is invalid */ if (bTxLastBits > 7) { return PH_ADD_COMPCODE(PH_ERR_INVALID_PARAMETER, PH_COMP_PAL_MIFARE); } /* Retrieve Parity-setting */ PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_GetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_PARITY, &wValue)); /* Disable Parity */ if (wValue == PH_ON) { PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_PARITY, PH_OFF)); } /* Disable TxCrc */ PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_TXCRC, PH_OFF)); /* Disable RxCrc */ PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_RXCRC, PH_OFF)); /* Set TxLastBits */ PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_TXLASTBITS, bTxLastBits)); } else { /* TxLastBits != 0 is invalid for buffered operation */ if (bTxLastBits != 0) { return PH_ADD_COMPCODE(PH_ERR_INVALID_PARAMETER, PH_COMP_PAL_MIFARE); } } /* Perform Exchange */ status = phhalHw_Exchange( pDataParams->pHalDataParams, wOption, pTxBuffer, wTxLength, ppRxBuffer, pRxLength); /* Return if no real exchange is done */ if (wOption & PH_EXCHANGE_BUFFERED_BIT) { return status; } /* Restore Parity-setting again since many PAL layers expect it */ if (wValue == PH_ON) { PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_PARITY, wValue)); } /* Retrieve RxLastBits */ if ((status & PH_ERR_MASK) == PH_ERR_SUCCESS_INCOMPLETE_BYTE) { PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_GetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_RXLASTBITS, &wValue)); *pRxLastBits = (uint8_t)wValue; } else { PH_CHECK_SUCCESS(status); } return PH_ADD_COMPCODE(PH_ERR_SUCCESS, PH_COMP_PAL_MIFARE); }
phStatus_t phpalI14443p4a_Sw_Rats( phpalI14443p4a_Sw_DataParams_t * pDataParams, uint8_t bFsdi, uint8_t bCid, uint8_t * pAts ) { phStatus_t PH_MEMLOC_REM status; phStatus_t PH_MEMLOC_REM statusTmp; uint8_t PH_MEMLOC_REM cmd[2]; uint8_t PH_MEMLOC_REM bAtsIndex; uint8_t PH_MEMLOC_REM bSfgi; uint32_t PH_MEMLOC_REM dwSfgt; uint32_t PH_MEMLOC_REM dwFwt; uint8_t * PH_MEMLOC_REM pResp; uint16_t PH_MEMLOC_REM wRespLength; /* Parameter check */ if ((bFsdi > 8) || (bCid > 14)) { return PH_ADD_COMPCODE(PH_ERR_INVALID_PARAMETER, PH_COMP_PAL_ISO14443P4A); } /* Set Activation timeout */ PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig( pDataParams->pHalDataParams, PHHAL_HW_CONFIG_TIMEOUT_VALUE_US, PHPAL_I14443P4A_SW_FWT_ACTIVATION_US + PHPAL_I14443P4A_SW_EXT_TIME_US)); /* Send Rats command */ cmd[0] = PHPAL_I14443P4A_SW_RATS; cmd[1] = (uint8_t)(((bFsdi << 4) & 0xF0) | (bCid & 0x0F)); status = phhalHw_Exchange( pDataParams->pHalDataParams, PH_EXCHANGE_DEFAULT, cmd, 2, &pResp, &wRespLength); if ((status & PH_ERR_MASK) == PH_ERR_SUCCESS) { /* Check for protocol error */ if (((uint8_t)wRespLength != pResp[0]) || (wRespLength < 1)) { return PH_ADD_COMPCODE(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_ISO14443P4A); } /* Copy ATS buffer */ memcpy(pAts, pResp, wRespLength); /* PRQA S 3200 */ /* Set default values */ /* */ pDataParams->bCidSupported = PH_OFF; pDataParams->bCid = 0x00; pDataParams->bNadSupported = PH_OFF; pDataParams->bBitRateCaps = 0x00; pDataParams->bFwi = PHPAL_I14443P4A_SW_FWI_DEFAULT; pDataParams->bFsdi = bFsdi; pDataParams->bFsci = PHPAL_I14443P4A_SW_FSCI_DEFAULT; pDataParams->bDri = 0x00; pDataParams->bDsi = 0x00; bSfgi = PHPAL_I14443P4A_SW_SFGI_DEFAULT; /* Retrieve ATS information */ /* Start parsing with T0 byte */ bAtsIndex = PHPAL_I14443P4A_SW_ATS_T0; /* Parse T0/TA/TB/TC */ if (wRespLength > 1) { /* Parse T0 */ pDataParams->bFsci = pAts[bAtsIndex] & 0x0F; if (pDataParams->bFsci > 8) { pDataParams->bFsci = 8; } bAtsIndex++; /* Parse TA(1) */ if (pAts[PHPAL_I14443P4A_SW_ATS_T0] & PHPAL_I14443P4A_SW_ATS_TA1_PRESENT) { /* Check for protocol error */ if (wRespLength <= bAtsIndex) { return PH_ADD_COMPCODE(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_ISO14443P4A); } else { /* Store Bitrate capabilities */ pDataParams->bBitRateCaps = pAts[bAtsIndex]; bAtsIndex++; } } /* Parse TB(1) */ if (pAts[PHPAL_I14443P4A_SW_ATS_T0] & PHPAL_I14443P4A_SW_ATS_TB1_PRESENT) { /* Check for protocol error */ if (wRespLength <= bAtsIndex) { return PH_ADD_COMPCODE(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_ISO14443P4A); } else { /* Store Sfgi */ bSfgi = pAts[bAtsIndex] & 0x0F; if (bSfgi == 0x0F) { bSfgi = PHPAL_I14443P4A_SW_SFGI_DEFAULT; } /* Store Fwi */ pDataParams->bFwi = (pAts[bAtsIndex] >> 4) & 0x0F; if (pDataParams->bFwi == 0x0F) { pDataParams->bFwi = PHPAL_I14443P4A_SW_FWI_DEFAULT; } bAtsIndex++; } } /* Parse TC(1) */ if (pAts[PHPAL_I14443P4A_SW_ATS_T0] & PHPAL_I14443P4A_SW_ATS_TC1_PRESENT) { /* Check for protocol error */ if (wRespLength <= bAtsIndex) { return PH_ADD_COMPCODE(PH_ERR_PROTOCOL_ERROR, PH_COMP_PAL_ISO14443P4A); } else { /* Check NAD Support */ if (pAts[bAtsIndex] & PHPAL_I14443P4A_SW_ATS_TC1_NAD_SUPPORT) { pDataParams->bNadSupported = 1; } /* Check CID Support */ if (pAts[bAtsIndex] & PHPAL_I14443P4A_SW_ATS_TC1_CID_SUPPORT) { pDataParams->bCidSupported = 1; pDataParams->bCid = bCid; } } } } /* Calculate SFGT in Microseconds */ dwSfgt = (uint32_t)(PHPAL_I14443P4A_SW_FWT_MIN_US * (1 << bSfgi)); /* Perform SFGT Wait */ if (dwSfgt > 0xFFFF) { PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_Wait( pDataParams->pHalDataParams, PHHAL_HW_TIME_MILLISECONDS, (uint16_t)(dwSfgt / 1000))); } else { PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_Wait( pDataParams->pHalDataParams, PHHAL_HW_TIME_MICROSECONDS, (uint16_t)dwSfgt)); } /* Calculate FWT timeout */ dwFwt = (uint32_t)(PHPAL_I14443P4A_SW_FWT_MIN_US * (1 << pDataParams->bFwi)); /* Add extension time */ dwFwt = dwFwt + PHPAL_I14443P4A_SW_EXT_TIME_US; /* Set FWT timeout */ if (dwFwt > 0xFFFF) { /* +1 is added to the timeout in millisecond to compensate the * fractional microseconds lost in division by 1000 */ PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig( pDataParams->pHalDataParams, PHHAL_HW_CONFIG_TIMEOUT_VALUE_MS, (uint16_t)((dwFwt / 1000) + 1))); } else { PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig( pDataParams->pHalDataParams, PHHAL_HW_CONFIG_TIMEOUT_VALUE_US, (uint16_t)dwFwt)); } }