/*
 * Copyright (C) 2019 SAMSUNG S.LSI
 *
 * 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.
 */

#ifdef ESE_U_BOOT_BUILD
#include <linux/types.h>
#else
//#include <unistd.h>
#endif

#include <ese_api.h>
#include "ese_data.h"

/********************* Definitions and structures *****************************/

/*!
 * \brief S-Frame types used in 7816-3 protocol stack
 */
typedef enum sFrameTypes {
	RESYNCH_REQ = 0x00, /*!< Re-synchronisation request between host and ESE */
	RESYNCH_RSP = 0x20, /*!< Re-synchronisation response between host and ESE */
	IFSC_REQ = 0x01,    /*!< IFSC size request */
	IFSC_RES = 0x21,    /*!< IFSC size response */
	ABORT_REQ = 0x02,   /*!< Abort request */
	ABORT_RES = 0x22,   /*!< Abort response */
	WTX_REQ = 0x03,     /*!< WTX request */
	WTX_RSP = 0x23,     /*!< WTX response */
	INVALID_REQ_RES           /*!< Invalid request */
} sFrameTypes_t;

/*!
 * \brief R-Frame types used in 7816-3 protocol stack
 */
typedef enum rFrameTypes {
	RACK = 0x01, /*!< R-frame Acknowledgement frame indicator */
	RNACK = 0x02 /*!< R-frame Negative-Acknowledgement frame indicator */
} rFrameTypes_t;

/*!
 * \brief R-Frame error types used 7816-3 protocol stack
 */
typedef enum rFrameErrorTypes {
	NO_ERROR,         /*!< R-frame received with success */
	PARITY_ERROR,     /*!< R-frame received with parity error */
	OTHER_ERROR,      /*!< R-frame received with Other error */
	SOF_MISSED_ERROR, /*!< R-frame received with frame missing error */
	UNDEFINED_ERROR   /*!< R-frame received with some undefined error */
} rFrameErrorTypes_t;

/*!
 * \brief Frame types used in 7816-3 protocol stack
 */
typedef enum FrameTypes {
	IFRAME,  /*!< Frame type: I-frame */
	SFRAME,  /*!< Frame type: S-frame */
	RFRAME,  /*!< Frame type: R-frame */
	INVALID, /*!< Frame type: Invalid */
	UNKNOWN  /*!< Frame type: Unknown */
} FrameTypes_t;

/*!
 * \brief 7816-3 protocol stack states
 */
typedef enum State {
	IDLE,       /*!< 7816-3 protocol state: IDLE */
	TRANSCEIVE, /*!< 7816-3 protocol state: TRANSCEIVE going on */
	DEINIT /*!< 7816-3 protocol state: DeInit going on */
} State_t;

typedef enum TransceiveStates {
	IDLE_STATE,  /*!< 7816-3 protocol transceive state: IDLE */
	SEND_IFRAME, /*!< 7816-3 protocol transceive state: I-frame to be sent */
	SEND_R_NACK, /*!< 7816-3 protocol transceive state: R-NACK frame to be sent */
	SEND_R_ACK,  /*!< 7816-3 protocol transceive state: R-ACK frame to be sent */
	SEND_S_RSYNC,    /*!< 7816-3 protocol transceive state: S-frame
					  re-synchronisation command to be sent */
	SEND_S_WTX_REQ,  /*!< 7816-3 protocol transceive state: S-frame WTX command to
					  be sent */
	SEND_S_WTX_RSP /*!< 7816-3 protocol transceive state: S-frame WTX response to
					be sent */
} TransceiveStates_t;

typedef struct iFrameInfo {
	uint8_t isChained;  /*!< I-frame: Indicates if more frames to follow in the same
						data packet or not */
	uint8_t* p_data; /*!< I-frame: Actual data (Information field (INF)) */
	uint8_t seqNo;   /*!< I-frame: Sequence number of the I-frame */
	uint32_t maxDataLen;   /*!< I-frame: Maximum data length to be allowed in a
							single I-frame */
	uint32_t dataOffset;   /*!< I-frame: Offset to the actual data(INF) for the
							current frame of the packet */
	uint32_t totalDataLen; /*!< I-frame: Total data left in the packet, used to
							set the chained flag/calculating offset */
	uint32_t sendDataLen;  /*!< I-frame: the length of the I-frame actual data */
} iFrameInfo_t;

/*!
 * \brief S-frame information structure for ISO 7816-3
 *
 * This structure holds the  information of S-frame used for sending
 * and receiving the frame packet.
 *
 */
typedef struct sFrameInfo {
	sFrameTypes_t sFrameType; /*!< S-frame: Type of S-frame cmd/rsp */
} sFrameInfo_t;

/*!
 * \brief R-frame information structure for ISO 7816-3
 *
 * This structure holds the  information of R-frame used for sending
 * and receiving the frame packet.
 *
 */
typedef struct rFrameInfo {
	uint8_t seqNo; /*!< R-frame: Sequence number of the expected I-frame */
	rFrameErrorTypes_t errCode; /*!< R-frame: Error type */
} rFrameInfo_t;

/*!
 * \brief Next/Last Tx information structure holding transceive data
 *
 * This structure holds the information of the next/last sent
 * I-frame/R-frame/S-frame depending on the frame type
 *
 */
typedef struct NextTx_Info {
	iFrameInfo_t
		IframeInfo; /*!< Information of the I-frame to be send next or the last
					 sent I-frame depending on the frame type */
	rFrameInfo_t
		RframeInfo; /*!< Information of the R-frame to be send next or the last
					 sent R-frame depending on the frame type */
	sFrameInfo_t
		SframeInfo; /*!< Information of the S-frame to be send next or the last
					 sent S-frame depending on the frame type */
	FrameTypes_t
		FrameType; /*!< Frame (I/R/S frames) type to be sent next */
} NextTx_Info_t;

/*!
 * \brief Last sent Tx ransceive data
 *
 * This structure holds the information of the last sent
 * I-frame/R-frame/S-frame
 *
 */
typedef NextTx_Info_t LastTx_Info_t;

/*!
 * \brief Last Rx information structure holding transceive data
 *
 * This structure holds the information of the next/last sent
 * I-frame/R-frame/S-frame
 *
 */
typedef struct pCntx {
	iFrameInfo_t lastRcvdIframeInfo; /*!< I-frame: Last received frame */
	rFrameInfo_t lastRcvdRframeInfo; /*!< R-frame: Last received frame */
	sFrameInfo_t lastRcvdSframeInfo; /*!< S-frame: Last received frame */
	FrameTypes_t
	  lastRcvdFrameType; /*!< Last received frame type */
} Rx_Cntx_t;

/*!
 * \brief 7816-3 protocol stack context structure
 *
 * This structure holds the complete information of the
 * 7816-3 protocol stack context
 *
 */
typedef struct Protocol_data {
	LastTx_Info_t LastTx_Cntx; /*!< Last transmitted frame information */
	NextTx_Info_t NextTx_Cntx;           /*!< Next frame to be transmitted */
	Rx_Cntx_t Rx_Cntx; /*!< Last received frame information */
	TransceiveStates_t nextTransceiveState; /*!< Next Transceive state. It
											determines the next
											action to be done from host */
	State_t CurrentState; /*!< Current protocol stack state */
	uint8_t recoveryCounter; /*!< Keeps track of number of error recovery done.
							  Stack exits after it reaches max. count  */
	unsigned long int wtx_counter_limit; /*!< Max. WTX counter limit */
	unsigned long int wtx_counter;       /*!< WTX count tracker */
	uint8_t timeoutCounter; /*!< Keeps track of number of timeout happened. Stack
							 exits after it reaches max. count  */
	FrameTypes_t lastSentNonErrorframeType; /*!< Copy of the last sent non-error frame
									type: R-ACK, S-frame, I-frame */
	unsigned long int rnack_retry_limit;
	unsigned long int rnack_retry_counter;

	recv_buff_list_t recv_data;
} protocol_t;

typedef struct PCB_bits {
	uint8_t lsb : 1;  /*!< PCB: lsb */
	uint8_t bit2 : 1; /*!< PCB: bit2 */
	uint8_t bit3 : 1; /*!< PCB: bit3 */
	uint8_t bit4 : 1; /*!< PCB: bit4 */
	uint8_t bit5 : 1; /*!< PCB: bit5 */
	uint8_t bit6 : 1; /*!< PCB: bit6 */
	uint8_t bit7 : 1; /*!< PCB: bit7 */
	uint8_t msb : 1;  /*!< PCB: msb */
} PCB_bits_t;

typedef struct ese_data_t {
	uint32_t len;    /*!< length of the buffer */
	uint8_t* p_data; /*!< pointer to a buffer */
} ese_data;

//#define DELAY_ERROR_RECOVERY 3500 //usleep
#define DELAY_ERROR_RECOVERY 4 //msleep

#define PROTOCOL_HEADER_LEN				0x03
#define PROTOCOL_LRC_LEN				0x01
#define PROTOCOL_ZERO					0x00
#define PROTOCOL_TIMEOUT_RETRY_COUNT	1
#define PROTOCOL_PCB_OFFSET				1
#define PROTOCOL_SEND_SIZE				254
#define PROTOCOL_CHAINING				0x20
#define PROTOCOL_S_BLOCK_REQ			0xC0
#define PROTOCOL_S_BLOCK_RSP			0xE0
#define PROTOCOL_FRAME_RETRY_COUNT		10
#define PROTOCOL_WTX_DEFAULT_COUNT		500
#define PROTOCOL_MAX_RNACK_RETRY_LIMIT	0x02

#define ESE_T1_MAXLEN					32

ESE_STATUS eseProtocol_transceive(ese_data* pCmd, ese_data* pRsp);
ESE_STATUS eseProtocol_open(void);
ESE_STATUS eseProtocol_close(void);
ESE_STATUS eseProtocol_reset (void);
