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); }
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); }
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); }