01 02 03 04 05 06 07 73 08 09 //apdu 00A404000C504B492EC9E7BBE1B1A3D5CF 返回正常 01 02 03 04 05 06 07 73 08 09 //apdu 00A4000002DF01 返回正常 01 02 03 04 05 06 07 73 08 09 //apdu 0A40000020018 返回正常 01 02 03 04 05 06 07 71 //apdu 00B00080FF 复位重启 Uart1PutChar(0x0X); 串口打印输出 /**************************************************************************************** phStatus_t phpalI14443p4_Sw_Exchange( phpalI14443p4_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; uint8_t PH_MEMLOC_REM bBufferOverflow; /* Used to build I/R/S block frames */ uint8_t PH_MEMLOC_REM bIsoFrame[3]; uint16_t PH_MEMLOC_REM wIsoFrameLen; uint8_t PH_MEMLOC_REM bRxOverlapped[3]; uint16_t PH_MEMLOC_REM wRxOverlappedLen; uint16_t PH_MEMLOC_REM wRxStartPos; uint8_t PH_MEMLOC_REM bUseNad; uint8_t PH_MEMLOC_REM bChained; uint8_t PH_MEMLOC_REM bForceSend; /* Used for transmission */ uint16_t PH_MEMLOC_REM wInfLength; /* Used for Tx-Buffering */ uint16_t PH_MEMLOC_REM wRxBufferSize; uint16_t PH_MEMLOC_REM wTxBufferSize; uint16_t PH_MEMLOC_REM wTxBufferLen; uint16_t PH_MEMLOC_REM wRxBufferStartPos; uint16_t PH_MEMLOC_REM wMaxPcdFrameSize; uint16_t PH_MEMLOC_REM wMaxCardFrameSize; uint16_t PH_MEMLOC_REM wPcb = 0; 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; } /* Retrieve HAL buffer sizes */ PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_GetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_RXBUFFER_BUFSIZE, &wRxBufferSize)); PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_GetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_TXBUFFER_BUFSIZE, &wTxBufferSize)); /* Retrieve maximum frame sizes */ wMaxPcdFrameSize = bI14443p4_FsTable[pDataParams->bFsdi]; wMaxCardFrameSize = bI14443p4_FsTable[pDataParams->bFsci]-2; /* R(ACK) transmission in case of Rx-Chaining */ if (((wOption & PH_EXCHANGE_MODE_MASK) == PH_EXCHANGE_RXCHAINING) || ((wOption & PH_EXCHANGE_MODE_MASK) == PH_EXCHANGE_RXCHAINING_BUFSIZE)) { pDataParams->bStateNow = PHPAL_I14443P4_SW_STATE_RACK_BLOCK_TX; } /* Default state -> I-Block transmission */ else { pDataParams->bStateNow = PHPAL_I14443P4_SW_STATE_I_BLOCK_TX; } /* Reset receive length */ *pRxLength = 0; /* ******************************** */ /* I-BLOCK TRANSMISSION LOOP */ /* ******************************** */ Uart1PutChar(0x01); do { /* Retrieve TxBuffer length (number of preloaded bytes) */ if (wOption & PH_EXCHANGE_LEAVE_BUFFER_BIT) { PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_GetConfig( pDataParams->pHalDataParams, PHHAL_HW_CONFIG_TXBUFFER_LENGTH, &wTxBufferLen)); } /* Ignore preloaded bytes if we do not retain them */ else { wTxBufferLen = 0; } switch (pDataParams->bStateNow & PHPAL_I14443P4_SW_STATE_MASK) { case PHPAL_I14443P4_SW_STATE_I_BLOCK_TX: /* Some data (incl. frame) has been preloaded into the TxBuffer */ if (wTxBufferLen > 0) { /* we do not know if we need to chain yet */ bChained = 0; /* do not generate the iso frame */ wIsoFrameLen = 0; /* just append given data */ wInfLength = wTxLength; } else { /* 7.1.1.3 c), ISO/IEC 14443-4:2008(E), "During chaining the NAD shall only be transmitted in the first block of chain." */ if (!(pDataParams->bStateNow & PHPAL_I14443P4_SW_STATE_CHAINING_BIT)) { bUseNad = pDataParams->bNadEnabled; } else { bUseNad = 0; } /* Evaluate frame overhead */ wIsoFrameLen = 1; if (bUseNad) { ++wIsoFrameLen; } if (pDataParams->bCidEnabled) { ++wIsoFrameLen; } /* Check if chaining is neccessary */ if (wTxLength > (wMaxCardFrameSize - wIsoFrameLen)) { bChained = 1; pDataParams->bStateNow |= PHPAL_I14443P4_SW_STATE_CHAINING_BIT; /* Set transmission information for HAL exchange */ wInfLength = wMaxCardFrameSize - wIsoFrameLen; } /* Switch to receive mode if it's the last (or only) block in the chain */ else { /* Forced chaining mode */ if ((wOption & PH_EXCHANGE_MODE_MASK) == PH_EXCHANGE_TXCHAINING) { bChained = 1; pDataParams->bStateNow |= PHPAL_I14443P4_SW_STATE_CHAINING_BIT; } else { bChained = 0; pDataParams->bStateNow &= (uint8_t)~(uint8_t)PHPAL_I14443P4_SW_STATE_CHAINING_BIT; } /* Set transmission information for HAL exchange */ wInfLength = wTxLength; } /* Generate I-Block frame header */ PH_CHECK_SUCCESS_FCT(statusTmp, phpalI14443p4_Sw_BuildIBlock( pDataParams->bCidEnabled, pDataParams->bCid, bUseNad, pDataParams->bNad, pDataParams->bPcbBlockNum, bChained, bIsoFrame, &wIsoFrameLen)); /* Write Frame to HAL TxBuffer but do not preform Exchange */ PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_Exchange( pDataParams->pHalDataParams, PH_EXCHANGE_BUFFER_FIRST, bIsoFrame, wIsoFrameLen, NULL, NULL)); /* Retain the preloaded bytes from now on */ wOption |= PH_EXCHANGE_LEAVE_BUFFER_BIT; } break; case PHPAL_I14443P4_SW_STATE_RACK_BLOCK_TX: /* no chaining */ bChained = 0; /* do not append any data */ wInfLength = 0; /* Adjust state */ pDataParams->bStateNow = PHPAL_I14443P4_SW_STATE_I_BLOCK_RX; /* Build R(ACK) frame */ PH_CHECK_SUCCESS_FCT(statusTmp, phpalI14443p4_Sw_BuildRBlock( pDataParams->bCidEnabled, pDataParams->bCid, pDataParams->bPcbBlockNum, 1, bIsoFrame, &wIsoFrameLen)); /* Write Frame to HAL TxBuffer but do not preform Exchange */ PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_Exchange( pDataParams->pHalDataParams, PH_EXCHANGE_BUFFERED_BIT, bIsoFrame, wIsoFrameLen, NULL, NULL)); /* Retain the preloaded bytes from now on */ wOption |= PH_EXCHANGE_LEAVE_BUFFER_BIT; break; /* Should NEVER happen! */ default: return PH_ADD_COMPCODE(PH_ERR_INTERNAL_ERROR, PH_COMP_PAL_ISO14443P4); } Uart1PutChar(0x02); /* Force frame exchange if a) the maximum frame size of the card has been reached; */ if ((wTxBufferLen + wIsoFrameLen + wInfLength) > wMaxCardFrameSize) { /* block needs to be chained */ bChained = 1; /* force frame exchange */ bForceSend = 1; /* limit number of bytes to send */ wInfLength = wMaxCardFrameSize - wTxBufferLen - wIsoFrameLen; } /* reset force frame exchange */ else { bForceSend = 0; } /* Force frame exchange if b) the TxBuffer is full; */ Uart1PutChar(0x03); if ((wOption & PH_EXCHANGE_BUFFERED_BIT) && ((wTxBufferLen + wIsoFrameLen + wInfLength) >= wTxBufferSize)) { /* block needs to be chained */ bChained = 1; /* force frame exchange */ bForceSend = 1; /* limit number of bytes to send */ wInfLength = wTxBufferSize - wTxBufferLen - wIsoFrameLen; } /* Tx-Buffering mode */ if ((!bForceSend) && (wOption & PH_EXCHANGE_BUFFERED_BIT)) { /* Preload the data into the TxBuffer */ return phhalHw_Exchange( pDataParams->pHalDataParams, (wOption & (uint16_t)~(uint16_t)PH_EXCHANGE_MODE_MASK), pTxBuffer, wInfLength, NULL, NULL); } /* Data has been preloaded into internal buffer before */ if ((bForceSend) || (wTxBufferLen > 0)) { /* retrieve PCB byte */ PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_ADDITIONAL_INFO, 0x00)); PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_GetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_TXBUFFER, &wPcb)); /* CHAINING enabled / forced */ if (bChained) { /* modify PCB if neccessary */ if (!(wPcb & PHPAL_I14443P4_SW_PCB_CHAINING)) { wPcb |= PHPAL_I14443P4_SW_PCB_CHAINING; PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_TXBUFFER, wPcb)); } /* set chaining bit in current status */ pDataParams->bStateNow |= PHPAL_I14443P4_SW_STATE_CHAINING_BIT; } /* CHAINING disabled */ else { /* modify PCB if neccessary */ if (wPcb & PHPAL_I14443P4_SW_PCB_CHAINING) { wPcb &= (uint8_t)~(uint8_t)PHPAL_I14443P4_SW_PCB_CHAINING; PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_TXBUFFER, wPcb)); } /* clear chaining bit in current status */ pDataParams->bStateNow &= (uint8_t)~(uint8_t)PHPAL_I14443P4_SW_STATE_CHAINING_BIT; } } Uart1PutChar(0x04); /* Perform Exchange using complete ISO handling */ if (!(wOption & PH_EXCHANGE_BUFFERED_BIT) || (bForceSend != 0)) { PH_CHECK_SUCCESS_FCT(statusTmp, phpalI14443p4_Sw_IsoHandling( pDataParams, wOption & (uint16_t)~(uint16_t)PH_EXCHANGE_BUFFERED_BIT, pTxBuffer, wInfLength, ppRxBuffer, pRxLength)); } /* Only buffer the contents */ else { PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_Exchange( pDataParams->pHalDataParams, wOption & (uint16_t)~(uint16_t)PH_EXCHANGE_CUSTOM_BITS_MASK, pTxBuffer, wInfLength, ppRxBuffer, pRxLength)); } Uart1PutChar(0x05); /* Retransmission in progress */ if (pDataParams->bStateNow & PHPAL_I14443P4_SW_STATE_RETRANSMIT_BIT) { /* Restore internal TxBuffer. Neccessary in case RxBuffer and TxBuffer are the same. */ if (wTxBufferLen > 0) { /* restore PCB byte */ PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_ADDITIONAL_INFO, 0x00)); PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_TXBUFFER, wPcb)); } /* Clear retransmission bit */ pDataParams->bStateNow &= (uint8_t)~(uint8_t)PHPAL_I14443P4_SW_STATE_RETRANSMIT_BIT; } /* No retransmission in progress */ else { /* Clear HAL buffer if everything was physically sent successful */ if ((bForceSend) || !(wOption & PH_EXCHANGE_BUFFERED_BIT)) { PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_TXBUFFER_LENGTH, 0x00)); } /* Chaining is active */ if (pDataParams->bStateNow == (PHPAL_I14443P4_SW_STATE_I_BLOCK_TX | PHPAL_I14443P4_SW_STATE_CHAINING_BIT)) { /* Remove sent bytes from TxBuffer */ if (wTxLength < wInfLength) { return PH_ADD_COMPCODE(PH_ERR_INTERNAL_ERROR, PH_COMP_PAL_ISO14443P4); } pTxBuffer += wInfLength; if (wTxLength >= wInfLength) { wTxLength = (uint16_t)(wTxLength - wInfLength); } else { return PH_ADD_COMPCODE(PH_ERR_INTERNAL_ERROR, PH_COMP_PAL_ISO14443P4); } /* Fix for TxChaining mode */ if (wTxLength == 0) { pDataParams->bStateNow = PHPAL_I14443P4_SW_STATE_I_BLOCK_RX; } } } } /* Loop as long as the state does not transit to RX mode */ while ((pDataParams->bStateNow & PHPAL_I14443P4_SW_STATE_MASK) != PHPAL_I14443P4_SW_STATE_I_BLOCK_RX); Uart1PutChar(0x06); /* TxChaining mode -> return after sending */ if ((wOption & PH_EXCHANGE_MODE_MASK) == PH_EXCHANGE_TXCHAINING) { return PH_ADD_COMPCODE(PH_ERR_SUCCESS, PH_COMP_PAL_ISO14443P4); } /* Overlap PCB */ wRxOverlappedLen = 1; /* Overlap CID */ if ((*ppRxBuffer)[PHPAL_I14443P4_SW_PCB_POS] & PHPAL_I14443P4_SW_PCB_CID_FOLLOWING) { wRxOverlappedLen++; } /* Overlap NAD */ if ((*ppRxBuffer)[PHPAL_I14443P4_SW_PCB_POS] & PHPAL_I14443P4_SW_PCB_NAD_FOLLOWING) { wRxOverlappedLen++; } /* Reset chaining state */ bChained = 0; wRxStartPos = 0; bBufferOverflow = 0; Uart1PutChar(0x07); /* ******************************** */ /* I-BLOCK RECEPTION LOOP */ /* ******************************** */ do { /* Only allow receive state at this point */ if ((pDataParams->bStateNow & PHPAL_I14443P4_SW_STATE_MASK) != PHPAL_I14443P4_SW_STATE_I_BLOCK_RX) { return PH_ADD_COMPCODE(PH_ERR_INTERNAL_ERROR, PH_COMP_PAL_ISO14443P4); } /* Restore overlapped INF bytes for all subsequent responses */ if (bChained) { memcpy(&(*ppRxBuffer)[wRxStartPos], bRxOverlapped, wRxOverlappedLen); /* PRQA S 3200 */ /* PRQA S 3354 */ } /* Rule 2, ISO/IEC 14443-4:2008(E), PICC chaining */ if (pDataParams->bStateNow & PHPAL_I14443P4_SW_STATE_CHAINING_BIT) { /* This is first chained response */ if (!bChained) { /* Special NAD chaining handling */ if (pDataParams->bNadEnabled) { --wRxOverlappedLen; } bChained = 1; } Uart1PutChar(0x071); /* Backup overlapped bytes */ memcpy(bRxOverlapped, &(*ppRxBuffer)[((*pRxLength) - wRxOverlappedLen)], wRxOverlappedLen); /* PRQA S 3200 */ /* Calculate RxBuffer Start Position */ wRxStartPos = (*pRxLength) - wRxOverlappedLen; /* Return with chaining status if the next chain may not fit into our buffer */ if (((wOption & PH_EXCHANGE_MODE_MASK) != PH_EXCHANGE_RXCHAINING_BUFSIZE) && ((*pRxLength + wMaxPcdFrameSize) > wRxBufferSize)) { /* Adjust RxBuffer position */ (*ppRxBuffer) += wRxOverlappedLen; *pRxLength = *pRxLength - wRxOverlappedLen; return PH_ADD_COMPCODE(PH_ERR_SUCCESS_CHAINING, PH_COMP_PAL_ISO14443P4); } Uart1PutChar(0x072); /* Set RxBuffer Start Position */ PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_SetConfig( pDataParams->pHalDataParams, PHHAL_HW_CONFIG_RXBUFFER_STARTPOS, wRxStartPos)); /* Send R(ACK) frame */ PH_CHECK_SUCCESS_FCT(statusTmp, phpalI14443p4_Sw_BuildRBlock( pDataParams->bCidEnabled, pDataParams->bCid, pDataParams->bPcbBlockNum, 1, bIsoFrame, &wIsoFrameLen)); } /* No chaining -> reception finished */ else { /* Special NAD chaining handling */ if (bChained && pDataParams->bNadEnabled) { ++wRxOverlappedLen; } Uart1PutChar(0x073); /* Adjust RxBuffer position */ (*ppRxBuffer) += wRxOverlappedLen; *pRxLength = *pRxLength - wRxOverlappedLen; pDataParams->bStateNow = PHPAL_I14443P4_SW_STATE_FINISHED; } /* Exchange mode is active */ if (pDataParams->bStateNow != PHPAL_I14443P4_SW_STATE_FINISHED) { /* Perform Exchange using complete ISO handling */ status = phpalI14443p4_Sw_IsoHandling( pDataParams, PH_EXCHANGE_DEFAULT, bIsoFrame, wIsoFrameLen, ppRxBuffer, pRxLength); /* Complete chaining if buffer is full */ if (((status & PH_ERR_MASK) == PH_ERR_BUFFER_OVERFLOW) && ((wOption & PH_EXCHANGE_MODE_MASK) == PH_EXCHANGE_RXCHAINING_BUFSIZE)) { /* Retrieve Rx-Buffer start position */ PH_CHECK_SUCCESS_FCT(statusTmp, phhalHw_GetConfig( pDataParams->pHalDataParams, PHHAL_HW_CONFIG_RXBUFFER_STARTPOS, &wRxBufferStartPos)); Uart1PutChar(0x074); /* Check if we received an I-Block PCB which indicates chaining */ if ((((*pRxLength) - wRxBufferStartPos) > 0) && (PHPAL_I14443P4_SW_IS_I_BLOCK((*ppRxBuffer)[wRxBufferStartPos])) && (PHPAL_I14443P4_SW_IS_CHAINING((*ppRxBuffer)[wRxBufferStartPos]))) { /* Reset Rx-Buffer parameters */ *pRxLength = 0; wRxStartPos = 0; wRxOverlappedLen = 0; bBufferOverflow = 1; } /* Otherwise bail out with the error */ else { return status; } Uart1PutChar(0x075); } else { PH_CHECK_SUCCESS(status); } } // CLR_WDG(); } while (pDataParams->bStateNow != PHPAL_I14443P4_SW_STATE_FINISHED); Uart1PutChar(0x08); /* Map return codes */ if (bBufferOverflow) { return PH_ADD_COMPCODE(PH_ERR_BUFFER_OVERFLOW, PH_COMP_PAL_ISO14443P4); } /* do not return any data in RxChainingBufsize state */ if ((wOption & PH_EXCHANGE_MODE_MASK) == PH_EXCHANGE_RXCHAINING_BUFSIZE) { *pRxLength = 0; } Uart1PutChar(0x09); return PH_ADD_COMPCODE(PH_ERR_SUCCESS, PH_COMP_PAL_ISO14443P4); }