/* * Copyright 2012-2014,2018-2020 NXP * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include "sm_types.h" #include "sm_timer.h" #ifdef FLOW_VERBOSE #define NX_LOG_ENABLE_SMCOM_DEBUG 1 #endif #include "nxLog_smCom.h" #include "nxEnsure.h" /** * \addtogroup ISO7816-3_protocol_lib * * @{ */ phNxpEseProto7816_t phNxpEseProto7816_3_Var; /****************************************************************************** \section Introduction Introduction * This module provide the 7816-3 protocol level implementation for ESE * ******************************************************************************/ static bool_t phNxpEseProto7816_SendRawFrame(void* conn_ctx, uint32_t data_len, uint8_t *p_data); static bool_t phNxpEseProto7816_GetRawFrame(void* conn_ctx, uint32_t *data_len, uint8_t **pp_data); static uint16_t phNxpEseProto7816_ComputeCRC(unsigned char *p_buff, uint32_t offset, uint32_t length); static bool_t phNxpEseProto7816_CheckCRC(uint32_t data_len, uint8_t *p_data); static bool_t phNxpEseProto7816_SendSFrame(void* conn_ctx, sFrameInfo_t sFrameData); static bool_t phNxpEseProto7816_SendIframe(void* conn_ctx, iFrameInfo_t iFrameData); static bool_t phNxpEseProto7816_sendRframe(void* conn_ctx, rFrameTypes_t rFrameType); static bool_t phNxpEseProto7816_SetFirstIframeContxt(void); static bool_t phNxpEseProto7816_SetNextIframeContxt(void); static bool_t phNxpEseProro7816_SaveRxframeData(uint8_t *p_data, uint32_t data_len); static bool_t phNxpEseProto7816_ResetRecovery(void); static bool_t phNxpEseProto7816_RecoverySteps(void); static bool_t phNxpEseProto7816_DecodeFrame(uint8_t *p_data, uint32_t data_len); static bool_t phNxpEseProto7816_ProcessResponse(void* conn_ctx); static bool_t TransceiveProcess(void* conn_ctx); static bool_t phNxpEseProto7816_RSync(void* conn_ctx); /****************************************************************************** * Function phNxpEseProto7816_SendRawFrame * * Description This internal function is called send the data to ESE * * param[in] uint32_t: number of bytes to be written * param[in] uint8_t : data buffer * * Returns On success return TRUE or else FALSE. * ******************************************************************************/ static bool_t phNxpEseProto7816_SendRawFrame(void* conn_ctx, uint32_t data_len, uint8_t *p_data) { ESESTATUS status = ESESTATUS_FAILED; status = phNxpEse_WriteFrame(conn_ctx, data_len, p_data); if (ESESTATUS_SUCCESS != status) { LOG_E("%s Error phNxpEse_WriteFrame ", __FUNCTION__); } return (status == ESESTATUS_SUCCESS)?TRUE : FALSE; } /****************************************************************************** * Function phNxpEseProto7816_GetRawFrame * * Description This internal function is called read the data from the ESE * * param[out] uint32_t: number of bytes read * param[out] uint8_t : Read data from ESE * * Returns On success return TRUE or else FALSE. * ******************************************************************************/ static bool_t phNxpEseProto7816_GetRawFrame(void* conn_ctx, uint32_t *data_len, uint8_t **pp_data) { bool_t bStatus = FALSE; ESESTATUS status = ESESTATUS_FAILED; status = phNxpEse_read(conn_ctx, data_len, pp_data); if (ESESTATUS_SUCCESS != status) { LOG_E("%s phNxpEse_read failed , status : 0x%x ", __FUNCTION__, status); } else { bStatus = TRUE; } return bStatus; } /****************************************************************************** * Function phNxpEseProto7816_ComputeCRC * * Description This internal function is called compute the CRC * * param[in] unsigned char: data buffer * param[in] uint32_t : offset from which CRC to be calculated * param[in] uint32_t : total length of frame * * Returns On success return TRUE or else FALSE. * ******************************************************************************/ static uint16_t phNxpEseProto7816_ComputeCRC(unsigned char *p_buff, uint32_t offset, uint32_t length) { uint16_t CAL_CRC = 0xFFFF, CRC = 0x0000; uint32_t i = 0; ENSURE_OR_GO_EXIT(p_buff != NULL); for (i = offset; i < length; i++) { CAL_CRC ^= p_buff[i]; for (int bit = 8; bit > 0; --bit) { if ((CAL_CRC & 0x0001) == 0x0001) { CAL_CRC = (unsigned short)((CAL_CRC >> 1) ^ 0x8408); } else { CAL_CRC >>= 1; } } } CAL_CRC ^=0xFFFF; #if defined(T1oI2C_UM11225) CRC = ((CAL_CRC & 0xFF) << 8) | ((CAL_CRC >> 8) & 0xFF); #elif defined(T1oI2C_GP1_0) CRC = CAL_CRC; #endif exit: return (uint16_t) CRC; } /****************************************************************************** * Function phNxpEseProto7816_CheckCRC * * Description This internal function is called compute and compare the * received CRC of the received data * * param[in] uint32_t : frame length * param[in] uint8_t: data buffer * * Returns On success return TRUE or else FALSE. * ******************************************************************************/ static bool_t phNxpEseProto7816_CheckCRC(uint32_t data_len, uint8_t *p_data) { bool_t status = FALSE; uint16_t calc_crc = 0; uint16_t recv_crc = 0; ENSURE_OR_GO_EXIT(p_data != NULL); status = TRUE; recv_crc = p_data[data_len - 2] <<8 | p_data[data_len - 1] ; //combine 2 byte CRC /* calculate the CRC after excluding Recieved CRC */ /* CRC calculation includes NAD byte, so offset is set to 0 */ calc_crc = phNxpEseProto7816_ComputeCRC(p_data, 0, (data_len -2)); LOG_D("Received CRC:0x%x Calculated CRC:0x%x ", recv_crc, calc_crc); if (recv_crc != calc_crc) { status = FALSE; LOG_E("%s CRC failed ", __FUNCTION__); } exit: return status; } /****************************************************************************** * Function getMaxSupportedSendIFrameSize * * Description This internal function is called to get the max supported * I-frame size * * param[in] void * * Returns IFSC_SIZE_SEND * ******************************************************************************/ uint8_t getMaxSupportedSendIFrameSize(void) { return IFSC_SIZE_SEND ; } /****************************************************************************** * Function phNxpEseProto7816_SendSFrame * * Description This internal function is called to send S-frame with all * updated 7816-3 headers * * param[in] sFrameInfo_t: Info about S frame * * Returns On success return TRUE or else FALSE. * ******************************************************************************/ static bool_t phNxpEseProto7816_SendSFrame(void* conn_ctx, sFrameInfo_t sFrameData) { bool_t status = ESESTATUS_FAILED; uint32_t frame_len = 0; uint8_t p_framebuff[7] = {0}; uint8_t pcb_byte = 0; sFrameInfo_t sframeData = sFrameData; uint16_t calc_crc=0; /* This update is helpful in-case a R-NACK is transmitted from the MW */ phNxpEseProto7816_3_Var.lastSentNonErrorframeType = SFRAME; switch(sframeData.sFrameType) { case RESYNCH_REQ: frame_len = (PH_PROTO_7816_HEADER_LEN + PH_PROTO_7816_CRC_LEN); p_framebuff[PH_PROPTO_7816_LEN_UPPER_OFFSET] = 0; #if defined(T1oI2C_GP1_0) /* T =1 GP block format LEN field is of 2 byte*/ p_framebuff[PH_PROPTO_7816_LEN_LOWER_OFFSET] = 0; #endif p_framebuff[PH_PROPTO_7816_INF_BYTE_OFFSET] = 0x00; pcb_byte |= PH_PROTO_7816_S_BLOCK_REQ; /* PCB */ pcb_byte |= PH_PROTO_7816_S_RESYNCH; break; #if defined(T1oI2C_UM11225) case INTF_RESET_REQ: frame_len = (PH_PROTO_7816_HEADER_LEN + PH_PROTO_7816_CRC_LEN); p_framebuff[PH_PROPTO_7816_LEN_UPPER_OFFSET] = 0; p_framebuff[PH_PROPTO_7816_INF_BYTE_OFFSET] = 0x00; pcb_byte |= PH_PROTO_7816_S_BLOCK_REQ; /* PCB */ pcb_byte |= PH_PROTO_7816_S_RESET; break; case PROP_END_APDU_REQ: frame_len = (PH_PROTO_7816_HEADER_LEN + PH_PROTO_7816_CRC_LEN); p_framebuff[PH_PROPTO_7816_LEN_UPPER_OFFSET] = 0; p_framebuff[PH_PROPTO_7816_INF_BYTE_OFFSET] = 0x00; pcb_byte |= PH_PROTO_7816_S_BLOCK_REQ; /* PCB */ pcb_byte |= PH_PROTO_7816_S_END_OF_APDU; break; case ATR_REQ: frame_len = (PH_PROTO_7816_HEADER_LEN + PH_PROTO_7816_CRC_LEN); p_framebuff[PH_PROPTO_7816_LEN_UPPER_OFFSET] = 0; p_framebuff[PH_PROPTO_7816_INF_BYTE_OFFSET] = 0x00; pcb_byte |= PH_PROTO_7816_S_BLOCK_REQ; /* PCB */ pcb_byte |= PH_PROTO_7816_S_GET_ATR; break; #endif case WTX_RSP: frame_len = (PH_PROTO_7816_HEADER_LEN + 1 + PH_PROTO_7816_CRC_LEN); #if defined(T1oI2C_UM11225) /* T =1 UM11225 SE050 block format LEN field is of 2 byte*/ p_framebuff[PH_PROPTO_7816_LEN_UPPER_OFFSET] = 0x01; #elif defined(T1oI2C_GP1_0) /* T =1 GP block format LEN field is of 2 byte*/ p_framebuff[PH_PROPTO_7816_LEN_UPPER_OFFSET] = 0x00; p_framebuff[PH_PROPTO_7816_LEN_LOWER_OFFSET] = 0x01; #endif p_framebuff[PH_PROPTO_7816_INF_BYTE_OFFSET] = 0x01; pcb_byte |= PH_PROTO_7816_S_BLOCK_RSP; pcb_byte |= PH_PROTO_7816_S_WTX; break; #if defined(T1oI2C_UM11225) case CHIP_RESET_REQ: frame_len = (PH_PROTO_7816_HEADER_LEN + PH_PROTO_7816_CRC_LEN); p_framebuff[PH_PROPTO_7816_LEN_UPPER_OFFSET] = 0; p_framebuff[PH_PROPTO_7816_INF_BYTE_OFFSET] = 0x00; pcb_byte |= PH_PROTO_7816_S_BLOCK_REQ; /* PCB */ pcb_byte |= PH_PROTO_7816_S_CHIP_RST; break; #endif #if defined(T1oI2C_GP1_0) case SWR_REQ: frame_len = (PH_PROTO_7816_HEADER_LEN + PH_PROTO_7816_CRC_LEN); p_framebuff[PH_PROPTO_7816_LEN_UPPER_OFFSET] = 0; p_framebuff[PH_PROPTO_7816_LEN_LOWER_OFFSET] = 0; p_framebuff[PH_PROPTO_7816_INF_BYTE_OFFSET] = 0x00; pcb_byte |= PH_PROTO_7816_S_BLOCK_REQ; /* PCB */ pcb_byte |= PH_PROTO_7816_S_SWR; break; case RELEASE_REQ: frame_len = (PH_PROTO_7816_HEADER_LEN + PH_PROTO_7816_CRC_LEN); p_framebuff[PH_PROPTO_7816_LEN_UPPER_OFFSET] = 0; p_framebuff[PH_PROPTO_7816_LEN_LOWER_OFFSET] = 0; p_framebuff[PH_PROPTO_7816_INF_BYTE_OFFSET] = 0x00; pcb_byte |= PH_PROTO_7816_S_BLOCK_REQ; /* PCB */ pcb_byte |= PH_PROTO_7816_S_RELEASE; break; case CIP_REQ: frame_len = (PH_PROTO_7816_HEADER_LEN + PH_PROTO_7816_CRC_LEN); p_framebuff[PH_PROPTO_7816_LEN_UPPER_OFFSET] = 0; p_framebuff[PH_PROPTO_7816_LEN_LOWER_OFFSET] = 0; p_framebuff[PH_PROPTO_7816_INF_BYTE_OFFSET] = 0x00; pcb_byte |= PH_PROTO_7816_S_BLOCK_REQ; /* PCB */ pcb_byte |= PH_PROTO_7816_S_GET_CIP; break; case COLD_RESET_REQ: frame_len = (PH_PROTO_7816_HEADER_LEN + PH_PROTO_7816_CRC_LEN); p_framebuff[PH_PROPTO_7816_LEN_UPPER_OFFSET] = 0; p_framebuff[PH_PROPTO_7816_LEN_LOWER_OFFSET] = 0; p_framebuff[PH_PROPTO_7816_INF_BYTE_OFFSET] = 0x00; pcb_byte |= PH_PROTO_7816_S_BLOCK_REQ; /* PCB */ pcb_byte |= PH_PROTO_7816_S_COLD_RST; break; #endif default: LOG_E(" %s :Invalid S-block",__FUNCTION__); return status; } /* frame the packet */ p_framebuff[PH_PROPTO_7816_NAD_OFFSET] = 0x5A; /* NAD Byte */ p_framebuff[PH_PROPTO_7816_PCB_OFFSET] = pcb_byte; /* PCB */ calc_crc = phNxpEseProto7816_ComputeCRC(p_framebuff, 0,(frame_len - 2)); p_framebuff[frame_len - 2] = (calc_crc >> 8) & 0xFF; p_framebuff[frame_len - 1] = calc_crc & 0xFF; LOG_D("S-Frame PCB: %x ", p_framebuff[PH_PROPTO_7816_PCB_OFFSET]); status = phNxpEseProto7816_SendRawFrame(conn_ctx, frame_len, p_framebuff); return status; } /****************************************************************************** * Function phNxpEseProto7816_sendRframe * * Description This internal function is called to send R-frame with all * updated 7816-3 headers * * param[in] sFrameInfo_t: Info about R frame * * Returns On success return TRUE or else FALSE. * ******************************************************************************/ static bool_t phNxpEseProto7816_sendRframe(void* conn_ctx, rFrameTypes_t rFrameType) { bool_t status = FALSE; #if defined(T1oI2C_UM11225) uint8_t recv_ack[5]= {0x5A,0x80,0x00,0x00,0x00}; #elif defined(T1oI2C_GP1_0) uint8_t recv_ack[6]= {0x5A,0x80,0x00,0x00,0x00,0x00}; #endif uint16_t calc_crc=0; iFrameInfo_t *pRx_lastRcvdIframeInfo = &phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdIframeInfo; rFrameInfo_t *pNextTx_RframeInfo = &phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.RframeInfo; if(RNACK == rFrameType) /* R-NACK */ { switch(pNextTx_RframeInfo->errCode) { case PARITY_ERROR: recv_ack[PH_PROPTO_7816_PCB_OFFSET] |= (0x01 & 0xFF); break; case OTHER_ERROR: recv_ack[PH_PROPTO_7816_PCB_OFFSET] |= (0x02 & 0xFF); break; case SOF_MISSED_ERROR: case UNDEFINED_ERROR: recv_ack[PH_PROPTO_7816_PCB_OFFSET] |= (0x03 & 0xFF); break; default: break; } } else /* R-ACK*/ { /* This update is helpful in-case a R-NACK is transmitted from the MW */ phNxpEseProto7816_3_Var.lastSentNonErrorframeType = RFRAME; } recv_ack[PH_PROPTO_7816_PCB_OFFSET] |= ((pRx_lastRcvdIframeInfo->seqNo ^ 1) << 4); LOG_D("%s recv_ack[PH_PROPTO_7816_PCB_OFFSET]:0x%x ", __FUNCTION__, recv_ack[PH_PROPTO_7816_PCB_OFFSET]); calc_crc = phNxpEseProto7816_ComputeCRC(recv_ack, 0x00, (sizeof(recv_ack) -2)); recv_ack[(sizeof(recv_ack) -2)] = (calc_crc >> 8) & 0xFF; recv_ack[(sizeof(recv_ack) -1)] = calc_crc &0xFF ; status = phNxpEseProto7816_SendRawFrame(conn_ctx, sizeof(recv_ack), recv_ack); return status; } /****************************************************************************** * Function phNxpEseProto7816_SendIframe * * Description This internal function is called to send I-frame with all * updated 7816-3 headers * * param[in] sFrameInfo_t: Info about I frame * * Returns On success return TRUE or else FALSE. * ******************************************************************************/ static bool_t phNxpEseProto7816_SendIframe(void* conn_ctx, iFrameInfo_t iFrameData) { bool_t status = FALSE; uint32_t frame_len = 0; uint8_t p_framebuff[MAX_DATA_LEN]; uint8_t pcb_byte = 0; uint16_t calc_crc = 0; iFrameInfo_t *pNextTx_IframeInfo = &phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo; if (0 == iFrameData.sendDataLen) { LOG_E("%s Line: [%d] I frame Len is 0, INVALID ",__FUNCTION__,__LINE__); return FALSE; } /* This update is helpful in-case a R-NACK is transmitted from the MW */ phNxpEseProto7816_3_Var.lastSentNonErrorframeType = IFRAME; frame_len = (iFrameData.sendDataLen+ PH_PROTO_7816_HEADER_LEN + PH_PROTO_7816_CRC_LEN); /* frame the packet */ p_framebuff[PH_PROPTO_7816_NAD_OFFSET] = SEND_PACKET_SOF; /* NAD Byte */ if (iFrameData.isChained) { /* make B6 (M) bit high */ pcb_byte |= PH_PROTO_7816_CHAINING; } /* Update the send seq no */ pcb_byte |= (pNextTx_IframeInfo->seqNo << 6); /* store the pcb byte */ p_framebuff[PH_PROPTO_7816_PCB_OFFSET] = pcb_byte; #if defined(T1oI2C_UM11225) /* store I frame length */ /* for T1oI2C_UM11225 LEN field is of 1 byte*/ p_framebuff[PH_PROPTO_7816_LEN_UPPER_OFFSET] =iFrameData.sendDataLen; #elif defined(T1oI2C_GP1_0) /* store I frame length */ /* for T1oI2C_GP1_0 LEN field is of 2 byte*/ p_framebuff[PH_PROPTO_7816_LEN_UPPER_OFFSET] =(((uint16_t)iFrameData.sendDataLen) >> 8 & 0xff); p_framebuff[PH_PROPTO_7816_LEN_LOWER_OFFSET] =(((uint16_t)iFrameData.sendDataLen) & 0xff); #endif /* store I frame */ phNxpEse_memcpy(&(p_framebuff[PH_PROPTO_7816_INF_BYTE_OFFSET]), iFrameData.p_data + iFrameData.dataOffset, iFrameData.sendDataLen); calc_crc = phNxpEseProto7816_ComputeCRC(p_framebuff, 0, (frame_len - 2)); p_framebuff[frame_len - 2] = (calc_crc >> 8) & 0xff; p_framebuff[frame_len - 1] = calc_crc & 0xff; status = phNxpEseProto7816_SendRawFrame(conn_ctx, frame_len, p_framebuff); return status; } /****************************************************************************** * Function phNxpEseProto7816_SetFirstIframeContxt * * Description This internal function is called to set the context for next I-frame. * Not applicable for the first I-frame of the transceive * * param[in] void * * Returns Always return TRUE. * ******************************************************************************/ static bool_t phNxpEseProto7816_SetFirstIframeContxt(void) { phNxpEseRx_Cntx_t *pRx_EseCntx = &phNxpEseProto7816_3_Var.phNxpEseRx_Cntx; iFrameInfo_t *pNextTx_IframeInfo = &phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo; iFrameInfo_t *pLastTx_IframeInfo = &phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.IframeInfo; pNextTx_IframeInfo->dataOffset = 0; phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = IFRAME; pNextTx_IframeInfo->seqNo = pLastTx_IframeInfo->seqNo ^ 1; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_IFRAME; pRx_EseCntx->pRsp->len = 0; if (pNextTx_IframeInfo->totalDataLen > pNextTx_IframeInfo->maxDataLen) { pNextTx_IframeInfo->isChained = TRUE; pNextTx_IframeInfo->sendDataLen = pNextTx_IframeInfo->maxDataLen; pNextTx_IframeInfo->totalDataLen = pNextTx_IframeInfo->totalDataLen - pNextTx_IframeInfo->maxDataLen; } else { pNextTx_IframeInfo->sendDataLen = pNextTx_IframeInfo->totalDataLen; pNextTx_IframeInfo->isChained = FALSE; } LOG_D("I-Frame Data Len: %ld Seq. no:%d ", pNextTx_IframeInfo->sendDataLen, pNextTx_IframeInfo->seqNo); return TRUE; } /****************************************************************************** * Function phNxpEseProto7816_SetNextIframeContxt * * Description This internal function is called to set the context for next I-frame. * Not applicable for the first I-frame of the transceive * * param[in] void * * Returns Always return TRUE. * ******************************************************************************/ static bool_t phNxpEseProto7816_SetNextIframeContxt(void) { iFrameInfo_t *pNextTx_IframeInfo = &phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo; iFrameInfo_t *pLastTx_IframeInfo = &phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.IframeInfo; /* Expecting to reach here only after first of chained I-frame is sent and before the last chained is sent */ phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = IFRAME; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_IFRAME; pNextTx_IframeInfo->seqNo = pLastTx_IframeInfo->seqNo ^ 1; pNextTx_IframeInfo->dataOffset = pLastTx_IframeInfo->dataOffset + pLastTx_IframeInfo->maxDataLen; pNextTx_IframeInfo->p_data = pLastTx_IframeInfo->p_data; pNextTx_IframeInfo->maxDataLen = pLastTx_IframeInfo->maxDataLen; //if chained if (pLastTx_IframeInfo->totalDataLen > pLastTx_IframeInfo->maxDataLen) { LOG_D("%s Process Chained Frame ",__FUNCTION__); pNextTx_IframeInfo->isChained = TRUE; pNextTx_IframeInfo->sendDataLen = pLastTx_IframeInfo->maxDataLen; pNextTx_IframeInfo->totalDataLen = pLastTx_IframeInfo->totalDataLen - pLastTx_IframeInfo->maxDataLen; } else { pNextTx_IframeInfo->isChained = FALSE; pNextTx_IframeInfo->sendDataLen = pLastTx_IframeInfo->totalDataLen; } LOG_D("I-Frame Data Len: %ld ", pNextTx_IframeInfo->sendDataLen); return TRUE; } /****************************************************************************** * Function phNxpEseProro7816_SaveRxframeData * * Description This internal function is called to save recv frame data * * param[in] uint8_t: data buffer * param[in] uint32_t: buffer length * * Returns Always return TRUE. * ******************************************************************************/ static bool_t phNxpEseProro7816_SaveRxframeData(uint8_t *p_data, uint32_t data_len) { uint32_t offset = 0; phNxpEseRx_Cntx_t *pRx_EseCntx = &phNxpEseProto7816_3_Var.phNxpEseRx_Cntx; LOG_D("Data[0]=0x%x len=%ld Data[%ld]=0x%x Data[%ld]=0x%x ", p_data[0], data_len,data_len-1, p_data[data_len-2],p_data[data_len-1]); if (pRx_EseCntx->pRsp != NULL) { offset = pRx_EseCntx->pRsp->len; phNxpEse_memcpy((pRx_EseCntx->pRsp->p_data + offset), p_data, data_len); pRx_EseCntx->pRsp->len += data_len; return TRUE; } else { LOG_E("Unsolicited response"); return FALSE; } } /****************************************************************************** * Function phNxpEseProto7816_ResetRecovery * * Description This internal function is called to do reset the recovery pareameters * * param[in] void * * Returns Always return TRUE. * ******************************************************************************/ static bool_t phNxpEseProto7816_ResetRecovery(void) { phNxpEseProto7816_3_Var.recoveryCounter = 0; return TRUE; } /****************************************************************************** * Function phNxpEseProto7816_RecoverySteps * * Description This internal function is called when 7816-3 stack failed to recover * after PH_PROTO_7816_FRAME_RETRY_COUNT, and the interface has to be * recovered * * param[in] void * * Returns Always return TRUE. * ******************************************************************************/ static bool_t phNxpEseProto7816_RecoverySteps(void) { sFrameInfo_t *pRx_lastRcvdSframeInfo = &phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdSframeInfo; sFrameInfo_t *pNextTx_SframeInfo = &phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.SframeInfo; if(phNxpEseProto7816_3_Var.recoveryCounter <= PH_PROTO_7816_FRAME_RETRY_COUNT) { #if defined(T1oI2C_UM11225) pRx_lastRcvdSframeInfo->sFrameType = INTF_RESET_REQ; phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= SFRAME; pNextTx_SframeInfo->sFrameType = INTF_RESET_REQ; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_S_INTF_RST; #elif defined(T1oI2C_GP1_0) pRx_lastRcvdSframeInfo->sFrameType = SWR_REQ; phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= SFRAME; pNextTx_SframeInfo->sFrameType = SWR_REQ; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_S_SWR; #endif } else { /* If recovery fails */ phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = IDLE_STATE; } return TRUE; } /****************************************************************************** * Function phNxpEseProto7816_DecodeSFrameData * * Description This internal function is to decode S-frame payload. * * param[in] uint8_t; data buffer * * Returns void * ******************************************************************************/ static void phNxpEseProto7816_DecodeSFrameData(uint8_t *p_data) { uint8_t maxSframeLen = 0, frameOffset = 0; ENSURE_OR_GO_EXIT(p_data != NULL); #if defined(T1oI2C_UM11225) frameOffset = PH_PROPTO_7816_LEN_UPPER_OFFSET; #elif defined(T1oI2C_GP1_0) /* current GP implementation support max payload of 0x00FE, so considering lower offset */ frameOffset = PH_PROPTO_7816_LEN_LOWER_OFFSET; #endif maxSframeLen = p_data[frameOffset] + frameOffset; /* to be in sync with offset which starts from index 0 */ while(maxSframeLen > frameOffset) { frameOffset += 1; /* To get the Type (TLV) */ LOG_D("%s frameoffset=%d value=0x%x ", __FUNCTION__, frameOffset, p_data[frameOffset]); frameOffset += p_data[frameOffset + 1]; /* Goto the end of current marker */ } exit: return; } /****************************************************************************** * Function phNxpEseProto7816_DecodeFrame * * Description This internal function is used to * 1. Identify the received frame * 2. If the received frame is I-frame with expected sequence number, store it or else send R-NACK 3. If the received frame is R-frame, 3.1 R-ACK with expected seq. number: Send the next chained I-frame 3.2 R-ACK with different sequence number: Sebd the R-Nack 3.3 R-NACK: Re-send the last frame 4. If the received frame is S-frame, send back the correct S-frame response. * * param[in] uint8_t : data buffer * param[in] uint32_t : buffer length * * Returns On success return TRUE or else FALSE. * ******************************************************************************/ static bool_t phNxpEseProto7816_DecodeFrame(uint8_t *p_data, uint32_t data_len) { bool_t status = TRUE; uint8_t pcb; phNxpEseProto7816_PCB_bits_t pcb_bits; iFrameInfo_t *pRx_lastRcvdIframeInfo = &phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdIframeInfo; rFrameInfo_t *pNextTx_RframeInfo = &phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.RframeInfo; sFrameInfo_t *pNextTx_SframeInfo = &phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.SframeInfo; iFrameInfo_t *pLastTx_IframeInfo = &phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.IframeInfo; sFrameInfo_t *pLastTx_SframeInfo = &phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.SframeInfo; rFrameInfo_t *pRx_lastRcvdRframeInfo = &phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdRframeInfo; sFrameInfo_t *pRx_lastRcvdSframeInfo = &phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdSframeInfo; LOG_D("Retry Counter = %d ", phNxpEseProto7816_3_Var.recoveryCounter); ENSURE_OR_GO_EXIT(p_data != NULL); pcb = p_data[PH_PROPTO_7816_PCB_OFFSET]; phNxpEse_memset(&pcb_bits, 0x00, sizeof(phNxpEseProto7816_PCB_bits_t)); phNxpEse_memcpy(&pcb_bits, &pcb, sizeof(uint8_t)); if (0x00 == pcb_bits.msb) /* I-FRAME decoded should come here */ { LOG_D("%s I-Frame Received ", __FUNCTION__); phNxpEseProto7816_3_Var.wtx_counter = 0; phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdFrameType = IFRAME ; if (pRx_lastRcvdIframeInfo->seqNo != pcb_bits.bit7) // != pcb_bits->bit7) { LOG_D("%s I-Frame lastRcvdIframeInfo.seqNo:0x%x ", __FUNCTION__, pcb_bits.bit7); phNxpEseProto7816_ResetRecovery(); pRx_lastRcvdIframeInfo->seqNo = 0x00; pRx_lastRcvdIframeInfo->seqNo |= pcb_bits.bit7; if (pcb_bits.bit6) { pRx_lastRcvdIframeInfo->isChained = TRUE; phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = RFRAME; pNextTx_RframeInfo->errCode = NO_ERROR; phNxpEseProro7816_SaveRxframeData(&p_data[PH_PROPTO_7816_INF_BYTE_OFFSET], data_len - PH_PROTO_7816_INF_FILED); phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_R_ACK ; } else { pRx_lastRcvdIframeInfo->isChained = FALSE; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = IDLE_STATE; phNxpEseProro7816_SaveRxframeData(&p_data[PH_PROPTO_7816_INF_BYTE_OFFSET], data_len - PH_PROTO_7816_INF_FILED); } } else { sm_sleep(DELAY_ERROR_RECOVERY/1000); if(phNxpEseProto7816_3_Var.recoveryCounter < PH_PROTO_7816_FRAME_RETRY_COUNT) { phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = RFRAME; pNextTx_RframeInfo->errCode = OTHER_ERROR; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_R_NACK ; phNxpEseProto7816_3_Var.recoveryCounter++; } else { phNxpEseProto7816_RecoverySteps(); phNxpEseProto7816_3_Var.recoveryCounter++; } } } else if ((0x01 == pcb_bits.msb) && (0x00 == pcb_bits.bit7)) /* R-FRAME decoded should come here */ { LOG_D("%s R-Frame Received", __FUNCTION__); phNxpEseProto7816_3_Var.wtx_counter = 0; phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdFrameType = RFRAME; pRx_lastRcvdRframeInfo->seqNo = 0; // = 0; pRx_lastRcvdRframeInfo->seqNo |= pcb_bits.bit5; if ((pcb_bits.lsb == 0x00) && (pcb_bits.bit2 == 0x00)) { pRx_lastRcvdRframeInfo->errCode = NO_ERROR; phNxpEseProto7816_ResetRecovery(); if (pRx_lastRcvdRframeInfo->seqNo != pLastTx_IframeInfo->seqNo) { phNxpEseProto7816_SetNextIframeContxt(); phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_IFRAME; } } /* Error handling 1 : Parity error */ else if (((pcb_bits.lsb == 0x01) && (pcb_bits.bit2 == 0x00)) || /* Error handling 2: Other indicated error */ ((pcb_bits.lsb == 0x00) && (pcb_bits.bit2 == 0x01))) { sm_sleep(DELAY_ERROR_RECOVERY/1000); if((pcb_bits.lsb == 0x00) && (pcb_bits.bit2 == 0x01)) pRx_lastRcvdRframeInfo->errCode = OTHER_ERROR; else pRx_lastRcvdRframeInfo->errCode = PARITY_ERROR; if(phNxpEseProto7816_3_Var.recoveryCounter < PH_PROTO_7816_FRAME_RETRY_COUNT) { if(phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.FrameType == IFRAME) { phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx = phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_IFRAME; phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = IFRAME; } else if(phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.FrameType == RFRAME) { /* Usecase to reach the below case: I-frame sent first, followed by R-NACK and we receive a R-NACK with last sent I-frame sequence number*/ if ((pRx_lastRcvdRframeInfo->seqNo == pLastTx_IframeInfo->seqNo) && (phNxpEseProto7816_3_Var.lastSentNonErrorframeType == IFRAME)) { phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx = phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_IFRAME; phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = IFRAME; } /* Usecase to reach the below case: R-frame sent first, followed by R-NACK and we receive a R-NACK with next expected I-frame sequence number*/ else if ((pRx_lastRcvdRframeInfo->seqNo != pLastTx_IframeInfo->seqNo) && (phNxpEseProto7816_3_Var.lastSentNonErrorframeType == RFRAME)) { phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = RFRAME; pNextTx_RframeInfo->errCode = NO_ERROR; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_R_ACK ; } /* Usecase to reach the below case: I-frame sent first, followed by R-NACK and we receive a R-NACK with next expected I-frame sequence number + all the other unexpected scenarios */ else { phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= RFRAME; pNextTx_RframeInfo->errCode = OTHER_ERROR; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_R_NACK ; } } else if(phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.FrameType == SFRAME) { /* Copy the last S frame sent */ phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx = phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx; } phNxpEseProto7816_3_Var.recoveryCounter++; } else { phNxpEseProto7816_RecoverySteps(); phNxpEseProto7816_3_Var.recoveryCounter++; } //resend previously send I frame } /* Error handling 3 */ else if ((pcb_bits.lsb == 0x01) && (pcb_bits.bit2 == 0x01)) { sm_sleep(DELAY_ERROR_RECOVERY/1000); if(phNxpEseProto7816_3_Var.recoveryCounter < PH_PROTO_7816_FRAME_RETRY_COUNT) { pRx_lastRcvdRframeInfo->errCode = SOF_MISSED_ERROR; phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx = phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx; phNxpEseProto7816_3_Var.recoveryCounter++; } else { phNxpEseProto7816_RecoverySteps(); phNxpEseProto7816_3_Var.recoveryCounter++; } } } else if ((0x01 == pcb_bits.msb) && (0x01 == pcb_bits.bit7)) /* S-FRAME decoded should come here */ { LOG_D("%s S-Frame Received ", __FUNCTION__); int32_t frameType = (int32_t)(pcb & 0x3F); /*discard upper 2 bits */ phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdFrameType = SFRAME; if(frameType!=WTX_REQ) { phNxpEseProto7816_3_Var.wtx_counter = 0; } switch(frameType) { case RESYNCH_RSP: pRx_lastRcvdSframeInfo->sFrameType = RESYNCH_RSP; phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= UNKNOWN; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = IDLE_STATE; break; case IFSC_RES: pRx_lastRcvdSframeInfo->sFrameType = IFSC_RES; phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= UNKNOWN; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = IDLE_STATE ; break; case ABORT_RES: pRx_lastRcvdSframeInfo->sFrameType = ABORT_RES; phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= UNKNOWN; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = IDLE_STATE ; break; case WTX_REQ: phNxpEseProto7816_3_Var.wtx_counter++; LOG_D("%s Wtx_counter value - %lu ", __FUNCTION__, phNxpEseProto7816_3_Var.wtx_counter); LOG_D("%s Wtx_counter wtx_counter_limit - %lu ", __FUNCTION__, phNxpEseProto7816_3_Var.wtx_counter_limit); /* Previous sent frame is some S-frame but not WTX response S-frame */ if (pLastTx_SframeInfo->sFrameType != WTX_RSP && phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.FrameType == SFRAME) { /* Goto recovery if it keep coming here for more than recovery counter max. value */ if(phNxpEseProto7816_3_Var.recoveryCounter < PH_PROTO_7816_FRAME_RETRY_COUNT) { /* Re-transmitting the previous sent S-frame */ phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx = phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx; phNxpEseProto7816_3_Var.recoveryCounter++; } else { phNxpEseProto7816_RecoverySteps(); phNxpEseProto7816_3_Var.recoveryCounter++; } } else { /* Checking for WTX counter with max. allowed WTX count */ if(phNxpEseProto7816_3_Var.wtx_counter == phNxpEseProto7816_3_Var.wtx_counter_limit) { #if defined(T1oI2C_UM11225) phNxpEseProto7816_3_Var.wtx_counter = 0; pRx_lastRcvdSframeInfo->sFrameType = INTF_RESET_REQ; phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= SFRAME; pNextTx_SframeInfo->sFrameType = INTF_RESET_REQ; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_S_INTF_RST; LOG_E("%s Interface Reset to eSE wtx count reached!!! ", __FUNCTION__); #elif defined(T1oI2C_GP1_0) phNxpEseProto7816_3_Var.wtx_counter = 0; pRx_lastRcvdSframeInfo->sFrameType = SWR_REQ; phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= SFRAME; pNextTx_SframeInfo->sFrameType = SWR_REQ; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_S_SWR; LOG_E("%s Software Reset to eSE wtx count reached!!! ", __FUNCTION__); #endif } else { sm_sleep(DELAY_ERROR_RECOVERY/1000); pRx_lastRcvdSframeInfo->sFrameType = WTX_REQ; phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= SFRAME; pNextTx_SframeInfo->sFrameType = WTX_RSP; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_S_WTX_RSP ; } } break; #if defined(T1oI2C_UM11225) case INTF_RESET_RSP: if(p_data[PH_PROPTO_7816_FRAME_LENGTH_OFFSET] > 0) phNxpEseProto7816_DecodeSFrameData(p_data); phNxpEseProro7816_SaveRxframeData(&p_data[PH_PROPTO_7816_INF_BYTE_OFFSET], data_len - PH_PROTO_7816_INF_FILED); if(phNxpEseProto7816_3_Var.recoveryCounter > PH_PROTO_7816_FRAME_RETRY_COUNT){ /*Max recovery counter reached, send failure to APDU layer */ LOG_E("%s Max retry count reached!!! ", __FUNCTION__); phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = IDLE_STATE; status = FALSE; } else{ phNxpEseProto7816_ResetProtoParams(); pRx_lastRcvdSframeInfo->sFrameType = INTF_RESET_RSP; phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= UNKNOWN; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = IDLE_STATE; } break; case PROP_END_APDU_RSP: pRx_lastRcvdSframeInfo->sFrameType = PROP_END_APDU_RSP; if(p_data[PH_PROPTO_7816_FRAME_LENGTH_OFFSET] > 0) phNxpEseProto7816_DecodeSFrameData(p_data); phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= UNKNOWN; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = IDLE_STATE; break; case ATR_RES: pRx_lastRcvdSframeInfo->sFrameType = ATR_RES; if(p_data[PH_PROPTO_7816_FRAME_LENGTH_OFFSET] > 0) phNxpEseProto7816_DecodeSFrameData(p_data); phNxpEseProro7816_SaveRxframeData(&p_data[PH_PROPTO_7816_INF_BYTE_OFFSET], data_len - PH_PROTO_7816_INF_FILED); phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= UNKNOWN; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = IDLE_STATE; break; case CHIP_RESET_RES: pRx_lastRcvdSframeInfo->sFrameType = CHIP_RESET_RES; if(p_data[PH_PROPTO_7816_FRAME_LENGTH_OFFSET] > 0) phNxpEseProto7816_DecodeSFrameData(p_data); phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= UNKNOWN; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = IDLE_STATE; break; #endif #if defined(T1oI2C_GP1_0) case SWR_RSP: if(p_data[PH_PROPTO_7816_FRAME_LENGTH_OFFSET] > 0) phNxpEseProto7816_DecodeSFrameData(p_data); if(phNxpEseProto7816_3_Var.recoveryCounter > PH_PROTO_7816_FRAME_RETRY_COUNT){ /*Max recovery counter reached, send failure to APDU layer */ LOG_E("%s Max retry count reached!!! ", __FUNCTION__); phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = IDLE_STATE; status = FALSE; } else{ phNxpEseProto7816_ResetProtoParams(); pRx_lastRcvdSframeInfo->sFrameType = SWR_RSP; phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= UNKNOWN; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = IDLE_STATE; } break; case RELEASE_RES: pRx_lastRcvdSframeInfo->sFrameType = RELEASE_RES; if(p_data[PH_PROPTO_7816_FRAME_LENGTH_OFFSET] > 0) phNxpEseProto7816_DecodeSFrameData(p_data); phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= UNKNOWN; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = IDLE_STATE; break; case CIP_RES: pRx_lastRcvdSframeInfo->sFrameType = CIP_RES; if(p_data[PH_PROPTO_7816_FRAME_LENGTH_OFFSET] > 0) phNxpEseProto7816_DecodeSFrameData(p_data); phNxpEseProro7816_SaveRxframeData(&p_data[PH_PROPTO_7816_INF_BYTE_OFFSET], data_len - PH_PROTO_7816_INF_FILED); phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= UNKNOWN; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = IDLE_STATE; break; case COLD_RESET_RES: pRx_lastRcvdSframeInfo->sFrameType = COLD_RESET_RES; if(p_data[PH_PROPTO_7816_FRAME_LENGTH_OFFSET] > 0) phNxpEseProto7816_DecodeSFrameData(p_data); phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= UNKNOWN; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = IDLE_STATE; break; #endif default: LOG_E("%s Wrong S-Frame Received ", __FUNCTION__); break; } } else { LOG_E("%s Wrong-Frame Received ", __FUNCTION__); } exit: return status ; } /****************************************************************************** * Function phNxpEseProto7816_ProcessResponse * * Description This internal function is used to * 1. Check the CRC * 2. Initiate decoding of received frame of data. * * param[in] void * * Returns On success return TRUE or else FALSE. * ******************************************************************************/ static bool_t phNxpEseProto7816_ProcessResponse(void* conn_ctx) { uint32_t data_len = 0; uint8_t *p_data = NULL; bool_t status = FALSE; bool_t checkCrcPass = TRUE; iFrameInfo_t *pRx_lastRcvdIframeInfo = &phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdIframeInfo; rFrameInfo_t *pNextTx_RframeInfo = &phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.RframeInfo; sFrameInfo_t *pLastTx_SframeInfo = &phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.SframeInfo; status = phNxpEseProto7816_GetRawFrame(conn_ctx, &data_len, &p_data); LOG_D("%s p_data ----> %p len ----> 0x%lx ", __FUNCTION__,p_data, data_len); if(TRUE == status) { /* Resetting the timeout counter */ phNxpEseProto7816_3_Var.timeoutCounter = PH_PROTO_7816_VALUE_ZERO; /* CRC check followed */ checkCrcPass = phNxpEseProto7816_CheckCRC(data_len, p_data); if(checkCrcPass == TRUE) { /* Resetting the RNACK retry counter */ phNxpEseProto7816_3_Var.rnack_retry_counter = PH_PROTO_7816_VALUE_ZERO; status = phNxpEseProto7816_DecodeFrame(p_data, data_len); } else { LOG_E("%s CRC Check failed ", __FUNCTION__); if(phNxpEseProto7816_3_Var.rnack_retry_counter < phNxpEseProto7816_3_Var.rnack_retry_limit) { phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdFrameType = INVALID ; phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= RFRAME; pNextTx_RframeInfo->errCode = PARITY_ERROR; pNextTx_RframeInfo->seqNo = (!pRx_lastRcvdIframeInfo->seqNo) << 4; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_R_NACK ; phNxpEseProto7816_3_Var.rnack_retry_counter++; } else { phNxpEseProto7816_3_Var.rnack_retry_counter = PH_PROTO_7816_VALUE_ZERO; /* Re-transmission failed completely, Going to exit */ phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = IDLE_STATE; phNxpEseProto7816_3_Var.timeoutCounter = PH_PROTO_7816_VALUE_ZERO; status = FALSE; } } } else { LOG_E("%s phNxpEseProto7816_GetRawFrame failed starting recovery", __FUNCTION__); if ((SFRAME == phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.FrameType) && ((WTX_RSP == pLastTx_SframeInfo->sFrameType) || (RESYNCH_RSP == pLastTx_SframeInfo->sFrameType))) { if(phNxpEseProto7816_3_Var.rnack_retry_counter < phNxpEseProto7816_3_Var.rnack_retry_limit) { phNxpEse_clearReadBuffer(conn_ctx); phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdFrameType = INVALID ; phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= RFRAME; pNextTx_RframeInfo->errCode = OTHER_ERROR; pNextTx_RframeInfo->seqNo = (!pRx_lastRcvdIframeInfo->seqNo) << 4; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_R_NACK ; phNxpEseProto7816_3_Var.rnack_retry_counter++; } else { LOG_E("%s Recovery failed completely, Going to exit ", __FUNCTION__); phNxpEseProto7816_3_Var.rnack_retry_counter = PH_PROTO_7816_VALUE_ZERO; /* Recovery failed completely, Going to exit */ phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = IDLE_STATE; phNxpEseProto7816_3_Var.timeoutCounter = PH_PROTO_7816_VALUE_ZERO; } } /*ISO7816-3 Rule 7.1 Implementation*/ else if (IFRAME == phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.FrameType) { if(phNxpEseProto7816_3_Var.rnack_retry_counter < phNxpEseProto7816_3_Var.rnack_retry_limit) { phNxpEse_clearReadBuffer(conn_ctx); phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdFrameType = INVALID ; phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= RFRAME; pNextTx_RframeInfo->errCode = PARITY_ERROR; pNextTx_RframeInfo->seqNo = (!pRx_lastRcvdIframeInfo->seqNo) << 4; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_R_NACK ; phNxpEseProto7816_3_Var.rnack_retry_counter++; } else { LOG_E("%s Recovery failed completely, Going to exit ", __FUNCTION__); phNxpEseProto7816_3_Var.rnack_retry_counter = PH_PROTO_7816_VALUE_ZERO; /* Recovery failed completely, Going to exit */ phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = IDLE_STATE; phNxpEseProto7816_3_Var.timeoutCounter = PH_PROTO_7816_VALUE_ZERO; } } else { sm_sleep(DELAY_ERROR_RECOVERY/1000); /* re transmit the frame */ if(phNxpEseProto7816_3_Var.timeoutCounter < PH_PROTO_7816_TIMEOUT_RETRY_COUNT) { phNxpEseProto7816_3_Var.timeoutCounter++; LOG_E("%s re-transmitting the previous frame ", __FUNCTION__); phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx = phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx ; } else { /* Recovery failed completely, Going to exit */ LOG_E("%s Recovery failed completely, Going to exit ", __FUNCTION__); phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = IDLE_STATE; phNxpEseProto7816_3_Var.timeoutCounter = PH_PROTO_7816_VALUE_ZERO; } } } return status; } /****************************************************************************** * Function TransceiveProcess * * Description This internal function is used to * 1. Send the raw data received from application after computing CRC * 2. Receive the the response data from ESE, decode, process and * store the data. * * param[in] void * * Returns On success return TRUE or else FALSE. * ******************************************************************************/ static bool_t TransceiveProcess(void* conn_ctx) { bool_t status = FALSE; sFrameInfo_t sFrameInfo; sFrameInfo.sFrameType = INVALID_REQ_RES; sFrameInfo.sFrameType = INVALID_REQ_RES; while(phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState != IDLE_STATE) { LOG_D("%s nextTransceiveState %x ", __FUNCTION__, phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState); switch(phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState) { case SEND_IFRAME: status = phNxpEseProto7816_SendIframe(conn_ctx, phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo); break; case SEND_R_ACK: status = phNxpEseProto7816_sendRframe(conn_ctx, RACK); break; case SEND_R_NACK: status = phNxpEseProto7816_sendRframe(conn_ctx, RNACK); break; case SEND_S_RSYNC: sFrameInfo.sFrameType = RESYNCH_REQ; status = phNxpEseProto7816_SendSFrame(conn_ctx, sFrameInfo); break; case SEND_S_WTX_RSP: sFrameInfo.sFrameType = WTX_RSP; status = phNxpEseProto7816_SendSFrame(conn_ctx, sFrameInfo); break; #if defined(T1oI2C_UM11225) case SEND_S_CHIP_RST: sFrameInfo.sFrameType = CHIP_RESET_REQ; status = phNxpEseProto7816_SendSFrame(conn_ctx, sFrameInfo); break; case SEND_S_INTF_RST: sFrameInfo.sFrameType = INTF_RESET_REQ; status = phNxpEseProto7816_SendSFrame(conn_ctx, sFrameInfo); break; case SEND_S_EOS: sFrameInfo.sFrameType = PROP_END_APDU_REQ; status = phNxpEseProto7816_SendSFrame(conn_ctx, sFrameInfo); break; case SEND_S_ATR: sFrameInfo.sFrameType = ATR_REQ; status = phNxpEseProto7816_SendSFrame(conn_ctx, sFrameInfo); break; #elif defined(T1oI2C_GP1_0) case SEND_S_CIP: sFrameInfo.sFrameType = CIP_REQ; status = phNxpEseProto7816_SendSFrame(conn_ctx, sFrameInfo); break; case SEND_S_SWR: sFrameInfo.sFrameType = SWR_REQ; status = phNxpEseProto7816_SendSFrame(conn_ctx, sFrameInfo); break; case SEND_S_RELEASE: sFrameInfo.sFrameType = RELEASE_REQ; status = phNxpEseProto7816_SendSFrame(conn_ctx, sFrameInfo); break; case SEND_S_COLD_RST: sFrameInfo.sFrameType = COLD_RESET_REQ; status = phNxpEseProto7816_SendSFrame(conn_ctx, sFrameInfo); break; #else #error Either T1oI2C_UM11225 or T1oI2C_GP1_0 must be defined. #endif default: phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = IDLE_STATE; break; } if(TRUE == status) { phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx = phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx; status = phNxpEseProto7816_ProcessResponse(conn_ctx); } else { LOG_E("%s Transceive send failed, going to recovery! ", __FUNCTION__); phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = IDLE_STATE; } }; return status; } /****************************************************************************** * Function phNxpEseProto7816_Transceive * * Description This function is used to * 1. Send the raw data received from application after computing CRC * 2. Receive the the response data from ESE, decode, process and * store the data. * 3. Get the final complete data and sent back to application * * param[in] phNxpEse_data: Command to ESE C-APDU * param[out] phNxpEse_data: Response from ESE R-APDU * * Returns On success return TRUE or else FALSE. * ******************************************************************************/ bool_t phNxpEseProto7816_Transceive(void* conn_ctx, phNxpEse_data *pCmd, phNxpEse_data *pRsp) { bool_t status = FALSE; uint32_t reqDataLen = 0; phNxpEseRx_Cntx_t *pRx_EseCntx = &phNxpEseProto7816_3_Var.phNxpEseRx_Cntx; iFrameInfo_t *pNextTx_IframeInfo = &phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo; LOG_D("Enter %s ", __FUNCTION__); if((NULL == pCmd) || (NULL == pRsp) || (phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState != PH_NXP_ESE_PROTO_7816_IDLE)) return status; reqDataLen = pRsp->len; /* Updating the transceive information to the protocol stack */ phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = PH_NXP_ESE_PROTO_7816_TRANSCEIVE; pNextTx_IframeInfo->p_data = pCmd->p_data; pNextTx_IframeInfo->totalDataLen = pCmd->len; pRx_EseCntx->pRsp = pRsp; LOG_D("Transceive data ptr 0x%p len:%ld ", pCmd->p_data, pCmd->len); phNxpEseProto7816_SetFirstIframeContxt(); status = TransceiveProcess(conn_ctx); if(FALSE == status) { /* ESE hard reset to be done */ LOG_E("%s Transceive failed, hard reset to proceed ",__FUNCTION__); } else if(pRsp->len > reqDataLen ) { LOG_W("Need '%d' bytes. Got '%d' to copy.", pRsp->len, reqDataLen); pRsp->len = 0; status = FALSE; } phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = PH_NXP_ESE_PROTO_7816_IDLE; return status; } /****************************************************************************** * Function phNxpEseProto7816_RSync * * Description This function is used to send the RSync command * * param[in] void * * Returns On success return TRUE or else FALSE. * ******************************************************************************/ static bool_t phNxpEseProto7816_RSync(void* conn_ctx) { bool_t status = FALSE; sFrameInfo_t *pNextTx_SframeInfo = &phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.SframeInfo; phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = PH_NXP_ESE_PROTO_7816_TRANSCEIVE; /* send the end of session s-frame */ phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= SFRAME; pNextTx_SframeInfo->sFrameType = RESYNCH_REQ; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_S_RSYNC; status = TransceiveProcess(conn_ctx); phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = PH_NXP_ESE_PROTO_7816_IDLE; return status; } /****************************************************************************** * Function phNxpEseProto7816_ResetProtoParams * * Description This function is used to reset the 7816 protocol stack instance * * param[in] void * * Returns Always return TRUE. * ******************************************************************************/ bool_t phNxpEseProto7816_ResetProtoParams(void) { unsigned long int tmpWTXCountlimit = PH_PROTO_7816_VALUE_ZERO; unsigned long int tmpRNACKCountlimit = PH_PROTO_7816_VALUE_ZERO; phNxpEseRx_Cntx_t *pRx_EseCntx = &phNxpEseProto7816_3_Var.phNxpEseRx_Cntx; iFrameInfo_t *pNextTx_IframeInfo = &phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo; iFrameInfo_t *pLastTx_IframeInfo = &phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.IframeInfo; tmpWTXCountlimit = phNxpEseProto7816_3_Var.wtx_counter_limit; tmpRNACKCountlimit = phNxpEseProto7816_3_Var.rnack_retry_limit; phNxpEse_memset(&phNxpEseProto7816_3_Var, PH_PROTO_7816_VALUE_ZERO, sizeof(phNxpEseProto7816_t)); phNxpEseProto7816_3_Var.wtx_counter_limit = tmpWTXCountlimit; phNxpEseProto7816_3_Var.rnack_retry_limit = tmpRNACKCountlimit; phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = PH_NXP_ESE_PROTO_7816_IDLE; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = IDLE_STATE; pRx_EseCntx->lastRcvdFrameType = INVALID; phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = INVALID; pNextTx_IframeInfo->maxDataLen = IFSC_SIZE_SEND; pNextTx_IframeInfo->p_data = NULL; phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.FrameType = INVALID; pLastTx_IframeInfo->maxDataLen = IFSC_SIZE_SEND; pLastTx_IframeInfo->p_data = NULL; /* Initialized with sequence number of the last I-frame sent */ pNextTx_IframeInfo->seqNo = PH_PROTO_7816_VALUE_ONE; /* Initialized with sequence number of the last I-frame received */ pRx_EseCntx->lastRcvdIframeInfo.seqNo = PH_PROTO_7816_VALUE_ONE; /* Initialized with sequence number of the last I-frame received */ pLastTx_IframeInfo->seqNo = PH_PROTO_7816_VALUE_ONE; phNxpEseProto7816_3_Var.recoveryCounter = PH_PROTO_7816_VALUE_ZERO; phNxpEseProto7816_3_Var.timeoutCounter = PH_PROTO_7816_VALUE_ZERO; phNxpEseProto7816_3_Var.wtx_counter = PH_PROTO_7816_VALUE_ZERO; /* This update is helpful in-case a R-NACK is transmitted from the MW */ phNxpEseProto7816_3_Var.lastSentNonErrorframeType = UNKNOWN; phNxpEseProto7816_3_Var.rnack_retry_counter = PH_PROTO_7816_VALUE_ZERO; pRx_EseCntx->pRsp = NULL; return TRUE; } /****************************************************************************** * Function phNxpEseProto7816_Reset * * Description This function is used to reset the 7816 protocol stack instance * * param[in] void * * Returns On success return TRUE or else FALSE. * ******************************************************************************/ bool_t phNxpEseProto7816_Reset(void) { bool_t status = FALSE; /* Resetting host protocol instance */ status = phNxpEseProto7816_ResetProtoParams(); /* Resynchronising ESE protocol instance */ //status = phNxpEseProto7816_RSync(); return status; } /****************************************************************************** * Function phNxpEseProto7816_Open * * Description This function is used to open the 7816 protocol stack instance * * param[in] phNxpEseProto7816InitParam_t: ESE communication mode * param[out] phNxpEse_data: ATR Response from ESE * * Returns On success return TRUE or else FALSE. * ******************************************************************************/ bool_t phNxpEseProto7816_Open(void* conn_ctx, phNxpEseProto7816InitParam_t initParam, phNxpEse_data *AtrRsp) { bool_t status = FALSE; phNxpEseRx_Cntx_t *pRx_EseCntx = &phNxpEseProto7816_3_Var.phNxpEseRx_Cntx; status = phNxpEseProto7816_ResetProtoParams(); LOG_D("%s: First open completed", __FUNCTION__); /* Update WTX max. limit */ phNxpEseProto7816_3_Var.wtx_counter_limit = initParam.wtx_counter_limit; phNxpEseProto7816_3_Var.rnack_retry_limit = initParam.rnack_retry_limit; /*Intialise the buffers before hand so that we are able to receive data if RSync goes to recovery handling*/ pRx_EseCntx->pRsp = AtrRsp; pRx_EseCntx->pRsp->len = 0; if(initParam.interfaceReset) /* Do interface reset */ { /*After power ON , initialization state takes 5ms after which slave enters active state where slave can exchange data with the master */ sm_sleep(WAKE_UP_DELAY_MS); phNxpEse_clearReadBuffer(conn_ctx); #if defined(T1oI2C_UM11225) /* Interface Reset respond with ATR*/ status = phNxpEseProto7816_RSync(conn_ctx); if(status == TRUE) { status = phNxpEseProto7816_GetAtr(conn_ctx, AtrRsp); } #elif defined(T1oI2C_GP1_0) /* For GP soft reset does not respond with CIP so master should send CIP req. seperatly */ status = phNxpEseProto7816_RSync(conn_ctx); if(status == TRUE) { status = phNxpEseProto7816_GetCip(conn_ctx, AtrRsp); } #endif } else /* Do R-Sync */ { status = phNxpEseProto7816_RSync(conn_ctx); } return status; } /****************************************************************************** * Function phNxpEseProto7816_Close * * Description This function is used to close the 7816 protocol stack instance * * param[in] void * * Returns On success return TRUE or else FALSE. * ******************************************************************************/ bool_t phNxpEseProto7816_Close(void* conn_ctx) { sFrameInfo_t *pNextTx_SframeInfo = &phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.SframeInfo; bool_t status = FALSE; /*Explicitly Initilising to NULL as the Application layer does not intend to receive a response*/ phNxpEseRx_Cntx_t *pRx_EseCntx = &phNxpEseProto7816_3_Var.phNxpEseRx_Cntx; pRx_EseCntx->pRsp = NULL; if(phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState != PH_NXP_ESE_PROTO_7816_IDLE) return status; phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = PH_NXP_ESE_PROTO_7816_DEINIT; phNxpEseProto7816_3_Var.recoveryCounter = 0; phNxpEseProto7816_3_Var.wtx_counter = 0; #if defined(T1oI2C_UM11225) /* send the end of session s-frame */ phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= SFRAME; pNextTx_SframeInfo->sFrameType = PROP_END_APDU_REQ; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_S_EOS; #elif defined(T1oI2C_GP1_0) /* send the release request s-frame */ phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= SFRAME; pNextTx_SframeInfo->sFrameType = RELEASE_REQ; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_S_RELEASE; #endif status = TransceiveProcess(conn_ctx); if(FALSE == status) { /* reset all the structures */ LOG_E("%s TransceiveProcess failed ", __FUNCTION__); } phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = PH_NXP_ESE_PROTO_7816_IDLE; return status; } #if defined(T1oI2C_UM11225) /****************************************************************************** * Function phNxpEseProto7816_IntfReset * * Description This function is used to reset just the current interface and get the ATR response on successful reset * * param[in] phNxpEse_data: ATR response from ESE * * Returns On success return TRUE or else FALSE. * ******************************************************************************/ bool_t phNxpEseProto7816_IntfReset(void* conn_ctx, phNxpEse_data *AtrRsp) { bool_t status = FALSE; sFrameInfo_t *pNextTx_SframeInfo = &phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.SframeInfo; phNxpEseRx_Cntx_t *pRx_EseCntx = &phNxpEseProto7816_3_Var.phNxpEseRx_Cntx; ENSURE_OR_GO_EXIT(AtrRsp != NULL); phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = PH_NXP_ESE_PROTO_7816_TRANSCEIVE; phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= SFRAME; pNextTx_SframeInfo->sFrameType = INTF_RESET_REQ; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_S_INTF_RST; pRx_EseCntx->pRsp = AtrRsp; pRx_EseCntx->pRsp->len = 0; phNxpEse_clearReadBuffer(conn_ctx); status = TransceiveProcess(conn_ctx); if(FALSE == status) { /* reset all the structures */ LOG_E("%s TransceiveProcess failed ", __FUNCTION__); } phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = PH_NXP_ESE_PROTO_7816_IDLE; exit: return status ; } /****************************************************************************** * Function phNxpEseProto7816_ChipReset * * Description This function is used to reset just the current interface * * param[in] void * * Returns On success return TRUE or else FALSE. * ******************************************************************************/ bool_t phNxpEseProto7816_ChipReset(void* conn_ctx) { bool_t status = FALSE; sFrameInfo_t *pNextTx_SframeInfo = &phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.SframeInfo; phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = PH_NXP_ESE_PROTO_7816_TRANSCEIVE; phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= SFRAME; pNextTx_SframeInfo->sFrameType = CHIP_RESET_REQ; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_S_CHIP_RST; status = TransceiveProcess(conn_ctx); if(FALSE == status) { /* reset all the structures */ LOG_E("%s TransceiveProcess failed ", __FUNCTION__); } phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = PH_NXP_ESE_PROTO_7816_IDLE; return status ; } #endif #if defined(T1oI2C_GP1_0) /****************************************************************************** * Function phNxpEseProto7816_SoftReset * * Description This function is used only for T1oI2C GP to reset just the current interface * * param[in] void * * Returns On success return TRUE or else FALSE. * ******************************************************************************/ bool_t phNxpEseProto7816_SoftReset(void* conn_ctx) { bool_t status = FALSE; sFrameInfo_t *pNextTx_SframeInfo = &phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.SframeInfo; phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = PH_NXP_ESE_PROTO_7816_TRANSCEIVE; phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= SFRAME; pNextTx_SframeInfo->sFrameType = SWR_REQ; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_S_SWR; phNxpEse_clearReadBuffer(conn_ctx); status = TransceiveProcess(conn_ctx); if(FALSE == status) { /* reset all the structures */ LOG_E("%s TransceiveProcess failed ", __FUNCTION__); } phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = PH_NXP_ESE_PROTO_7816_IDLE; return status ; } /****************************************************************************** * Function phNxpEseProto7816_ColdReset * * Description This function is used to reset just the current interface * * param[in] void * * Returns On success return TRUE or else FALSE. * ******************************************************************************/ bool_t phNxpEseProto7816_ColdReset(void* conn_ctx) { bool_t status = FALSE; sFrameInfo_t *pNextTx_SframeInfo = &phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.SframeInfo; phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = PH_NXP_ESE_PROTO_7816_TRANSCEIVE; phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= SFRAME; pNextTx_SframeInfo->sFrameType = COLD_RESET_REQ; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_S_COLD_RST; status = TransceiveProcess(conn_ctx); if(FALSE == status) { /* reset all the structures */ LOG_E("%s TransceiveProcess failed ", __FUNCTION__); } phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = PH_NXP_ESE_PROTO_7816_IDLE; return status ; } #endif /****************************************************************************** * Function phNxpEseProto7816_SetIfscSize * * Description This function is used to set the max T=1 data send size * * param[in] uint16_t IFSC_Size * * Returns Always return TRUE (1). * ******************************************************************************/ bool_t phNxpEseProto7816_SetIfscSize(uint16_t IFSC_Size) { iFrameInfo_t *pNextTx_IframeInfo = &phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo; pNextTx_IframeInfo->maxDataLen = IFSC_Size; return TRUE; } #if defined(T1oI2C_UM11225) /****************************************************************************** * Function phNxpEseProto7816_GetAtr * * Description This function is used to reset just the current interface * * param[in] phNxpEse_data : ATR response from ESE * * Returns On success return TRUE or else FALSE. * ******************************************************************************/ bool_t phNxpEseProto7816_GetAtr(void* conn_ctx, phNxpEse_data *pRsp) { bool_t status = FALSE; sFrameInfo_t *pNextTx_SframeInfo = &phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.SframeInfo; phNxpEseRx_Cntx_t *pRx_EseCntx = &phNxpEseProto7816_3_Var.phNxpEseRx_Cntx; ENSURE_OR_GO_EXIT(pRsp != NULL); phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = PH_NXP_ESE_PROTO_7816_TRANSCEIVE; phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= SFRAME; pNextTx_SframeInfo->sFrameType = ATR_REQ; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_S_ATR; pRx_EseCntx->pRsp = pRsp; pRx_EseCntx->pRsp->len = 0; status = TransceiveProcess(conn_ctx); if(FALSE == status) { /* reset all the structures */ LOG_E("%s TransceiveProcess failed ", __FUNCTION__); } phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = PH_NXP_ESE_PROTO_7816_IDLE; exit: return status ; } #endif #if defined(T1oI2C_GP1_0) /****************************************************************************** * Function phNxpEseProto7816_GetCip * * Description This function is used only by T1oI2c GP to get CIP response * * param[in] phNxpEse_data : CIP response from ESE * * Returns On success return TRUE or else FALSE. * ******************************************************************************/ bool_t phNxpEseProto7816_GetCip(void* conn_ctx, phNxpEse_data *pRsp) { bool_t status = FALSE; phNxpEseRx_Cntx_t *pRx_EseCntx = &phNxpEseProto7816_3_Var.phNxpEseRx_Cntx; sFrameInfo_t *pNextTx_SframeInfo = &phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.SframeInfo; ENSURE_OR_GO_EXIT(pRsp != NULL); phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = PH_NXP_ESE_PROTO_7816_TRANSCEIVE; phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType= SFRAME; pNextTx_SframeInfo->sFrameType = CIP_REQ; phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_S_CIP; pRx_EseCntx->pRsp = pRsp; pRx_EseCntx->pRsp->len = 0; status = TransceiveProcess(conn_ctx); if(FALSE == status) { /* reset all the structures */ LOG_E("%s TransceiveProcess failed ", __FUNCTION__); } phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = PH_NXP_ESE_PROTO_7816_IDLE; exit: return status ; } #endif /** @} */