Exemplo n.º 1
0
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);
}
Exemplo n.º 2
0
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
}
Exemplo n.º 3
0
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);
}
Exemplo n.º 4
0
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));
        }
    }