/*
 *
 * Copyright 2016-2018,2020 NXP
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @par Description
 * This file implements the SmCom T1oI2C communication layer.
 *
 *****************************************************************************/

#ifdef T1oI2C

#include <assert.h>

#include "smComT1oI2C.h"
#include "phNxpEse_Api.h"
#include "phNxpEseProto7816_3.h"

#include "i2c_a7.h"
#include "sm_printf.h"
#include "phEseStatus.h"
#include "sm_apdu.h"

#ifdef FLOW_VERBOSE
#define NX_LOG_ENABLE_SMCOM_DEBUG 1
#else
//#define NX_LOG_ENABLE_SMCOM_DEBUG 1
#endif

#include "nxLog_smCom.h"
#include "nxEnsure.h"

static U32 smComT1oI2C_Transceive(void* conn_ctx, apdu_t * pApdu);
static U32 smComT1oI2C_TransceiveRaw(void* conn_ctx, U8 * pTx, U16 txLen, U8 * pRx, U32 * pRxLen);
U16 smComT1oI2C_AnswerToReset(void* conn_ctx, U8 *T1oI2Catr, U16 *T1oI2CatrLen);

U16 smComT1oI2C_Close(void *conn_ctx, U8 mode)
{
    ESESTATUS status;
    if (conn_ctx) {
        status=phNxpEse_EndOfApdu(conn_ctx);
        //status=phNxpEse_chipReset();
        if(status ==ESESTATUS_SUCCESS)
        {
            status=phNxpEse_close(conn_ctx);
        }
        else
        {
            LOG_E("Failed to close session ");
            return SMCOM_COM_FAILED;
        }
    }
    else {
        LOG_W("Invalid conn_ctx");
    }
    return SMCOM_OK;
}


U16 smComT1oI2C_Init(void **conn_ctx, const char *pConnString)
{
    ESESTATUS ret;
    phNxpEse_initParams initParams;
    initParams.initMode = ESE_MODE_NORMAL;

    if(conn_ctx != NULL) {
        *conn_ctx = NULL;
    }
    ret = phNxpEse_open(conn_ctx, initParams, pConnString);
    if (ret != ESESTATUS_SUCCESS)
    {
        LOG_E(" Failed to create physical connection with ESE ");
        return SMCOM_COM_FAILED;
    }
    return SMCOM_OK;
}

U16 smComT1oI2C_Open(void *conn_ctx, U8 mode, U8 seqCnt, U8 *T1oI2Catr, U16 *T1oI2CatrLen)
{
    ESESTATUS ret;
    phNxpEse_data AtrRsp;
    phNxpEse_initParams initParams;
    initParams.initMode = ESE_MODE_NORMAL;
    AtrRsp.len = *T1oI2CatrLen;
    AtrRsp.p_data = T1oI2Catr;

    if (conn_ctx == NULL) {
        // Connection context is stored in global variable contained in phNxpEse_Api.c
        smComT1oI2C_Init(NULL, NULL);
    }

    ret=phNxpEse_init(conn_ctx, initParams, &AtrRsp);
    if (ret != ESESTATUS_SUCCESS)
    {
        *T1oI2CatrLen=0;
        LOG_E(" Failed to Open session ");
        return SMCOM_COM_FAILED;
    }
    else
    {
       *T1oI2CatrLen = AtrRsp.len ; /*Retrive INF FIELD*/
    }
    return smCom_Init(&smComT1oI2C_Transceive, &smComT1oI2C_TransceiveRaw);
}

static U32 smComT1oI2C_Transceive(void* conn_ctx, apdu_t * pApdu)
{
    U32 respLen= MAX_APDU_BUF_LENGTH;
    U32 retCode = SMCOM_COM_FAILED;

    ENSURE_OR_GO_EXIT(pApdu != NULL);

    retCode = smComT1oI2C_TransceiveRaw(conn_ctx, (U8 *)pApdu->pBuf, pApdu->buflen, pApdu->pBuf, &respLen);
    pApdu->rxlen = (U16)respLen;
exit:
    return retCode;
}

static U32 smComT1oI2C_TransceiveRaw(void* conn_ctx, U8 * pTx, U16 txLen, U8 * pRx, U32 * pRxLen)
{
    phNxpEse_data pCmdTrans;
    phNxpEse_data pRspTrans={0};
    ESESTATUS txnStatus;

    pCmdTrans.len = txLen;
    pCmdTrans.p_data = pTx;

    pRspTrans.len = *pRxLen;
    pRspTrans.p_data = pRx;

    LOG_MAU8_D("APDU Tx>", pTx, txLen);
    txnStatus = phNxpEse_Transceive(conn_ctx, &pCmdTrans, &pRspTrans);
    if ( txnStatus == ESESTATUS_SUCCESS )
    {
        *pRxLen = pRspTrans.len;
        LOG_MAU8_D("APDU Rx<", pRx, pRspTrans.len);
    }
    else
    {
        *pRxLen = 0;
        LOG_E(" Transcive Failed ");
        return SMCOM_SND_FAILED;
    }

    return SMCOM_OK;
}

U16 smComT1oI2C_AnswerToReset(void* conn_ctx, U8 *T1oI2Catr, U16 *T1oI2CatrLen)
{
    phNxpEse_data pRsp= {0};
    ESESTATUS txnStatus;
    U16 status = SMCOM_NO_ATR;

    ENSURE_OR_GO_EXIT(T1oI2Catr != NULL);
    ENSURE_OR_GO_EXIT(T1oI2CatrLen != NULL);
#if defined(T1oI2C_UM11225)
    txnStatus= phNxpEse_getAtr(conn_ctx, &pRsp);
#elif defined(T1oI2C_GP1_0)
    txnStatus= phNxpEse_getCip(conn_ctx, &pRsp);
#endif
    if(txnStatus == ESESTATUS_SUCCESS)
    {
        *T1oI2CatrLen = pRsp.len;
        if (pRsp.len > 0) {
            memcpy(T1oI2Catr, pRsp.p_data, pRsp.len);
            status = SMCOM_OK;
        }
        else {
            LOG_E(" ATR/CIP Length is improper!!!");
        }
    }
    else
    {
        *T1oI2CatrLen = 0;
        LOG_E(" Failed to Retrieve ATR/CIP status ");
    }
exit:
    return status;
}

U16 smComT1oI2C_ComReset(void* conn_ctx)
{
    ESESTATUS status = ESESTATUS_SUCCESS;
    status = phNxpEse_deInit(conn_ctx);
    if(status !=ESESTATUS_SUCCESS)
    {
        LOG_E("Failed to Reset 7816 protocol instance ");
        return SMCOM_COM_FAILED;
    }
    return SMCOM_OK;
}

#endif /* T1oI2C */
