/**
  *********************************************************************************
  *
  * @file    hal_crypt.h
  * @brief   Header file of CRYPT module driver.
  *
  * @version V1.0
  * @date    7 Dec 2017
  * @author  AE Team
  * @note
  *
  * Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
  *
  *********************************************************************************
  */

#ifndef __HAL_CRYPT_H__
#define __HAL_CRYPT_H__

#ifdef __cplusplus
 extern "C" {
#endif

#include "utils.h"
#include "hal_dma.h"

/** @addtogroup ES32FXXX_HAL
  * @{
  */

/** @addtogroup CRYPT
  * @{
  */

/** @defgroup CRYPT_Public_Types CRYPT Public Types
  * @{
  */

/**
  * @brief CRYPT encrypt or decrypt select
  */
typedef enum {
	CRYPT_ENCS_DECRYPT = 0, /**< Decrypt */
	CRYPT_ENCS_ENCRYPT = 1, /**< Encrypt */
}crypt_encs_t;

/**
  * @brief CRYPT aes key select
  */
typedef enum {
	CRYPT_AESKS_BITS_128 = 0, /**< 128bit key for aes */
	CRYPT_AESKS_BITS_192 = 1, /**< 192bit key for aes */
	CRYPT_AESKS_BITS_256 = 2, /**< 256bit key for aes */
}crypt_aesks_t;

/**
  * @brief CRYPT mode select
  */
typedef enum {
	CRYPT_MODE_ECB = 0, /**< ECB */
	CRYPT_MODE_CBC = 1, /**< CBC */
}crypt_mode_t;

/**
  * @brief CRYPT data type
  */
typedef enum {
	CRYPT_DATATYPE_EXCHANGE_NO = 0,	/**< No exchange */
	CRYPT_DATATYPE_EXCHANGE_16 = 1,	/**< 16bit exchange */
	CRYPT_DATATYPE_EXCHANGE_8 = 2,  /**< 8bit exchange */
	CRYPT_DATATYPE_EXCHANGE_1 = 3,  /**< 1bit exchange */
}crypt_datatype_t;

/**
  * @brief CRYPT des key select
  */
typedef enum {
	CRYPT_DESKS_KEYS_2 = 0, /**< 2 key for des */
	CRYPT_DESKS_KEYS_3 = 1, /**< 3 key for des */
	CRYPT_DESKS_KEYS_1 = 2, /**< 1 key for des */
}crypt_desks_t;

/**
  * @brief CRYPT crypt select
  */
typedef enum {
	CRYPT_CRYSEL_AES = 0, /**< AES */
	CRYPT_CRYSEL_DES = 1,  /**< DES */
}crypt_crysel_t;

/**
  * @brief CRYPT interrupt
  */
typedef enum {
	CRYPT_IT_IT = 0x80, /**< Interrupt */
}crypt_it_t;

/**
  * @brief CRYPT interrupt flag
  */
typedef enum {
	CRYPT_FLAG_AESIF = 0x1,  /**< Aes flag */
	CRYPT_FLAG_DESIF = 0x2,  /**< Des flag */
	CRYPT_FLAG_DONE = 0x100,  /**< Complete flag */
}crypt_flag_t;

/**
  * @brief CRYPT key select
  */
typedef enum {
	CRYPT_KS_AES_BITS_128 = 0, /**< 128bit key of aes */
	CRYPT_KS_AES_BITS_192 = 1, /**< 192bit key of aes */
	CRYPT_KS_AES_BITS_256 = 2, /**< 192bit key of ase */
	CRYPT_KS_DES_KEYS_1 = 3,   /**< 1 key of des */
	CRYPT_KS_DES_KEYS_2 = 4,   /**< 2 key of des */
	CRYPT_KS_DES_KEYS_3 = 5,    /**< 3 key of des */
}crypt_ks_t;



/**
  * @brief CRYPT state structures definition
  */
typedef enum {
	CRYPT_STATE_RESET = 0x0, /**< Peripheral is not initialized */
	CRYPT_STATE_READY = 0x1, /**< Peripheral Initialized and ready for use */
	CRYPT_STATE_BUSY = 0x2,  /**< An internal process is ongoing */
	CRYPT_STATE_ERROR = 0x4,  /**< Error */
} crypt_state_t;

/**
  * @brief CRYPT key length
  */
typedef enum {
	KEY_2_LEN = 2, /**< Key's lenth is 2 */
	KEY_4_LEN = 4, /**< Key's lenth is 4 */
	KEY_6_LEN = 6, /**< Key's lenth is 6 */
	KEY_8_LEN = 8,  /**< Key's lenth is 8 */
} crypt_key_len_t;

/**
  * @brief CRYPT ivr length
  */
typedef enum {
	IVR_2_LEN = 0, /**< Ivr's lenth is 2 */
	IVR_4_LEN = 1,  /**< Ivr's lenth is 4 */
} crypt_ivr_len_t;

/**
  * @brief CRYPT data type
  */
typedef enum {
	DATA_32_BIT = 0, /**< 32 bit data,don't swap */
	DATA_16_BIT = 1, /**< 16 bit data,swap */
	DATA_8_BIT = 2,  /**< 8 bit data,swap */
	DATA_1_BIT = 3,   /**< 1 bit data, swap */
} crypt_data_t;

/**
  * @brief CRYPT init structure definition
  */
typedef struct {
	crypt_mode_t mode;     /**< Crypt mode */
	crypt_data_t type;     /**< Data type select */
	crypt_ks_t key_select; /**< Key select */
} crypt_init_t;

/**
  * @brief  CRYPT Handle Structure definition
  */
typedef struct crypt_handle_s {
	CRYPT_TypeDef *perh;   /**< Register base address */
	crypt_init_t init;     /**< CRYPT required parameters */
#ifdef HAL_DMA
	dma_handle_t hdma_m2p; /**< CRYPT DMA handle parameters memory to crypt module */
	dma_handle_t hdma_p2m; /**< CRYPT DMA handle parameters crypt module to memory */
#endif
	uint8_t *plain_text;   /**< Pointer to plain text */
	uint8_t *cipher_text;  /**< Pointer to cipher text */
	uint32_t size;         /**< The size of crypt data buf */
	uint32_t count;        /**< The count of crypt data buf */
	uint32_t step;         /**< The step of once crypt 2(des) or 4(aes) */
	uint32_t dir;          /**< ENCRYPT or DECRYPT */
	uint32_t ivr[4];       /**< The ivr of crypt */
	uint32_t key[8];       /**< The key of crypt */
	lock_state_t lock;     /**< Locking object */
	crypt_state_t state;   /**< CRYPT operation state */

	void (*crypt_cplt_cbk)(struct crypt_handle_s *arg); /**< Crypt completed callback */
	void (*err_cplt_cbk)(struct crypt_handle_s *arg);   /**< Crypt error callback */
}crypt_handle_t;
/**
  * @}
  */

/** @defgroup CRYPT_Public_Macros CRYPT Public Macros
  * @{
  */
#define CRYPT_GO(handle) 		((handle)->perh->CR.GO = 1)
#define CRYPT_FIFOEN_ENABLE(handle) 	((handle)->perh->CR.FIFOEN = 1)
#define CRYPT_FIFOEN_DISABLE(handle) 	((handle)->perh->CR.FIFOEN = 0)
#define CRYPT_IVREN_ENABLE(handle) 	((handle)->perh->CR.IVREN = 1)
#define CRYPT_IVREN_DISABLE(handle) 	((handle)->perh->CR.IVREN = 0)
#define CRYPT_IE_ENABLE(handle)		((handle)->perh->CR.IE = 1)
#define CRYPT_IE_DISABLE(handle)	((handle)->perh->CR.IE = 0)
#define CRYPT_DMA_ENABLE(handle)	((handle)->perh->CR.DMAEN = 1)
#define CRYPT_DMA_DISABLE(handle)	((handle)->perh->CR.DMAEN = 0)
#define CRYPT_SETDIR(handle,dir)	((handle)->perh->CR.ENCS = (dir))
#define CRYPT_WRITE_FIFO(handle,data)   ((handle)->perh->FIFO.Word = (data))
#define CRYPT_READ_FIFO(handle)		((handle)->perh->FIFO.Word)
/**
  * @}
  */

/** @defgroup CRYPT_Private_Macros   CRYPT Private Macros
  * @{
  */
#define IS_CRYPT(x)		((x) == CRYPT)
#define IS_CRYPT_MODE(x) 	(((x) == CRYPT_MODE_ECB) ||   \
				 ((x) == CRYPT_MODE_CBC))
#define IS_CRYPT_KS(x) 		(((x) == CRYPT_KS_AES_BITS_128) || \
				 ((x) == CRYPT_KS_AES_BITS_192) || \
				 ((x) == CRYPT_KS_AES_BITS_256) || \
				 ((x) == CRYPT_KS_DES_KEYS_1)   || \
				 ((x) == CRYPT_KS_DES_KEYS_2)   || \
				 ((x) == CRYPT_KS_DES_KEYS_3))
#define IS_CRYPT_IT(x)		((x) == CRYPT_IT_IT)
#define IS_CRYPT_FLAG(x) 	(((x) == CRYPT_FLAG_AESIF) || \
				 ((x) == CRYPT_FLAG_DESIF) || \
				 ((x) == CRYPT_FLAG_DONE))
#define IS_CRYPT_IVR_LEN(x)	(((x) == IVR_2_LEN) ||\
				 ((x) == IVR_4_LEN))
#define IS_CRYPT_KEY_LEN(x)	(((x) == KEY_2_LEN) || \
				 ((x) == KEY_4_LEN) || \
				 ((x) == KEY_6_LEN) || \
				 ((x) == KEY_8_LEN))
/**
  * @}
  */

/** @addtogroup CRYPT_Public_Functions
  * @{
  */

/** @addtogroup CRYPT_Public_Functions_Group1
  * @{
  */
hal_status_t crypt_init(crypt_handle_t *hperh);
hal_status_t crypt_write_key(crypt_handle_t *hperh,uint32_t * key,crypt_key_len_t len);
hal_status_t crypt_read_key(crypt_handle_t *hperh,uint32_t * key,crypt_key_len_t len);
hal_status_t crypt_write_ivr(crypt_handle_t *hperh,uint32_t * ivr,crypt_ivr_len_t len);
hal_status_t crypt_read_ivr(crypt_handle_t *hperh,uint32_t * ivr,crypt_ivr_len_t len);
/**
  * @}
  */

/** @addtogroup CRYPT_Public_Functions_Group2
  * @{
  */
hal_status_t crypt_encrypt(crypt_handle_t *hperh, uint8_t * plain_text, uint8_t * cipher_text, uint32_t size);
hal_status_t crypt_decrypt(crypt_handle_t *hperh,uint8_t * cipher_text, uint8_t * plain_text, uint32_t size);
hal_status_t crypt_encrypt_by_it(crypt_handle_t *hperh, uint8_t * plain_text, uint8_t *cipher_text, uint32_t size);
hal_status_t crypt_decrypt_by_it(crypt_handle_t *hperh, uint8_t * plain_text, uint8_t *cipher_text, uint32_t size);
#ifdef HAL_DMA
hal_status_t crypt_encrypt_by_dma(crypt_handle_t *hperh, uint8_t * plain_text,
             uint8_t *cipher_text, uint32_t size, uint8_t channel_m2p, uint8_t channel_p2m);
hal_status_t crypt_decrypt_by_dma(crypt_handle_t *hperh, uint8_t * cipher_text,
               uint8_t *plain_text, uint32_t size, uint8_t channel_m2p, uint8_t channel_p2m);
#endif
/**
  * @}
  */

/** @addtogroup CRYPT_Public_Functions_Group3
  * @{
  */
#ifdef HAL_DMA
hal_status_t crypt_dma_pause(crypt_handle_t *hperh);
hal_status_t crypt_dma_resume(crypt_handle_t *hperh);
hal_status_t crypt_dma_stop(crypt_handle_t *hperh);
#endif
void crypt_irq_handle(crypt_handle_t *hperh);
/**
  * @}
  */

/** @addtogroup CRYPT_Public_Functions_Group4
  * @{
  */
void crypt_interrupt_config(crypt_handle_t *hperh, crypt_it_t it, type_func_t state);
flag_status_t crypt_get_flag_status(crypt_handle_t *hperh, crypt_flag_t flag);
void crypt_clear_flag_status(crypt_handle_t *hperh, crypt_flag_t flag);
it_status_t crypt_get_it_status(crypt_handle_t *hperh, crypt_it_t it);
/**
  * @}
  */

/** @addtogroup CRYPT_Public_Functions_Group5
  * @{
  */
crypt_state_t crypt_get_state(crypt_handle_t *hperh);
/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

#ifdef __cplusplus
}
#endif

#endif
