phStatus_t phhalHw_SamAV2_Rc523_GetFdt(
                                       phhalHw_SamAV2_DataParams_t * pDataParams,
                                       uint32_t * pTime
                                       )
{
    phStatus_t  PH_MEMLOC_REM statusTmp;
    uint8_t     PH_MEMLOC_REM bRegister;
    uint16_t    PH_MEMLOC_REM wDataRate;
    uint16_t    PH_MEMLOC_REM wPsReload;
    uint16_t    PH_MEMLOC_REM wTReload;
    uint16_t    PH_MEMLOC_REM wTValue;
    float32_t   PH_MEMLOC_REM fTimeout;

    /* Retrieve RxDataRate */
    PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_GetConfig(pDataParams, PHHAL_HW_CONFIG_RXDATARATE, &wDataRate));
    wDataRate++;

    /* Get prescaler value */
    PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_ReadRegister(pDataParams, PHHAL_HW_SAMAV2_RC523_REG_TMODE, &bRegister));
    wPsReload = (uint16_t)(bRegister & PHHAL_HW_SAMAV2_RC523_MASK_TPRESCALER_HI) << 8;
    PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_ReadRegister(pDataParams, PHHAL_HW_SAMAV2_RC523_REG_TPRESCALER, &bRegister));
    wPsReload |= (uint16_t)bRegister;

    /* Get reload value */
    PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_ReadRegister(pDataParams, PHHAL_HW_SAMAV2_RC523_REG_TRELOADHI, &bRegister));
    wTReload = (uint16_t)bRegister << 8;
    PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_ReadRegister(pDataParams, PHHAL_HW_SAMAV2_RC523_REG_TRELOADLO, &bRegister));
    wTReload |= (uint16_t)bRegister;

    /* Get counter value */
    PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_ReadRegister(pDataParams, PHHAL_HW_SAMAV2_RC523_REG_TCOUNTERVALHI, &bRegister));
    wTValue = (uint16_t)bRegister << 8;
    PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_ReadRegister(pDataParams, PHHAL_HW_SAMAV2_RC523_REG_TCOUNTERVALLO, &bRegister));
    wTValue |= (uint16_t)bRegister;

    /* Subtract reload- and counter values */
    wTValue = wTReload - wTValue;

    /* Calculate the timeout value */
    fTimeout = ((float32_t)wTValue * (1.0f + (2.0f * (float32_t)wPsReload))) / PHHAL_HW_SAMAV2_TIMER_FREQ;

    /* Subtract timershift from timeout value */
    fTimeout = fTimeout - (PHHAL_HW_SAMAV2_RC523_TIMER_SHIFT * (PHHAL_HW_SAMAV2_ETU_106 / (float32_t)wDataRate));

    /* Return the value */
    *pTime = (uint32_t)fTimeout;

    /* Round the value if neccessary */
    if ((fTimeout - (float32_t)*pTime) >= 0.5)
    {
        ++(*pTime);
    }

    return PH_ADD_COMPCODE(PH_ERR_SUCCESS, PH_COMP_HAL);
}
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_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 phhalHw_SamAV2_Rc523_SetFdt(
                                       phhalHw_SamAV2_DataParams_t * pDataParams,
                                       uint8_t bUnit,
                                       uint16_t wTimeout
                                       )
{
    phStatus_t  PH_MEMLOC_REM statusTmp;
    float32_t   PH_MEMLOC_REM fTimeoutUs;
    float32_t   PH_MEMLOC_REM fTemp;
    uint8_t     PH_MEMLOC_REM bTPrescaler;
    uint8_t     PH_MEMLOC_REM bRegister;
    uint16_t    PH_MEMLOC_REM wDataRate;
    uint16_t    PH_MEMLOC_REM wPrescaler;
    uint16_t    PH_MEMLOC_REM wReload;

    /* Retrieve RxDataRate */
    PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_GetConfig(pDataParams, PHHAL_HW_CONFIG_RXDATARATE, &wDataRate));
    wDataRate++;

    /* Handle timeout in microseconds */
    if (bUnit == PHHAL_HW_TIME_MICROSECONDS)
    {
        fTimeoutUs = (float32_t)wTimeout;
    }
    else
    {
        fTimeoutUs = (float32_t)wTimeout * 1000.0f;
    }

    /* Add timershift to timeout value */
    fTimeoutUs = fTimeoutUs + (PHHAL_HW_SAMAV2_RC523_TIMER_SHIFT * (PHHAL_HW_SAMAV2_ETU_106 / (float32_t)wDataRate));

    /* Max. timeout check */
    if (fTimeoutUs > PHHAL_HW_SAMAV2_RC523_TIMER_MAX_VALUE_US)
    {
        return PH_ADD_COMPCODE(PH_ERR_PARAMETER_OVERFLOW, PH_COMP_HAL);
    }

    /* Read Prescaler value */
    PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_ReadRegister(pDataParams, PHHAL_HW_SAMAV2_RC523_REG_TPRESCALER, &bTPrescaler));
    PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_ReadRegister(pDataParams, PHHAL_HW_SAMAV2_RC523_REG_TMODE, &bRegister));

    /* Get prescaler value */
    wPrescaler = ((uint16_t)(bRegister & PHHAL_HW_SAMAV2_RC523_MASK_TPRESCALER_HI) << 8) | bTPrescaler;

    /* Calculate the reload value */
    fTemp = (fTimeoutUs * PHHAL_HW_SAMAV2_TIMER_FREQ) / (1.0f + (2.0f * (float32_t)wPrescaler));

    /* Except for a special case, the float32_t value will have some commas
    and therefore needs to be "ceiled" */
    if (fTemp > (float32_t)(uint16_t)fTemp)
    {
        wReload = (uint16_t)(fTemp + 1);
    }
    else
    {
        wReload = (uint16_t)fTemp;
    }

    /* write reload value */
    PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_WriteRegister(pDataParams, PHHAL_HW_SAMAV2_RC523_REG_TRELOADLO, (uint8_t)(wReload & 0xFF)));
    PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_WriteRegister(pDataParams, PHHAL_HW_SAMAV2_RC523_REG_TRELOADHI, (uint8_t)((wReload >> 8) & 0xFF)));

    return PH_ADD_COMPCODE(PH_ERR_SUCCESS, PH_COMP_HAL);
}
phStatus_t phhalHw_SamAV2_Rc523_Wait(
                                     phhalHw_SamAV2_DataParams_t * pDataParams,
                                     uint8_t bUnit,
                                     uint16_t wTimeout
                                     )
{
    phStatus_t  PH_MEMLOC_REM statusTmp;
    uint8_t     PH_MEMLOC_REM bRegister;
    uint8_t		PH_MEMLOC_REM bIrqRq;
    uint16_t    PH_MEMLOC_REM wTimerShift;
    uint16_t    PH_MEMLOC_REM wTimeoutNew;

    /* Parameter check */
    if ((bUnit != PHHAL_HW_TIME_MICROSECONDS) && (bUnit != PHHAL_HW_TIME_MILLISECONDS))
    {
        return PH_ADD_COMPCODE(PH_ERR_INVALID_PARAMETER, PH_COMP_HAL);
    }

    /* Terminate a probably running command */
    PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_WriteRegister(pDataParams, PHHAL_HW_SAMAV2_RC523_REG_COMMAND, PHHAL_HW_SAMAV2_RC523_CMD_IDLE));

    /* Retrieve RxDataRate */
    PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_GetConfig(pDataParams, PHHAL_HW_CONFIG_RXDATARATE, &wTimerShift));
    ++wTimerShift;

    /* Calculate timershift */
    wTimerShift = (uint16_t)(PHHAL_HW_SAMAV2_RC523_TIMER_SHIFT * (PHHAL_HW_SAMAV2_ETU_106 / (float32_t)wTimerShift));

    /* do as long as we have an overflow in the IC timer */
    do
    {
        /* Set temporary timeout */
        if (bUnit == PHHAL_HW_TIME_MICROSECONDS)
        {
            wTimeoutNew = (wTimeout > wTimerShift) ? (wTimeout - wTimerShift) : 0;
            PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SamAV2_Rc523_SetFdt(pDataParams, PHHAL_HW_TIME_MICROSECONDS, wTimeoutNew));
            wTimeout = 0;
        }
        else
        {
            /* Timer would overflow -> use maximum value and decrement overall value for next iteration */
            if (wTimeout > ((PHHAL_HW_SAMAV2_RC523_TIMER_MAX_VALUE_US / 1000) - 1))
            {
                wTimeoutNew = (PHHAL_HW_SAMAV2_RC523_TIMER_MAX_VALUE_US / 1000) - 1;
                PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SamAV2_Rc523_SetFdt(pDataParams, PHHAL_HW_TIME_MILLISECONDS, wTimeoutNew));
                wTimeout = wTimeout - wTimeoutNew;
            }
            /* No overflow -> set the complete time */
            else
            {
                PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SamAV2_Rc523_SetFdt(pDataParams, PHHAL_HW_TIME_MILLISECONDS, wTimeout));
                wTimeout = 0;
            }
        }

        /* retrieve content of Control register */
        PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_ReadRegister(pDataParams, PHHAL_HW_SAMAV2_RC523_REG_CONTROL, &bRegister));

        /* enable timer interrupt */
        PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_WriteRegister(pDataParams, PHHAL_HW_SAMAV2_RC523_REG_COMMIEN, PHHAL_HW_SAMAV2_RC523_BIT_TIMERI));

        /* clear all irq flags */
        PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_WriteRegister(pDataParams, PHHAL_HW_SAMAV2_RC523_REG_COMMIRQ, (uint8_t)~(uint8_t)PHHAL_HW_SAMAV2_RC523_BIT_SET));

        /* start timer */
        bRegister |= PHHAL_HW_SAMAV2_RC523_BIT_TSTARTNOW;
        PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_WriteRegister(pDataParams, PHHAL_HW_SAMAV2_RC523_REG_CONTROL, bRegister));

        /* wait for timer interrupt */
        do
        {
            PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_ReadRegister(pDataParams, PHHAL_HW_SAMAV2_RC523_REG_COMMIRQ, &bIrqRq));
        }
        while (!(bIrqRq & (PHHAL_HW_SAMAV2_RC523_BIT_ERRI | PHHAL_HW_SAMAV2_RC523_BIT_TIMERI)));

        /* clear all irq flags */
        PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_WriteRegister(pDataParams, PHHAL_HW_SAMAV2_RC523_REG_COMMIRQ, (uint8_t)~(uint8_t)PHHAL_HW_SAMAV2_RC523_BIT_SET));
    }
    while (wTimeout > 0);

    /* Restore previous timeout */
    if (pDataParams->bTimeoutUnit == PHHAL_HW_TIME_MICROSECONDS)
    {
        PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SamAV2_Rc523_SetFdt(
            pDataParams,
            PHHAL_HW_TIME_MICROSECONDS,
            pDataParams->wCfgShadow[PHHAL_HW_CONFIG_TIMEOUT_VALUE_US]));
    }
    else
    {
        PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SamAV2_Rc523_SetFdt(
            pDataParams,
            PHHAL_HW_TIME_MILLISECONDS,
            pDataParams->wCfgShadow[PHHAL_HW_CONFIG_TIMEOUT_VALUE_MS]));
    }

    return PH_ADD_COMPCODE(PH_ERR_SUCCESS, PH_COMP_HAL);
}
示例#6
0
phStatus_t phalMfdf_Sw_Int_IsoRead(
                                   phalMfdf_Sw_DataParams_t * pDataParams,
                                   uint16_t wOption,
                                   uint8_t * bCmdBuff,
                                   uint16_t wCmdLen,
                                   uint8_t ** ppRxBuffer,
                                   uint16_t * pBytesRead
                                   )
{
    phStatus_t  PH_MEMLOC_REM status;
    uint16_t    PH_MEMLOC_REM statusTmp;
    uint16_t    PH_MEMLOC_REM wRxBufferSize;
    uint16_t    PH_MEMLOC_REM wNextPos;
    uint16_t    PH_MEMLOC_REM wRxlen;
    uint16_t    PH_MEMLOC_REM wTmp;
    uint8_t     PH_MEMLOC_REM *pRecv;
    uint8_t     PH_MEMLOC_REM bBackupBytes[3];

    status = phpalMifare_ExchangeL4(
        pDataParams->pPalMifareDataParams,
        wOption,
        bCmdBuff,
        wCmdLen,
        ppRxBuffer,
        pBytesRead
        );

    /* First put everything on the reader Rx buffer upto buffer size - 60 */
    wRxlen = *pBytesRead;
    pRecv = *ppRxBuffer;

    if ((status != PH_ERR_SUCCESS) && ((status & PH_ERR_MASK) != PH_ERR_SUCCESS_CHAINING))
    {

        return status;
    }

    while ((status & PH_ERR_MASK) == PH_ERR_SUCCESS_CHAINING)
    {
        PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_GetConfig(
            pDataParams->pHalDataParams,
            PHHAL_HW_CONFIG_RXBUFFER_BUFSIZE,
            &wRxBufferSize
            ));

        wNextPos = *pBytesRead;
        memcpy(bBackupBytes, &pRecv[wNextPos - 3], 3); /* PRQA S 3200 */

        if (wNextPos + PHAL_MFDF_MAX_FRAME_SIZE >= wRxBufferSize)
        {
            /* Calculate partical cmac if authenticated and return PH_ERR_SUCCESS_CHAINING */
            break;
        }

        PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(
            pDataParams->pHalDataParams,
            PHHAL_HW_CONFIG_RXBUFFER_STARTPOS,
            wNextPos
            ));
        status = phpalMifare_ExchangeL4(
            pDataParams->pPalMifareDataParams,
            PH_EXCHANGE_RXCHAINING,
            bCmdBuff,
            wCmdLen,
            ppRxBuffer,
            pBytesRead
            );

        /* Put back the backed up bytes */
        memcpy(&pRecv[wNextPos - 3], bBackupBytes, 3); /* PRQA S 3200 */

        if ((status != PH_ERR_SUCCESS) && 
            ((status & PH_ERR_MASK) != PH_ERR_SUCCESS_CHAINING))
        {

            return status;
        }
        wRxlen = *pBytesRead;
    }

    /* The data is now in *ppRxBuffer, length = wRxlen */

    /* Size of MAC bytes */
    wTmp = 0x08;

    if (status == PH_ERR_SUCCESS)
    {
        statusTmp = (*ppRxBuffer)[*pBytesRead - 2]; /* SW1 */
        statusTmp = statusTmp << 8; /* Shift SW1 to MSB */
        statusTmp |= (*ppRxBuffer)[*pBytesRead - 1]; /* SW2 */

        if (pDataParams->bAuthMode == PHAL_MFDF_NOT_AUTHENTICATED)
        {
            *pBytesRead -= 2; 
            return phalMfdf_Int_ComputeErrorResponse(pDataParams, statusTmp);
        }

        statusTmp = phalMfdf_Int_ComputeErrorResponse(pDataParams, statusTmp);
        if (statusTmp != PH_ERR_SUCCESS)
        {

            return statusTmp;
        }
    }
    return PH_ADD_COMPCODE((status & PH_ERR_MASK), PH_COMP_AL_MFDF);
}
示例#7
0
phStatus_t phalMfdf_Sw_Int_GetData(
                                   phalMfdf_Sw_DataParams_t * pDataParams,
                                   uint8_t * pSendBuff,
                                   uint16_t wCmdLen,
                                   uint8_t ** pResponse,
                                   uint16_t * pRxlen
                                   )
{
    uint16_t   PH_MEMLOC_REM wOption;
    uint8_t    PH_MEMLOC_REM * pRecv;
    phStatus_t PH_MEMLOC_REM statusTmp = 0;
    uint8_t    PH_MEMLOC_REM bStatusByte = 0xFF;
    uint8_t    PH_MEMLOC_REM bCmdBuff[10];
    uint8_t    PH_MEMLOC_REM bBackupByte = 0;
    uint16_t   PH_MEMLOC_REM wNextPos = 0;
    uint16_t   PH_MEMLOC_REM wRxBufferSize = 0;
    uint8_t    PH_MEMLOC_REM bBackupBytes[3];
    uint8_t    PH_MEMLOC_REM pApdu[5] = { PHAL_MFDF_WRAPPEDAPDU_CLA, 0x00, PHAL_MFDF_WRAPPEDAPDU_P1, PHAL_MFDF_WRAPPEDAPDU_P2, 0x00 };
    uint8_t    PH_MEMLOC_REM bBackUpByte;
    uint8_t    PH_MEMLOC_REM bBackUpByte1;
    uint16_t   PH_MEMLOC_REM wBackUpLen;
    uint16_t   PH_MEMLOC_REM wTmp = 0;

    /* Status and two other bytes to be backed up before getting new frame of data */
    memset(bBackupBytes, 0x00, 3); /* PRQA S 3200 */

    PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_GetConfig(pDataParams->pHalDataParams,
        PHHAL_HW_CONFIG_RXBUFFER_STARTPOS,
        &wTmp
        ));

    wOption = PH_EXCHANGE_DEFAULT;
    if (pDataParams->bWrappedMode)
    {
        if (wCmdLen > PHAL_MFDF_MAXWRAPPEDAPDU_SIZE)
        {
            return PH_ADD_COMPCODE(PH_ERR_BUFFER_OVERFLOW, PH_COMP_AL_MFDF);
        }

        pApdu[1] = pSendBuff[0];  /* Desfire command code. */
        /* Encode APDU Length*/
        pApdu[4]= (uint8_t)wCmdLen - 1; /* Set APDU Length. */

        statusTmp = phpalMifare_ExchangeL4(
            pDataParams->pPalMifareDataParams,
            pApdu[4] == 0x00 ? PH_EXCHANGE_DEFAULT : PH_EXCHANGE_BUFFER_FIRST,
            pApdu,
            PHAL_MFDF_WRAP_HDR_LEN,
            &pRecv,
            pRxlen
            );
        if ((pApdu[4] != 0x00) && (statusTmp == PH_ERR_SUCCESS))
        {
            PH_CHECK_SUCCESS_FCT(statusTmp, phpalMifare_ExchangeL4(
                pDataParams->pPalMifareDataParams,
                PH_EXCHANGE_BUFFER_CONT,
                &pSendBuff[1],
                wCmdLen - 1,
                &pRecv,
                pRxlen
                ));

            statusTmp = phpalMifare_ExchangeL4(
                pDataParams->pPalMifareDataParams,
                PH_EXCHANGE_BUFFER_LAST,
                &pApdu[2],
                0x01,
                &pRecv,
                pRxlen
                );
        }
        /* To handle the case where the card returns only status 91 and returns
        AF in the next frame */
        if ((statusTmp & PH_ERR_MASK) == PH_ERR_SUCCESS_CHAINING)
        {
            if (((pDataParams->bWrappedMode) && (*pRxlen == 2)) ||
                ((!(pDataParams->bWrappedMode)) && (*pRxlen == 1)))
            {
                /* AF should always be accompanied by data. Otherwise
                it is a protocol error */
                return PH_ADD_COMPCODE(PH_ERR_PROTOCOL_ERROR, PH_COMP_AL_MFDF);
            }
            /* One more status byte to read from DesFire */
            bBackUpByte = pRecv[0];
            bBackUpByte1 = pRecv[1];
            wBackUpLen = *pRxlen;

            PH_CHECK_SUCCESS_FCT(statusTmp, phpalMifare_ExchangeL4(
                pDataParams->pPalMifareDataParams,
                PH_EXCHANGE_RXCHAINING,
                &pApdu[2],
                0x01,
                &pRecv,
                pRxlen
                ));

            /* Received length can be one or two Ex: 0x91 0xAF */
            if (*pRxlen == 2)
            {
                pRecv[wBackUpLen] = pRecv[0];
                pRecv[wBackUpLen + 1] = pRecv[1];
                bStatusByte = pRecv[1];
            }
            else if (*pRxlen == 1)
            {
                bStatusByte = pRecv[0];
                pRecv[wBackUpLen] = bStatusByte;
            }
            else
            {
                return PH_ADD_COMPCODE(PH_ERR_PROTOCOL_ERROR, PH_COMP_AL_MFDF);
            }

            *pRxlen = wBackUpLen + *pRxlen;

            /* Set back the backed up bytes */
            pRecv[0] = bBackUpByte;
            pRecv[1] = bBackUpByte1;
        }
        else
        {
            if (statusTmp != PH_ERR_SUCCESS)
            {
                return statusTmp;
            }
        }
    }
    else
    {
        /* Normal mode */
        if (wCmdLen > PHAL_MFDF_MAXDFAPDU_SIZE)
        {
            return PH_ADD_COMPCODE(PH_ERR_BUFFER_OVERFLOW, PH_COMP_AL_MFDF);
        }

        /* Send this on L4 */
        PH_CHECK_SUCCESS_FCT(statusTmp, phpalMifare_ExchangeL4(
            pDataParams->pPalMifareDataParams,
            wOption,
            pSendBuff,
            wCmdLen,
            &pRecv,
            pRxlen
            ));
    }

    /* Storing the original pointer */
    *pResponse = pRecv;

    /* Status is 0xAF or Ox00? */
    if (*pRxlen > 0x0000)
    {
        if (pDataParams->bWrappedMode)
        {
            bStatusByte = (*pResponse)[(*pRxlen) - 1];
        } 
        else 
        {
            bStatusByte = (*pResponse)[wTmp];
        }
    }

    if (bStatusByte == PHAL_MFDF_RESP_ADDITIONAL_FRAME)
    {
        if (((pDataParams->bWrappedMode) && (*pRxlen == 2)) ||
            ((!(pDataParams->bWrappedMode)) && (*pRxlen == 1)))
        {
            /* AF should always be accompanied by data. Otherwise
            it is a protocol error */
            return PH_ADD_COMPCODE(PH_ERR_PROTOCOL_ERROR, PH_COMP_AL_MFDF);
        }

        if (pDataParams->bWrappedMode)
        {
            /* Next position will ensure overwriting on the 
            SW1SW2 received from previous command */
            wNextPos = (*pRxlen) - 2;
            memcpy(bBackupBytes, &(*pResponse)[wNextPos - 3], 3); /* PRQA S 3200 */
        } 
        else
        {
            /* Backup the last byte */
            bBackupByte = (*pResponse)[(*pRxlen - 1)];
            memcpy(bBackupBytes, &(*pResponse)[(*pRxlen - 3)], 3); /* PRQA S 3200 */
            wNextPos = (*pRxlen) - 1;
        }

        PH_CHECK_SUCCESS_FCT(statusTmp,phhalHw_GetConfig(
            pDataParams->pHalDataParams,
            PHHAL_HW_CONFIG_RXBUFFER_BUFSIZE,
            &wRxBufferSize
            ));
    }

    while (bStatusByte == PHAL_MFDF_RESP_ADDITIONAL_FRAME)
    {
        if (((pDataParams->bWrappedMode) && (*pRxlen == 2)) ||
            ((!(pDataParams->bWrappedMode)) && (*pRxlen == 1)))
        {
            /* AF should always be accompanied by data. Otherwise
            it is a protocol error */
            return PH_ADD_COMPCODE(PH_ERR_PROTOCOL_ERROR, PH_COMP_AL_MFDF);
        }
        if (wNextPos + PHAL_MFDF_MAX_FRAME_SIZE >= wRxBufferSize)
        {
            /* Return 0xAF and let the caller recall the function with
            option = PH_EXCHANGE_RXCHAINING */
            /* Return the data accumulated till now and its length */
            if (pDataParams->bWrappedMode)
            {
                (*pRxlen) -= 2;
            } 
            else
            {
                (*pRxlen) -= 1;
                (*pResponse)++;
            }
            return PH_ADD_COMPCODE(PH_ERR_SUCCESS_CHAINING, PH_COMP_AL_MFDF);
        }
        PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams,
            PHHAL_HW_CONFIG_RXBUFFER_STARTPOS,
            wNextPos
            ));

        bCmdBuff[0] = PHAL_MFDF_RESP_ADDITIONAL_FRAME;
        wCmdLen = 1;
        if ( pDataParams->bWrappedMode )
        {
            pApdu[1] = bCmdBuff[0];  /* Desfire command code. */
            /* Encode APDU Length*/
            pApdu[4]= (uint8_t)wCmdLen - 1; /* Set APDU Length. */

            statusTmp = phpalMifare_ExchangeL4(
                pDataParams->pPalMifareDataParams,
                pApdu[4] == 0x00 ? PH_EXCHANGE_DEFAULT : PH_EXCHANGE_BUFFER_FIRST,
                pApdu,
                PHAL_MFDF_WRAP_HDR_LEN,
                &pRecv,
                pRxlen
                );
            if ((pApdu[4] != 0x00) && (statusTmp == PH_ERR_SUCCESS))
            {
                PH_CHECK_SUCCESS_FCT(statusTmp, phpalMifare_ExchangeL4(
                    pDataParams->pPalMifareDataParams,
                    PH_EXCHANGE_BUFFER_CONT,
                    bCmdBuff,
                    wCmdLen,
                    &pRecv,
                    pRxlen
                    ));

                bCmdBuff[0] = 0x00; /* Le */
                statusTmp = phpalMifare_ExchangeL4(
                    pDataParams->pPalMifareDataParams,
                    PH_EXCHANGE_BUFFER_LAST,
                    bCmdBuff,
                    0x01,
                    &pRecv,
                    pRxlen
                    );
            }
            /* To handle the case where the card returns only status 91 and returns
            AF in the next frame */
            if ((statusTmp & PH_ERR_MASK) == PH_ERR_SUCCESS_CHAINING)
            {
                /* One or two more status bytes to read from DesFire */
                bBackUpByte = pRecv[0];
                bBackUpByte1 = pRecv[1];
                wBackUpLen = *pRxlen;

                PH_CHECK_SUCCESS_FCT(statusTmp, phpalMifare_ExchangeL4(
                    pDataParams->pPalMifareDataParams,
                    PH_EXCHANGE_RXCHAINING,
                    &pApdu[2],
                    0x01,
                    &pRecv,
                    pRxlen
                    ));

                /* Received length can be one or two Ex: 0x91 0xAF */
                if (*pRxlen == 2)
                {
                    pRecv[wBackUpLen] = pRecv[0];
                    pRecv[wBackUpLen + 1] = pRecv[1];
                    bStatusByte = pRecv[1];
                }
                else if (*pRxlen == 1)
                {
                    bStatusByte = pRecv[0];
                    pRecv[wBackUpLen] = bStatusByte;
                }
                else
                {
                    return PH_ADD_COMPCODE(PH_ERR_PROTOCOL_ERROR, PH_COMP_AL_MFDF);
                }

                *pRxlen = wBackUpLen + *pRxlen;

                /* Set back the backed up bytes */
                pRecv[0] = bBackUpByte;
                pRecv[1] = bBackUpByte1;
            }
            else
            {
                if (statusTmp != PH_ERR_SUCCESS)
                {
                    return statusTmp;
                }
            }
        }
        else
        {
            /* Send this on L4 */
            PH_CHECK_SUCCESS_FCT(statusTmp, phpalMifare_ExchangeL4(
                pDataParams->pPalMifareDataParams,
                wOption,
                bCmdBuff,
                wCmdLen,
                &pRecv,
                pRxlen
                ));
        }

        /* Update wNextPos */
        if (pDataParams->bWrappedMode)
        {
            bStatusByte = (*pResponse)[(*pRxlen) - 1];

            /* Putback the backed up bytes */
            memcpy(&(*pResponse)[wNextPos - 3], bBackupBytes, 3); /* PRQA S 3200 */

            wNextPos = (*pRxlen) - 2;
            memcpy(bBackupBytes, &(*pResponse)[wNextPos - 3], 3); /* PRQA S 3200 */
        } 
        else
        {
            bStatusByte = (*pResponse)[wNextPos];

            /* Put back the previously backedup byte */
            (*pResponse)[wNextPos] = bBackupByte;

            /* Putback the backed up bytes */
            memcpy(&(*pResponse)[wNextPos - 2], bBackupBytes, 3); /* PRQA S 3200 */

            wNextPos = (*pRxlen) - 1;
            bBackupByte = (*pResponse)[wNextPos];

            /* Backup 3 bytes. The nxt frame will overwrite these */
            memcpy(bBackupBytes, &(*pResponse)[wNextPos - 2], 3); /* PRQA S 3200 */
        }
    }
    if (pDataParams->bWrappedMode)
    {
        (*pRxlen) -= 2;
    } 
    else
    {
        (*pRxlen) -= 1;
        (*pResponse)++;
    }
    return phalMfdf_Int_ComputeErrorResponse(pDataParams, bStatusByte);
}