blob: adbefd2c34649efd8f0843eefa26cefa3ad42780 [file] [log] [blame]
/*
* 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 <phNxpEseProto7816_3.h>
#include <phNxpEsePal_i2c.h>
#include <phEseTypes.h>
#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, 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;
if(RNACK == rFrameType) /* R-NACK */
{
recv_ack[PH_PROPTO_7816_PCB_OFFSET] = 0x82;
}
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 ", __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)
{
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
{
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;
}
}
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
{
/* Re-transmission failed completely, Going to exit */
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
/** @} */