#ifndef __SEC_APDU_H__
#define __SEC_APDU_H__

#include "sec_EseStatus.h"

#ifdef USE_QSEE
#include <stdint.h>
#endif
#ifdef USE_MOBICORE
#include <stdint.h>
#endif

#ifdef USE_BLOWFISH
#include <stdint.h>
#include <tee_spi.h>
#include <stdio.h>
extern TEES_SPIHandler handler;
#define MAX_BUFFER_SIZE 258
#endif

#ifdef USE_TRUSTY_UNISOC
#include <stdint.h>
#endif

#define MIN_HEADER_LEN  4

#define ESESTATUS_INVALID_INS               0x1001
#define ESESTATUS_INVALID_CHANNLE_ID        0x1002
#define ESESTATUS_INVALID_OFFSET            0x1003

#ifndef EXTENDED_APDU
#define MAX_CAPDU_SIZE                      261
#define MAX_RAPDU_SIZE                      258
#define MAX_CAPDU_DATA_SIZE                 255
#define MAX_RAPDU_DATA_SIZE                 256
#else
#define MAX_CAPDU_SIZE                      32776 //MAX_CAPDU_DATA_SIZE + header(9)
#define MAX_RAPDU_SIZE                      32770 //MAX_RAPDU_DATA_SIZE + SW(2)
#define MAX_CAPDU_DATA_SIZE                 32767 //(32*1024-1)
#define MAX_RAPDU_DATA_SIZE                 32768 //(32*1024)
#endif

#define MAX_AID_SIZE                        16

#define RESULT_SPI_OPEN_FAILED              -1
#define RESULT_SPI_INIT_FAILED              -2

#ifdef COMMON_VENDOR
#define CHIP_VENDOR_NXP_JCOP40              1
#define CHIP_VENDOR_THALES_UT20             101
#define CHIP_VENDOR_THALES_UT51             102
#define CHIP_VENDOR_THALES_UT60             103

#define RESULT_NOT_SUPPORTED                -100

int spiOpenWithChipVendor(uint8_t chipVendor);
extern uint8_t chip_vendor;
#endif

typedef struct secEse_7816_cpdu {
    uint8_t cla; /* Class of instruction */
    uint8_t ins; /* Instruction code */
    uint8_t p1; /* Instruction parameter 1 */
    uint8_t p2; /* Instruction parameter 2 */
    uint16_t lc; /* No of data present in the data field of the command */
    uint8_t cpdu_type; /*0 - short len, 1 = extended len, this field is valid only if le > 0*/
    uint8_t  *pdata; /*application data*/
    uint8_t le_type; /*0 - Le absent ,1 - one byte le,2 - two byte le or 3 - 3  byte le*/
    uint32_t le; /* le value field */
} secEse_7816_cpdu_t, *p_secEse_7816_cpdu_t;

typedef struct secEse_7816_rpdu {
    uint8_t sw1; /*Status byte most significant byte */
    uint8_t sw2; /*Status byte least significant byte */
    uint8_t  *pdata; /*Buffer allocated by caller*/
    uint16_t len; /* Lenght of the buffer, updated by calling api */
} secEse_7816_rpdu_t, *p_secEse_7816_rpdu_t;

extern int is_secure_spi_opened;

int spiOpen(void);
int spiClose(void);
/**
 * Open the eSE channel
 *
 * @param[out] channelId The eSE channel which is allocated
 *
 * @return 0 on success, negative on failure
 */
ESESTATUS secEseOpen(uint8_t* channelId);

/**
 * Close the eSE channel
 *
 * @param[in] channelId The eSE channel ID to be deallocated
 *
 * @return 0 on success, negative on failure
 */
ESESTATUS secEseClose(uint8_t channelId);

/**
 * Select the applet for each channel on eSE
 *
 * @param[in] channelId The eSE channel ID to be used
 * @param[in] aID The applet channel ID to be selected
 * @param[in] offset The start point of aID
 * @param[in] length The length of aID
 * @param[out] pRsp The reponse APDU(Need to be allocated include data before)
 * ex) secEse_7816_rpdu_t rpdu;
 *     uint8_t rpduData[4];
 *     rpdu.pdata = rpduData;
 *
 * @return 0 on success, negative on failure
 */
ESESTATUS secEseSelect(uint8_t channelId, uint8_t *aid, uint8_t offset, uint8_t length, p_secEse_7816_rpdu_t pRsp);

/**
 * Transmit the APDU to eSE
 *
 * @param[in] channelId The eSE channel ID to be used
 * @param[in] pCmd The commad APDU(Need to be allocated include data before)
 * ex) secEse_7816_cpdu_t cpdu;
 *     uint8_t cpduData[4];
 *     cpdu.cla = 0x00;
 *     cpdu.ins = 0xA4;
 *     cpdu.p1 = 0x04;
 *     cpdu.p2 = 0x00;
 *     cpdu.lc = length;
 *     cpdu.cpdu_type = 0x00;
 *     cpdu.pdata = cpduData;
 *     cpdu.le = 0x02;
 *     cpdu.le_type = 0x01;
 * @param[out] pRsp The reponse APDU(Need to be allocated include data before)
 * ex) secEse_7816_rpdu_t rpdu;
 *     uint8_t rpduData[4];
 *     rpdu.pdata = rpduData;
 *
 * @return 0 on success, negative on failure
 */
ESESTATUS secEseTransmit(uint8_t channelId, p_secEse_7816_cpdu_t pCmd, p_secEse_7816_rpdu_t pRsp);

ESESTATUS secEseAPDUTransmit(uint8_t channelId, uint8_t* pApdu, uint16_t apduLen, p_secEse_7816_rpdu_t pRsp);

ESESTATUS initProcess(void);

void set_increased_wtx_max_time(uint8_t time);

#endif  /* __SEC_APDU_H__ */

