From cc432b761c884a0bd8e9d83db0a4e26109fc08b1 Mon Sep 17 00:00:00 2001
From: chen <15335560115@163.com>
Date: 星期五, 08 十一月 2024 15:35:38 +0800
Subject: [PATCH] 安邦手环GPS删除部分无用数据和修改4G波特率9600出厂测试固件

---
 keil/include/components/se/src/T1.c | 1670 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 1,670 insertions(+), 0 deletions(-)

diff --git a/keil/include/components/se/src/T1.c b/keil/include/components/se/src/T1.c
new file mode 100644
index 0000000..9c4231d
--- /dev/null
+++ b/keil/include/components/se/src/T1.c
@@ -0,0 +1,1670 @@
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "T1.h"
+#include "phdriver.h"
+#include "se_api.h"
+#include "mk_misc.h"
+#include "mk_trace.h"
+
+static uint8_t gp_data_tx[270];
+static uint8_t gp_data_tx_bck[270];
+uint8_t gp_data_rx[270];
+static T1_params g_T1_params;
+static uint8_t g_all_data_buf[1024];
+
+atr_info g_atr = {
+    .len = 0x13,
+    .vendor_ID = {0x00},
+    .dll_IC = 0x01,
+    .bgt = {0x00, 0x01},
+    .bwt = {0x03, 0xE8},
+    .max_freq = {0x4E, 0x20},
+    .checksum = 0x00,
+    .default_IFSC = 0xFE,
+    .num_channels = 0x01,
+    .max_IFSC = {0x00, 0xFF},
+    .capbilities = {0x00, 0x14}, // Extended frame length feature doesn't support
+};
+
+uint32_t g_recv_total_len = 0;
+
+static uint8_t t1_calculate_LRC(uint8_t *p_data, uint16_t offset, uint16_t len);
+static uint16_t t1_calculate_CRC(uint8_t *p_data, uint16_t offset, uint16_t len);
+static void t1_set_epilogue(uint8_t *p_data, uint16_t offset, uint16_t len);
+
+static ESESTATUS t1_read(uint16_t *p_data_len);
+
+static uint8_t set_info_len(uint8_t *p_data, uint16_t info_len);
+static uint16_t get_info_len(uint8_t *p_data);
+static ESESTATUS decode_ATR(uint8_t *p_data, bool is_CIP);
+static void free_tx_part_mem(void);
+static void reset_for_resync_rsp(void);
+
+static ESESTATUS do_T1_recovery_at_decode_Iframe(void);
+static ESESTATUS do_T1_recovery_at_decode_Sframe(void);
+static ESESTATUS do_T1_recovery_at_decode_Rframe(void);
+static ESESTATUS t1_recv_data_store_in_list(uint8_t *p_data, uint16_t data_len, uint16_t total_len);
+static void t1_recv_data_list_destroy(void);
+static void reset_ATR(void);
+
+/******************************************************************************
+ * @Function     Transmit_receive_process
+ * @Returns      On success return ESESTATUS_SUCCESS or else ESESTATUS error.
+ ******************************************************************************/
+ESESTATUS Transmit_receive_process(void)
+{
+    ESESTATUS status = ESESTATUS_SUCCESS;
+    g_ese_ctx.is_read_done = false;
+
+    g_recv_total_len = 0;
+    while (STATE_IDEL != g_ese_ctx.next_T1_state)
+    {
+        switch (g_ese_ctx.p_T1_params->tx_frame_type)
+        {
+            case IFRAME:
+            {
+                status = t1_send_Iframe();
+                break;
+            }
+
+            case RFRAME:
+            {
+                status = t1_send_Rframe();
+                break;
+            }
+
+            case SFRAME:
+            {
+                status = t1_send_Sframe();
+                break;
+            }
+            case FRAME_TYPE_INVALID_MAX:
+            case FRAME_TYPE_INVALID_MIN:
+            {
+                status = ESESTATUS_INVALID_PARAMETER;
+                LOG_INFO(TRACE_MODULE_SE, "%s : invalid T1 frame type: %d\r\n", __FUNCTION__, g_ese_ctx.p_T1_params->tx_frame_type);
+            }
+        }
+
+        if (ESESTATUS_SUCCESS == status)
+        {
+#ifdef DBG_LEVEL_STACK
+            gDumpStackFlag = false;
+#endif
+            g_ese_ctx.p_T1_params->blk_retry_cnt = 0;
+            status = response_process();
+            // Do not need handle the status value
+        }
+        else
+        {
+            if (((ESESTATUS_PH_IO != status) && (ESESTATUS_MEM_EXCEPTION != status)) || (g_ese_ctx.p_T1_params->blk_retry_cnt >= g_ese_ctx.max_blk_retry_cnt))
+            {
+                LOG_INFO(TRACE_MODULE_SE, "%s: send frame failed, frameType = %d, status = %d, retryCnt = %d\r\n", __FUNCTION__,
+                         g_ese_ctx.p_T1_params->tx_frame_type, status, g_ese_ctx.max_blk_retry_cnt);
+                g_ese_ctx.next_T1_state = STATE_IDEL;
+                break;
+            }
+            else
+            {
+                // resend
+                g_ese_ctx.p_T1_params->blk_retry_cnt++;
+            }
+        }
+    }
+
+    return status;
+}
+
+/******************************************************************************
+ * @Function     response_process
+ * @Returns      On success return ESESTATUS_SUCCESS or else ESESTATUS error.
+ ******************************************************************************/
+ESESTATUS response_process(void)
+{
+    ESESTATUS status = ESESTATUS_SUCCESS;
+    uint16_t data_len = 0;
+
+    // LOG_INFO(TRACE_MODULE_SE, "%s: enter\r\n", __FUNCTION__);
+    status = t1_read(&data_len);
+
+    if (ESESTATUS_SUCCESS == status)
+    {
+        status = t1_chk_epilogue(gp_data_rx, 0, data_len);
+        if (status == ESESTATUS_SUCCESS)
+        {
+            status = t1_decode_frame(data_len);
+
+            if (ESESTATUS_SUCCESS == status)
+            {
+            }
+        }
+        else
+        {
+            do_T1_recovery_at_undecode();
+        }
+    }
+    else if (ESESTATUS_FATAL_ERROR == status)
+    {
+        g_ese_ctx.next_T1_state = STATE_IDEL;
+    }
+    else
+    {
+        do_T1_recovery_at_undecode();
+    }
+
+    return status;
+}
+
+/******************************************************************************
+ * @Function         t1_send_Sframe
+ * @Returns          On success return ESESTATUS_SUCCESS or else ESESTATUS error.
+ ******************************************************************************/
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wswitch-enum"
+#endif
+ESESTATUS t1_send_Sframe(void)
+{
+    ESESTATUS status = ESESTATUS_SUCCESS;
+    int ret = -1;
+    uint8_t frame_len = 0;
+
+    if (SFRAME_TYPE_INVALID == g_ese_ctx.p_T1_params->tx_sub_Sframe_type)
+    {
+        LOG_INFO(TRACE_MODULE_SE, "%s : invalid S-block frame type: %d\r\n", __FUNCTION__, g_ese_ctx.p_T1_params->tx_sub_Sframe_type);
+        return ESESTATUS_INVALID_PARAMETER;
+    }
+    else
+    {
+        frame_len = get_header_len(true);
+    }
+
+    // memset(gp_data_tx, 0, sizeof(gp_data_tx));
+    switch (g_ese_ctx.p_T1_params->tx_sub_Sframe_type)
+    {
+        case RESYNC_REQ:
+        {
+            gp_data_tx[T1_PCB_OFFSET] = (T1_S_BLOCK_REQ_MASK | RESYNC_REQ);
+            break;
+        }
+
+        case IFS_REQ:
+        {
+            uint8_t len_offset = 0, info_len = 0x02;
+            frame_len += info_len;
+            gp_data_tx[T1_PCB_OFFSET] = (T1_S_BLOCK_REQ_MASK | IFS_REQ);
+            len_offset = set_info_len(gp_data_tx, info_len);
+            gp_data_tx[len_offset + 1] = (uint8_t)(g_ese_ctx.max_IFSD >> 8);
+            gp_data_tx[len_offset + 2] = (uint8_t)(g_ese_ctx.max_IFSD & 0xFF);
+            break;
+        }
+
+        case IFS_RSP:
+        {
+            uint8_t len_offset = 0, info_len = 0;
+            info_len = (uint8_t)get_info_len(gp_data_rx);
+            frame_len += info_len;
+            gp_data_tx[T1_PCB_OFFSET] = (T1_S_BLOCK_REQ_MASK | IFS_REQ);
+            len_offset = set_info_len(gp_data_tx, info_len);
+            memcpy(&gp_data_tx[len_offset + 1], &gp_data_rx[len_offset + 1], info_len);
+            break;
+        }
+
+        case ABORT_REQ:
+        {
+            gp_data_tx[T1_PCB_OFFSET] = (T1_S_BLOCK_REQ_MASK | ABORT_REQ);
+            break;
+        }
+        case WTX_RSP:
+        {
+            uint8_t len_offset = 0, info_len = 1;
+            frame_len += info_len;
+            gp_data_tx[T1_PCB_OFFSET] = (T1_S_BLOCK_REQ_MASK | WTX_RSP);
+            len_offset = set_info_len(gp_data_tx, info_len);
+            gp_data_tx[len_offset + 1] = g_ese_ctx.p_T1_params->wtx_info;
+            break;
+        }
+
+        case CIP_REQ:
+        {
+            /* Note:T1 CIP_REQ for ATR, the frame's INFO length should be 1 byte,
+             */
+            gp_data_tx[T1_PCB_OFFSET] = (T1_S_BLOCK_REQ_MASK | CIP_REQ);
+            break;
+        }
+
+        case PROP_END_APDU_REQ:
+        {
+            gp_data_tx[T1_PCB_OFFSET] = (T1_S_BLOCK_REQ_MASK | PROP_END_APDU_REQ);
+            break;
+        }
+
+        case HARD_RESET_REQ:
+        {
+            break;
+        }
+
+        case ATR_REQ:
+        {
+            gp_data_tx[T1_PCB_OFFSET] = (T1_S_BLOCK_REQ_MASK | ATR_REQ);
+            break;
+        }
+
+        default:
+        {
+            LOG_INFO(TRACE_MODULE_SE, "%s : invalid S-block frame type: %X\r\n", __FUNCTION__, g_ese_ctx.p_T1_params->tx_sub_Sframe_type);
+            break;
+        }
+    }
+
+    gp_data_tx[T1_NAD_OFFSET] = NAD_D2C;
+    // caculate LRC or CRC and set it to pFramebuff
+    t1_set_epilogue(gp_data_tx, 0, frame_len);
+
+    ret = phdriver_write(gp_data_tx, frame_len);
+    if (-1 == ret)
+    {
+        status = ESESTATUS_PH_IO;
+        LOG_INFO(TRACE_MODULE_SE, "write fail: %s, errno = %d, ret = %d\r\n", __FUNCTION__, errno, ret);
+    }
+
+    return status;
+}
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+
+/******************************************************************************
+ * @Function         t1_send_Iframe
+ * @Returns          On success return ESESTATUS_SUCCESS or else ESESTATUS error.
+ ******************************************************************************/
+ESESTATUS t1_send_Iframe(void)
+{
+    ESESTATUS status = ESESTATUS_SUCCESS;
+    int ret = -1;
+    uint16_t frame_len = 0;
+    uint8_t *p_frame_buf = NULL;
+    uint16_t len_offset = 0;
+    uint16_t send_len = 0;
+    uint16_t tx_data_offset = 0;
+
+    if (g_ese_ctx.p_T1_params->recovery_cnt > g_ese_ctx.max_recovery_cnt)
+    {
+        LOG_INFO(TRACE_MODULE_SE, "%s fatal error, recovery_cnt = %d\r\n", __FUNCTION__, g_ese_ctx.p_T1_params->recovery_cnt);
+        status = ESESTATUS_FATAL_ERROR;
+        goto cleanup;
+    }
+    else if ((g_ese_ctx.p_T1_params->p_data_tx_part != NULL))
+    {
+        // LOG_INFO(TRACE_MODULE_SE, "%s retry_send_part, tx_len_part = %u\r\n", __FUNCTION__, g_ese_ctx.p_T1_params->tx_len_part);
+        p_frame_buf = g_ese_ctx.p_T1_params->p_data_tx_part;
+        frame_len = g_ese_ctx.p_T1_params->tx_len_part;
+        goto retry_send_part;
+    }
+
+    tx_data_offset = g_ese_ctx.p_T1_params->tx_data_offset;
+
+    frame_len = (g_ese_ctx.is_T1_ext_hdr_len ? T1_EXT_HEADER_LEN : T1_HEADER_LEN) + ((LRC == g_atr.checksum) ? T1_LRC_LEN : T1_CRC_LEN);
+
+    if ((g_ese_ctx.p_T1_params->tx_len - tx_data_offset) > g_ese_ctx.max_IFSC)
+    {
+        g_ese_ctx.p_T1_params->is_device_chaining = true;
+        send_len = g_ese_ctx.max_IFSC;
+        tx_data_offset += g_ese_ctx.max_IFSC;
+    }
+    else
+    {
+        g_ese_ctx.p_T1_params->is_device_chaining = false;
+        send_len = g_ese_ctx.p_T1_params->tx_len - tx_data_offset;
+        tx_data_offset += send_len;
+    }
+
+    frame_len += send_len;
+    // memset(gp_data_tx, 0, sizeof(gp_data_tx));
+    p_frame_buf = gp_data_tx;
+
+    p_frame_buf[T1_NAD_OFFSET] = NAD_D2C;
+    len_offset = set_info_len(p_frame_buf, send_len);
+    memcpy((p_frame_buf + len_offset + 1), (g_ese_ctx.p_T1_params->p_data_tx + g_ese_ctx.p_T1_params->tx_data_offset), send_len);
+    g_ese_ctx.p_T1_params->tx_data_offset = tx_data_offset;
+
+    // memset(gp_data_tx_bck, 0, sizeof(gp_data_tx_bck));
+    memcpy(gp_data_tx_bck, p_frame_buf, frame_len);
+    g_ese_ctx.p_T1_params->p_data_tx_part = gp_data_tx_bck;
+    g_ese_ctx.p_T1_params->tx_len_part = frame_len;
+
+retry_send_part:
+    p_frame_buf[T1_PCB_OFFSET] = 0x00;
+    if (g_ese_ctx.p_T1_params->is_device_chaining)
+    {
+        p_frame_buf[T1_PCB_OFFSET] |= T1_CHAINING_MASK;
+    }
+    p_frame_buf[T1_PCB_OFFSET] |= (g_ese_ctx.seq_num_device << 6);
+
+    t1_set_epilogue(p_frame_buf, 0, frame_len);
+
+    ret = phdriver_write(p_frame_buf, frame_len);
+    if (-1 == ret)
+    {
+        status = ESESTATUS_PH_IO;
+        LOG_INFO(TRACE_MODULE_SE, "write fail: %s, errno = %d, ret = %d\r\n", __FUNCTION__, errno, ret);
+    }
+
+cleanup:
+
+    if (S_ABORT_RSP == g_ese_ctx.next_T1_state)
+    {
+        g_ese_ctx.next_T1_state = STATE_IDEL;
+        free_tx_part_mem();
+    }
+
+    return status;
+}
+
+/******************************************************************************
+ * @Function         t1_send_Rframe
+ * @Returns          On success return ESESTATUS_SUCCESS or else ESESTATUS error.
+ ******************************************************************************/
+ESESTATUS t1_send_Rframe(void)
+{
+    ESESTATUS status = ESESTATUS_SUCCESS;
+    int ret = -1;
+    uint8_t frame_len = 0;
+    uint8_t *p_frame_buff = gp_data_tx;
+
+    if (RNACK_INVALID_ERROR == g_ese_ctx.p_T1_params->tx_sub_Rframe_type)
+    {
+        LOG_INFO(TRACE_MODULE_SE, "%s : invalid R-block frame type: %d\r\n", __FUNCTION__, g_ese_ctx.p_T1_params->tx_sub_Sframe_type);
+        return ESESTATUS_INVALID_PARAMETER;
+    }
+    else
+    {
+        frame_len = get_header_len(true);
+    }
+
+    // memset(gp_data_tx, 0, sizeof(gp_data_tx));
+    // pFramebuff = gp_data_tx;
+
+    if (RNACK_PARITY_ERROR == g_ese_ctx.p_T1_params->tx_sub_Rframe_type)
+    {
+        p_frame_buff[1] = 0x81;
+    }
+    else if (RNACK_OTHER_ERROR == g_ese_ctx.p_T1_params->tx_sub_Rframe_type)
+    {
+        p_frame_buff[1] = 0x82;
+    }
+    else
+    { // if (RACK == g_ese_ctx.p_T1_params->subRFrameType) {
+        p_frame_buff[1] = 0x80;
+    }
+
+    p_frame_buff[1] |= (g_ese_ctx.seq_num_card << 4);
+
+    p_frame_buff[T1_NAD_OFFSET] = NAD_D2C;
+    // caculate LRC or CRC and set it to pFramebuff
+    t1_set_epilogue(p_frame_buff, 0, frame_len);
+
+    ret = phdriver_write(p_frame_buff, frame_len);
+    if (-1 == ret)
+    {
+        status = ESESTATUS_PH_IO;
+
+        LOG_INFO(TRACE_MODULE_SE, "write fail: %s, errno = %d, ret = %d\r\n", __FUNCTION__, errno, ret);
+    }
+    else
+    {
+        // LOG_INFO(TRACE_MODULE_SE, "\nTx", 2, pFramebuff, frameLen);
+        // LOG_INFO(TRACE_MODULE_SE, "\n");
+    }
+
+    if (NULL == p_frame_buff)
+    {
+        LOG_INFO(TRACE_MODULE_SE, "%s failed, frame buffer malloc memory failed\r\n", __FUNCTION__);
+        status = ESESTATUS_MEM_EXCEPTION;
+    }
+
+    return status;
+}
+
+/******************************************************************************
+ * @Function     t1_calculate_LRC
+ * @Param        p_data - data to compute the LRC over.
+ *               offset - calculate start offset.
+ *               len    - data length, not include the epilogue byte.
+ * @Returns      On success return the LRC of the data.
+ ******************************************************************************/
+static uint8_t t1_calculate_LRC(uint8_t *p_data, uint16_t offset, uint16_t len)
+{
+    uint8_t LRC = 0;
+    uint16_t i = 0;
+    for (i = offset; i < len; i++)
+    {
+        LRC = LRC ^ p_data[i];
+    }
+    return LRC;
+}
+
+/******************************************************************************
+ * @Function     t1_calculate_CRC
+ * @Param        p_data - data to compute the CRC over.
+ *               offset - calculate start offset.
+ *               len    - data length, not include the epilogue bytes..
+ * @Returns      On success return the CRC of the data.
+ ******************************************************************************/
+static uint16_t t1_calculate_CRC(uint8_t *p_data, uint16_t offset, uint16_t len)
+{
+    uint16_t crc;
+
+    crc = (uint16_t)CRC_PRESET;
+
+    int i, j;
+    for (i = offset; i < len; i++)
+    {
+        crc = crc ^ ((unsigned short)p_data[i]);
+        for (j = 0; j < 8; j++)
+        {
+            if ((crc & 0x0001) == 0x0001)
+            {
+                crc = (crc >> 1) ^ CRC_POLYNOMIAL;
+            }
+            else
+            {
+                crc = crc >> 1;
+            }
+        }
+    }
+    crc = ~crc;
+
+    return crc;
+}
+
+/******************************************************************************
+ * @Function     t1_set_epilogue
+ * @Param        p_data - data to compute the LRC or CRC over.
+ *               offset - calculate start offset.
+ *               len    - data length, include the epilogue byte(s).
+ ******************************************************************************/
+static void t1_set_epilogue(uint8_t *p_data, uint16_t offset, uint16_t len)
+{
+    if ((LRC == g_atr.checksum) ||
+        (CIP_REQ == g_ese_ctx.p_T1_params->tx_sub_Sframe_type)
+        /*|| (ATR_REQ == g_ese_ctx.p_T1_params->tx_sub_Sframe_type)*/
+        || (CIP_RSP == g_ese_ctx.p_T1_params->tx_sub_Sframe_type)
+        /*|| (ATR_RSP == g_ese_ctx.p_T1_params->tx_sub_Sframe_type)*/)
+    {
+        // LRC
+        p_data[len - 1] = t1_calculate_LRC(p_data, offset, len - 1);
+    }
+    else
+    {
+        const uint16_t CRC = t1_calculate_CRC(p_data, offset, len - 2);
+
+        p_data[len - 2] = (uint8_t)(CRC >> 8);
+        p_data[len - 1] = (uint8_t)CRC;
+    }
+}
+
+/******************************************************************************
+ * @Function     t1_chk_epilogue
+ * @Param        p_data  - data to compute the LRC or CRC over.
+ *               offset - calculate start offset.
+ *               len    - data length, include the epilogue byte(s).
+ * @Returns      ESESTATUS_SUCCESS if caculate result is equal to response's epilogue,
+ *               else ESESTATUS_PARITY_ERROR.
+ ******************************************************************************/
+ESESTATUS t1_chk_epilogue(uint8_t *p_data, uint16_t offset, uint16_t len)
+{
+    ESESTATUS status = ESESTATUS_PARITY_ERROR;
+
+    /* Note:T1 CIP_REQ for ATR, the frame's INFO length should be 1 byte,
+     *      do not support 2 bytes length.
+     *      And epiLogue field should use LRC (1 byte).
+     */
+    if ((LRC == g_atr.checksum) ||
+        (CIP_REQ == g_ese_ctx.p_T1_params->tx_sub_Sframe_type)
+        /*|| (ATR_REQ == g_ese_ctx.p_T1_params->tx_sub_Sframe_type)*/
+        || (CIP_RSP == g_ese_ctx.p_T1_params->tx_sub_Sframe_type)
+        /*|| (ATR_RSP == g_ese_ctx.p_T1_params->tx_sub_Sframe_type)*/)
+    {
+        // LRC
+        const uint8_t LRC = t1_calculate_LRC(p_data, offset, len - 1);
+        if (LRC == p_data[len - 1])
+        {
+            status = ESESTATUS_SUCCESS;
+        }
+    }
+    else
+    {
+        uint16_t rspCRC = (uint16_t)(((uint16_t)p_data[len - 2]) << 8);
+        rspCRC |= p_data[len - 1];
+        const uint16_t CRC = t1_calculate_CRC(p_data, offset, len - 2);
+        if (CRC == rspCRC)
+        {
+            status = ESESTATUS_SUCCESS;
+        }
+    }
+
+    return status;
+}
+
+/******************************************************************************
+ * @Function     t1_read
+ * @Param        p_data_len - point to data length.
+ * @Returns      On success return ESESTATUS_SUCCESS, else ESESTATUS_xxx.
+ ******************************************************************************/
+static ESESTATUS t1_read(uint16_t *p_data_len)
+{
+    ESESTATUS status = ESESTATUS_SUCCESS;
+    int ret = -1;
+    const uint32_t sof_max_cnt = g_ese_ctx.max_read_retry_cnt;
+    uint32_t sof_cnt = 0;
+    uint16_t total_cnt = 0, num_Bytes_to_read = 0, read_index = 0;
+
+#ifdef USE_SPI_SPLIT_READ
+    const uint8_t hdrLen = get_header_len(false) + 1;
+#else
+    const uint8_t hdrLen = g_ese_ctx.max_IFSD;
+#endif
+
+#ifdef DBG_LEVEL_STACK
+    if (gDumpStackFlag)
+    {
+        dumpCallstack();
+    }
+    gDumpStackFlag = true;
+#endif
+
+    // memset(gp_data_rx, 0x00, sizeof(gp_data_rx));
+    do
+    {
+        sys_timer_delay_ms(1); // 10
+
+        ret = phdriver_read(gp_data_rx, 1);
+
+        if ((ret < 0) || (NAD_C2DT != gp_data_rx[0]))
+        {
+            sof_cnt++;
+            continue;
+        }
+        else
+        {
+            phdriver_read(gp_data_rx + 1, (hdrLen - 1));
+
+            if (g_ese_ctx.is_T1_ext_hdr_len)
+            {
+                num_Bytes_to_read = (uint16_t)(((uint16_t)gp_data_rx[T1_FRAME_LEN_OFFSET]) << 8);
+                num_Bytes_to_read |= gp_data_rx[T1_FRAME_LEN_OFFSET2];
+
+                if (CRC == g_atr.checksum)
+                {
+                    num_Bytes_to_read += 1;
+                }
+            }
+            else
+            {
+                num_Bytes_to_read = gp_data_rx[T1_FRAME_LEN_OFFSET];
+            }
+            read_index = hdrLen;
+            total_cnt += hdrLen;
+            // LOG_INFO(TRACE_MODULE_SE, "_spi_read() [HDR] read data right!! \r\n");
+            break;
+        }
+    } while (sof_cnt < sof_max_cnt);
+
+    /*SOF Read timeout happened, go for frame retransmission*/
+    if (sof_cnt == sof_max_cnt)
+    {
+        if (ret >= 0)
+        {
+            ret = -1;
+            status = ESESTATUS_PH_IOR_INVALID_DATA;
+        }
+        else
+        {
+            status = ESESTATUS_PH_IO;
+        }
+        // LOG_INFO(TRACE_MODULE_SE, "_spi_read() [HDR] execption, ret = %d, sofCnt = %X\r\n", ret, sofCnt);
+    }
+
+#ifdef USE_SPI_SPLIT_READ
+    if (ret < 0)
+    {
+        if ((-1 == ret) && (4 == errno))
+        {
+            // Interrupted system call, is NFC_DLD_FLUSH
+            status = ESESTATUS_FATAL_ERROR;
+        }
+    }
+    else
+    {
+        if (0 != num_Bytes_to_read)
+        {
+            ret = phdriver_read(&gp_data_rx[read_index], num_Bytes_to_read);
+            if (ret < 0)
+            {
+                status = ESESTATUS_PH_IO;
+                LOG_INFO(TRACE_MODULE_SE, "%s _spi_read() [payload] execption, ret = %x, errno = %d\r\n", __FUNCTION__, ret, errno);
+            }
+            else
+            {
+                // LOG_INFO(TRACE_MODULE_SE, " _spi_read() [payload] right!!!!!!!!!!!!!!\r\n");
+                total_cnt += num_Bytes_to_read;
+            }
+        }
+    }
+#endif
+
+    if (ESESTATUS_SUCCESS != status)
+    {
+        *p_data_len = 0;
+        // LOG_INFO(TRACE_MODULE_SE, "RxFail\r\n");
+        // LOG_INFO(TRACE_MODULE_SE, "read fail: %s, errno = %d, ret = %d\r\n", __FUNCTION__, errno, ret);
+    }
+    else
+    {
+        *p_data_len = total_cnt;
+
+        // LOG_INFO(TRACE_MODULE_SE, "Rx\r\n");
+    }
+    return status;
+}
+
+/******************************************************************************
+ * @Function     t1_decode_frame
+ * @Param        data_len - data length.
+ * @Returns      On success return ESESTATUS_SUCCESS, else ESESTATUS_xxx.
+ ******************************************************************************/
+ESESTATUS t1_decode_frame(uint16_t data_len)
+{
+    ESESTATUS status = ESESTATUS_SUCCESS;
+    uint8_t pcb = gp_data_rx[T1_PCB_OFFSET];
+    T1_pcb_bits *p_pcb_bits;
+
+    if (g_ese_ctx.p_T1_params)
+    {
+        p_pcb_bits = &g_ese_ctx.p_T1_params->last_rx_pcb_bits;
+    }
+    else
+    {
+        LOG_INFO(TRACE_MODULE_SE, "p_T1_params is NULL\r\n");
+        return ESESTATUS_INVALID_PCB;
+    }
+
+    // memset(p_pcb_bits, 0x00, sizeof(T1_pcb_bits));
+    memcpy(p_pcb_bits, &pcb, sizeof(uint8_t));
+    uint16_t infoLen = get_info_len(gp_data_rx);
+    uint8_t dataOffset = get_header_len(false);
+
+    if (0x00 == p_pcb_bits->msb)
+    {
+        // I-FRAME decoded
+        g_ese_ctx.p_T1_params->last_rx_frame_type = IFRAME;
+        g_ese_ctx.p_T1_params->last_rx_sub_Sframe_type = SFRAME_TYPE_INVALID;
+        g_ese_ctx.p_T1_params->last_rx_sub_Rframe_type = RNACK_INVALID_ERROR;
+
+        g_ese_ctx.p_T1_params->wtx_cnt = 0;
+
+        if (g_ese_ctx.is_seq_num_dr && (p_pcb_bits->bit7 != g_ese_ctx.seq_num_card))
+        {
+            g_ese_ctx.seq_num_card ^= 0x01;
+        }
+        g_ese_ctx.is_seq_num_dr = false;
+
+        if (p_pcb_bits->bit7 == g_ese_ctx.seq_num_card)
+        {
+            g_ese_ctx.p_T1_params->recovery_cnt = 0;
+            g_ese_ctx.p_T1_params->resync_CIP_req_cnt = 0;
+            g_ese_ctx.is_resync_recovery_flag = false;
+
+            if (p_pcb_bits->bit6)
+            {
+                g_ese_ctx.p_T1_params->is_card_chaining = true;
+                g_ese_ctx.seq_num_card = (g_ese_ctx.seq_num_card ^ 0x01);
+
+                status = t1_recv_data_store_in_list(&gp_data_rx[dataOffset], infoLen, data_len);
+
+                if (ESESTATUS_SUCCESS != status)
+                {
+                    LOG_INFO(TRACE_MODULE_SE, "%s, t1_recv_data_store_in_list failed, terminate transmission, status = %d\r\n", __FUNCTION__, status);
+                    g_ese_ctx.next_T1_state = STATE_IDEL;
+                    free_tx_part_mem();
+                }
+                else
+                {
+                    // Card response chaining and successfully, then request the next segments data.
+                    g_ese_ctx.next_T1_state = R_ACK;
+                    g_ese_ctx.p_T1_params->tx_frame_type = RFRAME;
+                    g_ese_ctx.p_T1_params->tx_sub_Rframe_type = RACK;
+                }
+            }
+            else
+            {
+                g_ese_ctx.p_T1_params->is_card_chaining = false;
+                status = t1_recv_data_store_in_list(&gp_data_rx[dataOffset], infoLen, data_len);
+                if (ESESTATUS_SUCCESS != status)
+                {
+                    LOG_INFO(TRACE_MODULE_SE, "%s, t1_recv_data_store_in_list failed, terminate transmission, status = %d\r\n", __FUNCTION__, status);
+                }
+                else
+                {
+                    // Not chaining, and response success.
+                }
+
+                g_ese_ctx.seq_num_device = (g_ese_ctx.seq_num_device ^ 0x01);
+                g_ese_ctx.seq_num_card = (g_ese_ctx.seq_num_card ^ 0x01);
+                g_ese_ctx.next_T1_state = STATE_IDEL;
+                free_tx_part_mem();
+            }
+        }
+        else
+        {
+            LOG_INFO(TRACE_MODULE_SE, "%s, received invalid seqNum = %02X, seq_num_card = %02X\r\n", __FUNCTION__, p_pcb_bits->bit7, g_ese_ctx.seq_num_card);
+            status = do_T1_recovery_at_decode_Iframe();
+        }
+    }
+    else if ((0x01 == p_pcb_bits->msb) && (0x00 == p_pcb_bits->bit7))
+    {
+        // R-FRAME decoded
+        g_ese_ctx.p_T1_params->last_rx_frame_type = RFRAME;
+        g_ese_ctx.p_T1_params->last_rx_sub_Sframe_type = SFRAME_TYPE_INVALID;
+
+        if ((0x00 == p_pcb_bits->lsb) && (0x00 == p_pcb_bits->bit2))
+        {
+            g_ese_ctx.p_T1_params->last_rx_sub_Rframe_type = RACK;
+            if ((NULL != g_ese_ctx.p_T1_params->p_data_tx) && g_ese_ctx.p_T1_params->is_device_chaining)
+            {
+                if (g_ese_ctx.seq_num_device != p_pcb_bits->bit5)
+                {
+                    // Device chaining, valid card request the next segments of device data to send.
+                    // seq_num_device should changed, but the seq_num_card unchanged until received card I-block.
+                    g_ese_ctx.seq_num_device = p_pcb_bits->bit5;
+                    g_ese_ctx.next_T1_state = I_BLK;
+                    g_ese_ctx.p_T1_params->tx_frame_type = IFRAME;
+                    g_ese_ctx.p_T1_params->tx_sub_Rframe_type = RNACK_INVALID_ERROR;
+                    free_tx_part_mem();
+                }
+                else
+                {
+                    status = do_T1_recovery_at_decode_Rframe();
+                }
+            }
+            else if (NULL != g_ese_ctx.p_T1_params->p_data_tx)
+            {
+                status = ESESTATUS_INVALID_PARAMETER;
+                LOG_INFO(TRACE_MODULE_SE, "%s: Device initiates unchaining I-block cannot receive RACK, terminate transmit.\r\n", __FUNCTION__);
+                // terminate transmit
+                g_ese_ctx.next_T1_state = STATE_IDEL;
+            }
+            else
+            {
+                g_ese_ctx.next_T1_state = STATE_IDEL;
+            }
+        }
+        else
+        {
+            g_ese_ctx.p_T1_params->last_rx_sub_Sframe_type = SFRAME_TYPE_INVALID;
+            if ((0x01 == p_pcb_bits->lsb) && (0x00 == p_pcb_bits->bit2))
+            {
+                g_ese_ctx.p_T1_params->last_rx_sub_Rframe_type = RNACK_PARITY_ERROR;
+                status = ESESTATUS_PARITY_ERROR;
+            }
+            else if ((0x00 == p_pcb_bits->lsb) && (0x01 == p_pcb_bits->bit2))
+            {
+                // Other error
+                g_ese_ctx.p_T1_params->last_rx_sub_Rframe_type = RNACK_OTHER_ERROR;
+                status = ESESTATUS_UNKNOWN_ERROR;
+            }
+            else
+            {
+                g_ese_ctx.p_T1_params->last_rx_sub_Rframe_type = RNACK_INVALID_ERROR;
+                status = ESESTATUS_UNKNOWN_ERROR;
+            }
+
+            // LOG_INFO(TRACE_MODULE_SE, "%s: PCB = 0x%02X, recovery_cnt = %d, max_recovery_cnt = %d\r\n", __FUNCTION__, pcb,
+            // g_ese_ctx.p_T1_params->recovery_cnt,
+            // g_ese_ctx.max_recovery_cnt);
+            do_T1_recovery_at_decode_Rframe();
+        }
+    }
+    else if ((0x01 == p_pcb_bits->msb) && (0x01 == p_pcb_bits->bit7))
+    {
+        g_ese_ctx.p_T1_params->last_rx_frame_type = SFRAME;
+        g_ese_ctx.p_T1_params->last_rx_sub_Rframe_type = RNACK_INVALID_ERROR;
+
+        LOG_INFO(TRACE_MODULE_SE, "%s S-Frame Received\r\n", __FUNCTION__);
+        uint8_t subFrameType = pcb & T1_S_BLOCK_SUB_TYPE_MASK;
+        if (RESYNC_RSP != subFrameType)
+        {
+            g_ese_ctx.is_resync_recovery_flag = false;
+        }
+
+        switch (subFrameType)
+        {
+            case RESYNC_RSP:
+            {
+                g_ese_ctx.p_T1_params->last_rx_sub_Sframe_type = RESYNC_RSP;
+                status = do_T1_recovery_at_decode_Sframe();
+                break;
+            }
+
+            case IFS_REQ:
+            {
+                uint16_t IFSC = 0;
+                if (2 == infoLen)
+                {
+                    IFSC = (uint16_t)(((uint16_t)gp_data_rx[dataOffset]) << 8);
+                    IFSC |= gp_data_rx[dataOffset + 1];
+                    LOG_INFO(TRACE_MODULE_SE, "%s IFS_RSP Received, IFSD = %04X\r\n", __FUNCTION__, IFSC);
+                }
+                else if (1 == infoLen)
+                {
+                    IFSC = (uint16_t)gp_data_rx[dataOffset];
+                    LOG_INFO(TRACE_MODULE_SE, "%s IFS_RSP Received, IFSD = %02X\r\n", __FUNCTION__, IFSC);
+                }
+                else
+                {
+                    LOG_INFO(TRACE_MODULE_SE, "%s Invalid IFS_RSP Received\r\n", __FUNCTION__);
+                }
+                g_ese_ctx.max_IFSC = IFSC;
+                g_ese_ctx.next_T1_state = S_IFS_RSP;
+                g_ese_ctx.p_T1_params->tx_frame_type = SFRAME;
+                g_ese_ctx.p_T1_params->tx_sub_Sframe_type = IFS_RSP;
+                break;
+            }
+
+            case IFS_RSP:
+            {
+                g_ese_ctx.p_T1_params->last_rx_sub_Sframe_type = IFS_RSP;
+                uint16_t IFSD = 0;
+                uint8_t offset = get_header_len(false);
+                if (2 == infoLen)
+                {
+                    IFSD = (uint16_t)(((uint16_t)gp_data_rx[offset]) << 8);
+                    IFSD |= gp_data_rx[offset + 1];
+                    LOG_INFO(TRACE_MODULE_SE, "%s IFS_RSP Received, IFSD = %04X\r\n", __FUNCTION__, IFSD);
+                }
+                else if (1 == infoLen)
+                {
+                    IFSD = (uint16_t)gp_data_rx[offset];
+                    LOG_INFO(TRACE_MODULE_SE, "%s IFS_RSP Received, IFSD = %02X\r\n", __FUNCTION__, IFSD);
+                }
+                else
+                {
+                    LOG_INFO(TRACE_MODULE_SE, "%s Invalid IFS_RSP Received\r\n", __FUNCTION__);
+                }
+                if (g_ese_ctx.max_IFSD != IFSD)
+                {
+                    LOG_INFO(TRACE_MODULE_SE, "%s : invalid IFS receive paylod, receivedIFSD = %X, sentIFSD = %X\r\n", __FUNCTION__, IFSD, g_ese_ctx.max_IFSD);
+                }
+                status = do_T1_recovery_at_decode_Sframe();
+                break;
+            }
+
+            case ABORT_REQ:
+            case ABORT_RSP:
+            {
+                // Rule 9: only chaining cmd or rsp will send (receive) ABORT_REQ
+                if (g_ese_ctx.p_T1_params->is_card_chaining || g_ese_ctx.p_T1_params->is_device_chaining)
+                {
+                    t1_recv_data_list_destroy();
+                }
+
+                g_ese_ctx.next_T1_state = STATE_IDEL;
+                break;
+            }
+
+            case WTX_REQ:
+            {
+                if (g_ese_ctx.p_T1_params->wtx_cnt <= g_ese_ctx.max_wtx_cnt)
+                {
+                    g_ese_ctx.p_T1_params->wtx_cnt++;
+
+                    g_ese_ctx.p_T1_params->wtx_info = gp_data_rx[get_header_len(false)];
+                    g_ese_ctx.next_T1_state = S_WTX_RSP;
+                    g_ese_ctx.p_T1_params->tx_frame_type = SFRAME;
+                    g_ese_ctx.p_T1_params->tx_sub_Sframe_type = WTX_RSP;
+                }
+                else
+                {
+                    LOG_INFO(TRACE_MODULE_SE, "%s : failed, WTX_REQ counter larger than maxWtxCnt\r\n", __FUNCTION__);
+                    status = ESESTATUS_FAILED;
+                    g_ese_ctx.next_T1_state = STATE_IDEL;
+                }
+                break;
+            }
+
+            case CIP_RSP:
+            {
+                status = decode_ATR(gp_data_rx, true);
+                reset_for_resync_rsp();
+                g_ese_ctx.next_T1_state = STATE_IDEL;
+                break;
+            }
+
+            case PROP_END_APDU_RSP:
+            {
+                status = ESESTATUS_SUCCESS;
+                g_ese_ctx.next_T1_state = STATE_IDEL;
+                break;
+            }
+
+            case HARD_RESET_RSP:
+            {
+                status = ESESTATUS_SUCCESS;
+                g_ese_ctx.next_T1_state = STATE_IDEL;
+                break;
+            }
+
+            case ATR_RSP:
+            {
+                status = decode_ATR(gp_data_rx, false);
+                g_ese_ctx.next_T1_state = STATE_IDEL;
+                break;
+            }
+
+            default:
+            {
+                status = ESESTATUS_SUCCESS;
+                g_ese_ctx.next_T1_state = STATE_IDEL;
+                LOG_INFO(TRACE_MODULE_SE, "%s : invalid S-block frame type: %X\r\n", __FUNCTION__, subFrameType);
+            }
+        }
+    }
+    else
+    {
+        // LOG_ERROR(TRACE_MODULE_SE, "[RX]Nothing\r\n");
+        LOG_INFO(TRACE_MODULE_SE, "%s Wrong-Frame Received, PCB = %X\r\n", __FUNCTION__, pcb);
+        status = ESESTATUS_INVALID_PCB;
+    }
+
+    return status;
+}
+
+/** Contains the Prologue and (or not) Epilogue field length **/
+uint8_t get_header_len(bool contains_epilogue)
+{
+    uint8_t len = 0;
+    bool is_T1_ext_hdr_len = g_ese_ctx.is_T1_ext_hdr_len;
+    uint8_t checksum = g_atr.checksum;
+    if ((SFRAME == g_ese_ctx.p_T1_params->tx_frame_type) && ((CIP_REQ == g_ese_ctx.p_T1_params->tx_sub_Sframe_type)
+                                                             /*|| (ATR_REQ == g_ese_ctx.p_T1_params->tx_sub_Sframe_type)*/))
+    {
+        is_T1_ext_hdr_len = false;
+        checksum = 0;
+    }
+
+    len = (is_T1_ext_hdr_len ? T1_EXT_HEADER_LEN : T1_HEADER_LEN);
+    if (contains_epilogue)
+    {
+        len += ((checksum == 0) ? T1_LRC_LEN : T1_CRC_LEN);
+    }
+
+    return len;
+}
+
+static uint8_t set_info_len(uint8_t *p_data, uint16_t info_len)
+{
+    uint8_t len_offset = 0;
+    bool is_T1_ext_hdr_len = g_ese_ctx.is_T1_ext_hdr_len;
+    if ((SFRAME == g_ese_ctx.p_T1_params->tx_frame_type) && ((CIP_REQ == g_ese_ctx.p_T1_params->tx_sub_Sframe_type)
+                                                             /*|| (ATR_REQ == g_ese_ctx.p_T1_params->tx_sub_Sframe_type)*/))
+    {
+        is_T1_ext_hdr_len = false;
+    }
+
+    if (is_T1_ext_hdr_len)
+    {
+        p_data[T1_FRAME_LEN_OFFSET] = (uint8_t)(info_len >> 8);
+        p_data[T1_FRAME_LEN_OFFSET2] = (uint8_t)(info_len & 0xFF);
+        len_offset = T1_FRAME_LEN_OFFSET2;
+    }
+    else
+    {
+        p_data[T1_FRAME_LEN_OFFSET] = (uint8_t)(info_len & 0xFF);
+        len_offset = T1_FRAME_LEN_OFFSET;
+    }
+    return len_offset;
+}
+
+static uint16_t get_info_len(uint8_t *p_data)
+{
+    uint16_t info_len = 0;
+    bool is_T1_ext_hdr_len = g_ese_ctx.is_T1_ext_hdr_len;
+    if ((SFRAME == g_ese_ctx.p_T1_params->tx_frame_type) && ((CIP_REQ == g_ese_ctx.p_T1_params->tx_sub_Sframe_type)
+                                                             /*|| (ATR_REQ == g_ese_ctx.p_T1_params->tx_sub_Sframe_type)*/))
+    {
+        is_T1_ext_hdr_len = false;
+    }
+
+    if (is_T1_ext_hdr_len)
+    {
+        info_len = (uint16_t)(((uint16_t)p_data[T1_FRAME_LEN_OFFSET]) << 8);
+        info_len |= p_data[T1_FRAME_LEN_OFFSET2];
+    }
+    else
+    {
+        info_len = p_data[T1_FRAME_LEN_OFFSET];
+    }
+    return info_len;
+}
+
+/******************************************************************************
+ * @Function     decode_ATR
+ * @Param        p_data  - received data and its must be PCB = 0xE4 or 0xE7.
+ *               is_CIP  - true if received data's PCB = 0xE4.
+ * @Return       ESESTATUS_SUCCESS if decode ATR success, else ESESTATUS_INVALID_T1_LEN.
+ ******************************************************************************/
+static ESESTATUS decode_ATR(uint8_t *p_data, bool is_CIP)
+{
+    ESESTATUS status = ESESTATUS_SUCCESS;
+    uint16_t info_len = get_info_len(p_data);
+    uint8_t *p_start = &p_data[T1_FRAME_LEN_OFFSET];
+    if (!is_CIP && g_ese_ctx.is_T1_ext_hdr_len)
+    {
+        // Currently, ATR length is 0x13, exttended frame length high byte should be 0x00
+        p_start++;
+    }
+
+    if (sizeof(atr_info) == (info_len + 1))
+    {
+        memcpy(&g_atr.len, p_start, sizeof(atr_info));
+    }
+    else if (0 == p_data[T1_FRAME_LEN_OFFSET])
+    {
+        // Do nothing, keep befor ATR value.
+        reset_ATR();
+    }
+    else
+    {
+        LOG_INFO(TRACE_MODULE_SE, "%s : invalid ATR response AtrInfoLen = %02X\r\n", __FUNCTION__, (uint8_t)sizeof(atr_info));
+
+        status = ESESTATUS_INVALID_T1_LEN;
+    }
+
+    if (ESESTATUS_SUCCESS == status)
+    {
+        g_ese_ctx.max_IFSC = (uint16_t)(((uint16_t)g_atr.max_IFSC[0]) << 8);
+        g_ese_ctx.max_IFSC |= g_atr.max_IFSC[1];
+        g_ese_ctx.is_T1_ext_hdr_len = (g_atr.capbilities[1] & 0x08) != 0;
+    }
+
+    return status;
+}
+
+/******************************************************************************
+ * @Function     init_Iframe_from_cmd_apdu
+ * @Param        p_cmd_apdu - 7816-4 APDU that shall be sent.
+ *               cmd_len - Length of the apduCmd to be sent.
+ * @Returns      On success return ESESTATUS_SUCCESS or else ESESTATUS error.
+ ******************************************************************************/
+ESESTATUS init_Iframe_from_cmd_apdu(uint8_t *p_cmd_apdu, uint16_t cmd_len)
+{
+    ESESTATUS status = ESESTATUS_SUCCESS;
+
+    g_ese_ctx.p_T1_params = &g_T1_params;
+    g_ese_ctx.p_T1_params->is_device_chaining = (cmd_len > g_ese_ctx.max_IFSC ? true : false);
+    g_ese_ctx.next_T1_state = I_BLK;
+    g_ese_ctx.p_T1_params->tx_frame_type = IFRAME;
+    g_ese_ctx.p_T1_params->p_data_tx = p_cmd_apdu;
+    g_ese_ctx.p_T1_params->tx_len = cmd_len;
+
+    g_ese_ctx.p_T1_params->tx_data_offset = 0;
+    g_ese_ctx.p_T1_params->tx_len_part = 0;
+    g_ese_ctx.p_T1_params->p_data_tx_part = NULL;
+
+    g_ese_ctx.p_T1_params->resync_CIP_req_cnt = 0;
+
+    return status;
+}
+
+/******************************************************************************
+ * @Function     deinit_Iframe_from_cmd_apdu
+ * @Returns      On success return ESESTATUS_SUCCESS or else ESESTATUS error.
+ ******************************************************************************/
+void deinit_Iframe_from_cmd_apdu(void)
+{
+    if (NULL != g_ese_ctx.p_T1_params)
+    {
+        g_ese_ctx.p_T1_params->p_data_tx = NULL;
+
+        if (NULL != g_ese_ctx.p_T1_params->p_data_tx_part)
+        {
+            g_ese_ctx.p_T1_params->p_data_tx_part = NULL;
+        }
+
+        g_ese_ctx.p_T1_params = NULL;
+    }
+}
+
+/******************************************************************************
+ * @Function     free_tx_part_mem
+ ******************************************************************************/
+static void free_tx_part_mem(void)
+{
+    if (NULL != g_ese_ctx.p_T1_params)
+    {
+        if (NULL != g_ese_ctx.p_T1_params->p_data_tx_part)
+        {
+            g_ese_ctx.p_T1_params->p_data_tx_part = NULL;
+        }
+    }
+}
+
+/******************************************************************************
+ * @Function     reset_for_resync_rsp
+ ******************************************************************************/
+static void reset_for_resync_rsp(void)
+{
+    g_ese_ctx.seq_num_card = 0;
+    g_ese_ctx.seq_num_device = 0;
+    g_ese_ctx.p_T1_params->recovery_cnt = 0;
+    g_ese_ctx.p_T1_params->resync_CIP_req_cnt = 0;
+    g_ese_ctx.p_T1_params->wtx_cnt = 0;
+    g_ese_ctx.p_T1_params->tx_data_offset = 0;
+    if (g_ese_ctx.p_T1_params->is_card_chaining)
+    {
+        t1_recv_data_list_destroy();
+    }
+    g_ese_ctx.p_T1_params->is_device_chaining = false;
+    g_ese_ctx.p_T1_params->is_card_chaining = false;
+}
+
+/******************************************************************************
+ * @Function     do_T1_recovery_at_undecode
+ * @Returns      On success return ESESTATUS_SUCCESS, else ESESTATUS_FATAL_ERROR.
+ ******************************************************************************/
+ESESTATUS do_T1_recovery_at_undecode(void)
+{
+    ESESTATUS status = ESESTATUS_SUCCESS;
+    if (g_ese_ctx.p_T1_params->recovery_cnt < g_ese_ctx.max_recovery_cnt)
+    {
+        g_ese_ctx.p_T1_params->recovery_cnt++;
+
+        if ((SFRAME != g_ese_ctx.p_T1_params->tx_frame_type) || (WTX_RSP == g_ese_ctx.p_T1_params->tx_sub_Sframe_type))
+        {
+            g_ese_ctx.next_T1_state = R_PARITY_ERR;
+            g_ese_ctx.p_T1_params->tx_frame_type = RFRAME;
+            g_ese_ctx.p_T1_params->tx_sub_Rframe_type = RNACK_PARITY_ERROR;
+            // Should use the N(S), that is g_ese_ctx.seq_num_device
+        }
+    }
+    else
+    {
+        if (((SFRAME != g_ese_ctx.p_T1_params->tx_frame_type) || (WTX_RSP == g_ese_ctx.p_T1_params->tx_sub_Sframe_type)) && !g_ese_ctx.is_resync_recovery_flag)
+        {
+            g_ese_ctx.is_resync_recovery_flag = true;
+
+            // Do case 4
+            g_ese_ctx.next_T1_state = S_RESYNC_REQ;
+            g_ese_ctx.p_T1_params->tx_frame_type = SFRAME;
+            g_ese_ctx.p_T1_params->tx_sub_Sframe_type = RESYNC_REQ;
+        }
+        else if (g_ese_ctx.is_resync_recovery_flag)
+        {
+            if (g_ese_ctx.p_T1_params->resync_CIP_req_cnt < g_ese_ctx.max_recovery_cnt)
+            {
+                g_ese_ctx.p_T1_params->resync_CIP_req_cnt++;
+
+                // Do case 5
+                g_ese_ctx.next_T1_state = S_CIP_REQ;
+                g_ese_ctx.p_T1_params->tx_frame_type = SFRAME;
+                g_ese_ctx.p_T1_params->tx_sub_Sframe_type = CIP_REQ;
+            }
+            else
+            {
+                status = ESESTATUS_FATAL_ERROR;
+                g_ese_ctx.next_T1_state = STATE_IDEL;
+            }
+        }
+        else
+        {
+            // Chip hard reset if warm reset failed.
+            if ((SFRAME == g_ese_ctx.p_T1_params->tx_frame_type) && (CIP_REQ == g_ese_ctx.p_T1_params->tx_sub_Sframe_type))
+            {
+                LOG_INFO(TRACE_MODULE_SE, "%s: warm reset failed, TODO need chip hard reset to recover\r\n", __FUNCTION__);
+                // need to chip hard reset
+                status = ESESTATUS_FATAL_ERROR;
+                g_ese_ctx.next_T1_state = STATE_IDEL;
+            }
+            else
+            {
+                LOG_INFO(TRACE_MODULE_SE, "%s: S(... REQ) failed, warm reset to recover lastTxFrameType = %d, lastTxSFrameType = %d\r\n", __FUNCTION__,
+                         g_ese_ctx.p_T1_params->tx_frame_type, g_ese_ctx.p_T1_params->tx_sub_Sframe_type);
+
+                g_ese_ctx.next_T1_state = S_CIP_REQ;
+                g_ese_ctx.p_T1_params->tx_frame_type = SFRAME;
+                g_ese_ctx.p_T1_params->tx_sub_Sframe_type = CIP_REQ;
+            }
+        }
+    }
+
+    return status;
+}
+
+/******************************************************************************
+ * @Function     do_T1_recovery_at_decode_Iframe
+ * @Returns      On success return ESESTATUS_SUCCESS, else ESESTATUS_FATAL_ERROR.
+ ******************************************************************************/
+static ESESTATUS do_T1_recovery_at_decode_Iframe(void)
+{
+    ESESTATUS status = ESESTATUS_SUCCESS;
+    T1_frame_types last_rx_frame_type = g_ese_ctx.p_T1_params->last_rx_frame_type;
+    T1_pcb_bits *p_pcb_bits = &g_ese_ctx.p_T1_params->last_rx_pcb_bits;
+
+    if (IFRAME == last_rx_frame_type)
+    {
+        if (g_ese_ctx.p_T1_params->recovery_cnt < g_ese_ctx.max_recovery_cnt)
+        {
+            g_ese_ctx.p_T1_params->recovery_cnt++;
+            if (p_pcb_bits->bit7 != g_ese_ctx.seq_num_card)
+            {
+                g_ese_ctx.next_T1_state = R_OTHER_ERR;
+                g_ese_ctx.p_T1_params->tx_frame_type = RFRAME;
+                g_ese_ctx.p_T1_params->tx_sub_Rframe_type = RNACK_OTHER_ERROR;
+            }
+            else
+            {
+                // Cannot be occured this case
+                LOG_INFO(TRACE_MODULE_SE,
+                         "%s: an I-block received, seqNum exception, terminate transmission. lastTxSeqNum = %d, lastRxExpectedNum = %d, lastRxSeqNum = %d\r\n",
+                         __FUNCTION__, g_ese_ctx.seq_num_device, g_ese_ctx.seq_num_card, p_pcb_bits->bit7);
+                g_ese_ctx.next_T1_state = STATE_IDEL;
+                g_ese_ctx.is_resync_recovery_flag = false;
+                status = ESESTATUS_INVALID_PARAMETER;
+                free_tx_part_mem();
+            }
+        }
+        else
+        {
+            // Should transmit RESYNC_REQ to recover.
+            LOG_INFO(TRACE_MODULE_SE, "%s: lastRecvFrameType = %d, recovery_cnt = %d, max_recovery_cnt = %d RESYNC_REQ should be sent to recover\r\n",
+                     __FUNCTION__, last_rx_frame_type, g_ese_ctx.p_T1_params->recovery_cnt, g_ese_ctx.max_recovery_cnt);
+            // RESYNC_REQ only send once, recovery_cnt should not be reset to zero.
+            g_ese_ctx.is_resync_recovery_flag = true;
+
+            g_ese_ctx.next_T1_state = S_RESYNC_REQ;
+            g_ese_ctx.p_T1_params->tx_frame_type = SFRAME;
+            g_ese_ctx.p_T1_params->tx_sub_Sframe_type = RESYNC_REQ;
+        }
+    }
+    else
+    {
+        status = ESESTATUS_INVALID_PARAMETER;
+        LOG_INFO(TRACE_MODULE_SE,
+                 "%s: should be called when received an invalid IFrame, but non-IFrame received, lastRecvFrameType = %d, recovery_cnt = %d, max_recovery_cnt = "
+                 "%d\r\n",
+                 __FUNCTION__, last_rx_frame_type, g_ese_ctx.p_T1_params->recovery_cnt, g_ese_ctx.max_recovery_cnt);
+        g_ese_ctx.next_T1_state = STATE_IDEL;
+        free_tx_part_mem();
+    }
+
+    return status;
+}
+
+/******************************************************************************
+ * @Function     do_T1_recovery_at_decode_Sframe
+ * @Returns      On success return ESESTATUS_SUCCESS, else ESESTATUS_FATAL_ERROR.
+ ******************************************************************************/
+static ESESTATUS do_T1_recovery_at_decode_Sframe(void)
+{
+    ESESTATUS status = ESESTATUS_SUCCESS;
+    T1_frame_types last_rx_frame_type = g_ese_ctx.p_T1_params->last_rx_frame_type;
+    Sframe_types last_rx_sub_Sframe_type = g_ese_ctx.p_T1_params->last_rx_sub_Sframe_type;
+
+    if ((SFRAME == last_rx_frame_type) && (NULL != g_ese_ctx.p_T1_params->p_data_tx))
+    {
+        // recovery_cnt will be ignored for RESYNC_RSP and IFS_RSP
+        if (RESYNC_RSP == last_rx_sub_Sframe_type)
+        {
+            reset_for_resync_rsp();
+            g_ese_ctx.next_T1_state = I_BLK;
+            g_ese_ctx.p_T1_params->tx_frame_type = IFRAME;
+            g_ese_ctx.p_T1_params->tx_sub_Sframe_type = SFRAME_TYPE_INVALID;
+            g_ese_ctx.p_T1_params->tx_sub_Rframe_type = RNACK_INVALID_ERROR;
+        }
+        else if (IFS_RSP == last_rx_sub_Sframe_type)
+        {
+            if (g_ese_ctx.p_T1_params->is_card_chaining)
+            {
+                g_ese_ctx.next_T1_state = R_ACK;
+                g_ese_ctx.p_T1_params->tx_frame_type = RFRAME;
+                g_ese_ctx.p_T1_params->tx_sub_Sframe_type = SFRAME_TYPE_INVALID;
+                g_ese_ctx.p_T1_params->tx_sub_Rframe_type = RACK;
+            }
+            else if (g_ese_ctx.p_T1_params->is_device_chaining)
+            {
+                g_ese_ctx.next_T1_state = I_BLK;
+                g_ese_ctx.p_T1_params->tx_frame_type = IFRAME;
+                g_ese_ctx.p_T1_params->tx_sub_Sframe_type = SFRAME_TYPE_INVALID;
+                g_ese_ctx.p_T1_params->tx_sub_Rframe_type = RNACK_INVALID_ERROR;
+            }
+            else
+            {
+                LOG_INFO(TRACE_MODULE_SE, "%s: device initiates block I-block is unchaining, terminate transmit when received IFS_RSP\r\n", __FUNCTION__);
+                // terminate transmit
+                g_ese_ctx.next_T1_state = STATE_IDEL;
+            }
+        }
+        else
+        {
+            LOG_INFO(TRACE_MODULE_SE, "%s: device initiates block is an I-block, lastTxFrameType = %d, but device received R-block, cannot be occurred.\r\n",
+                     __FUNCTION__, last_rx_sub_Sframe_type);
+            // terminate transmit
+            g_ese_ctx.next_T1_state = STATE_IDEL;
+        }
+    }
+    else
+    {
+        status = ESESTATUS_INVALID_PARAMETER;
+        LOG_INFO(TRACE_MODULE_SE,
+                 "%s: should be called when received an SFrame, but non-SFrame received, lastRecvFrameType = %d, recovery_cnt = %d, max_recovery_cnt = %d\r\n",
+                 __FUNCTION__, last_rx_frame_type, g_ese_ctx.p_T1_params->recovery_cnt, g_ese_ctx.max_recovery_cnt);
+
+        g_ese_ctx.next_T1_state = STATE_IDEL;
+    }
+    return status;
+}
+
+/******************************************************************************
+ * @Function     do_T1_recovery_at_decode_Rframe
+ * @Returns      On success return ESESTATUS_SUCCESS, else ESESTATUS_FATAL_ERROR.
+ ******************************************************************************/
+static ESESTATUS do_T1_recovery_at_decode_Rframe(void)
+{
+    ESESTATUS status = ESESTATUS_SUCCESS;
+    T1_frame_types last_rx_frame_type = g_ese_ctx.p_T1_params->last_rx_frame_type;
+    Rframe_types last_rx_sub_Rframe_type = g_ese_ctx.p_T1_params->last_rx_sub_Rframe_type;
+
+    if (RFRAME == last_rx_frame_type)
+    {
+        if (g_ese_ctx.p_T1_params->recovery_cnt < g_ese_ctx.max_recovery_cnt)
+        {
+            g_ese_ctx.p_T1_params->recovery_cnt++;
+
+            if ((NULL != g_ese_ctx.p_T1_params->p_data_tx))
+            {
+                // device initiates block is an I-block
+                if (IFRAME == g_ese_ctx.p_T1_params->tx_frame_type)
+                {
+                    if (RACK == last_rx_sub_Rframe_type)
+                    {
+                        g_ese_ctx.next_T1_state = R_OTHER_ERR;
+                        g_ese_ctx.p_T1_params->tx_frame_type = RFRAME;
+                        g_ese_ctx.p_T1_params->tx_sub_Rframe_type = RNACK_OTHER_ERROR;
+                        g_ese_ctx.p_T1_params->tx_sub_Sframe_type = SFRAME_TYPE_INVALID;
+                        LOG_INFO(TRACE_MODULE_SE, "%s: RACK for RNACK_OTHER_ERROR\r\n", __FUNCTION__);
+                    }
+                    else if (RNACK_PARITY_ERROR == last_rx_sub_Rframe_type)
+                    {
+                        g_ese_ctx.next_T1_state = I_BLK;
+                        g_ese_ctx.p_T1_params->tx_frame_type = IFRAME;
+                        // LOG_INFO(TRACE_MODULE_SE, "%s: RNACK_PARITY_ERROR, resend IFRAME\r\n", __FUNCTION__);
+                    }
+                    else if (RNACK_OTHER_ERROR == last_rx_sub_Rframe_type)
+                    {
+                        g_ese_ctx.seq_num_device ^= 0x01;
+                        g_ese_ctx.is_seq_num_dr = true;
+                        g_ese_ctx.next_T1_state = I_BLK;
+                        g_ese_ctx.p_T1_params->tx_frame_type = IFRAME;
+                        // LOG_INFO(TRACE_MODULE_SE, "%s: RNACK_OTHER_ERROR, resend IFRAME\r\n", __FUNCTION__);
+                    }
+                    else
+                    {
+                        g_ese_ctx.next_T1_state = STATE_IDEL;
+                        g_ese_ctx.is_resync_recovery_flag = false;
+                        LOG_INFO(
+                            TRACE_MODULE_SE,
+                            "%s: lastSendIFrame, lastRecvRFrame recovery failed, unkonwn  lastRFrameType = %d, recovery_cnt = %d, max_recovery_cnt = %d\r\n",
+                            __FUNCTION__, g_ese_ctx.p_T1_params->last_rx_sub_Rframe_type, g_ese_ctx.p_T1_params->recovery_cnt, g_ese_ctx.max_recovery_cnt);
+                    }
+                }
+                else if (SFRAME == g_ese_ctx.p_T1_params->tx_frame_type)
+                {
+                    if ((WTX_RSP == g_ese_ctx.p_T1_params->tx_sub_Sframe_type) || (IFS_RSP == g_ese_ctx.p_T1_params->tx_sub_Sframe_type) ||
+                        (ABORT_RSP == g_ese_ctx.p_T1_params->tx_sub_Sframe_type))
+                    {
+                        LOG_INFO(TRACE_MODULE_SE,
+                                 "%s: device initiates block is an I-block, lastTxSubSFrameType = %d, but device received R-block, cannot be occurred.\r\n",
+                                 __FUNCTION__, g_ese_ctx.p_T1_params->tx_sub_Sframe_type);
+                        // terminate transmit
+                        g_ese_ctx.next_T1_state = STATE_IDEL;
+                        g_ese_ctx.is_resync_recovery_flag = false;
+                    }
+                    else
+                    {
+                        LOG_INFO(TRACE_MODULE_SE, "%s: device initiates block is I-block, lastTxSubSFrameType = %d, recovery_cnt = %d\r\n", __FUNCTION__,
+                                 g_ese_ctx.p_T1_params->tx_sub_Sframe_type, g_ese_ctx.p_T1_params->recovery_cnt);
+                    }
+                }
+                else if (RFRAME == g_ese_ctx.p_T1_params->tx_frame_type)
+                {
+                    LOG_INFO(TRACE_MODULE_SE, "%s: device initiates block is I-block, lastTxSubRFrameType = %d, recovery_cnt = %d\r\n", __FUNCTION__,
+                             g_ese_ctx.p_T1_params->tx_sub_Rframe_type, g_ese_ctx.p_T1_params->recovery_cnt);
+                }
+                else
+                {
+                    // unknown R-block type, terminate transmit
+                    g_ese_ctx.next_T1_state = STATE_IDEL;
+                    g_ese_ctx.is_resync_recovery_flag = false;
+                    LOG_INFO(TRACE_MODULE_SE, "%s: lastSend unknown frame type, recovery_cnt = %d\r\n", __FUNCTION__, g_ese_ctx.p_T1_params->recovery_cnt);
+                }
+            }
+            else if (SFRAME == g_ese_ctx.p_T1_params->tx_frame_type)
+            {
+                LOG_INFO(TRACE_MODULE_SE, "%s: device initiates block is S-block, lastTxSubSFrameType = %d, recovery_cnt = %d\r\n", __FUNCTION__,
+                         g_ese_ctx.p_T1_params->tx_sub_Sframe_type, g_ese_ctx.p_T1_params->recovery_cnt);
+            }
+            else
+            {
+                LOG_INFO(TRACE_MODULE_SE, "%s: device initiates block cannot be an R-block, lastTxFrameType = %d\r\n", __FUNCTION__,
+                         g_ese_ctx.p_T1_params->tx_frame_type);
+                g_ese_ctx.next_T1_state = STATE_IDEL;
+                g_ese_ctx.is_resync_recovery_flag = false;
+            }
+        }
+        else
+        {
+            if (!g_ese_ctx.is_resync_recovery_flag && (NULL != g_ese_ctx.p_T1_params->p_data_tx))
+            {
+                g_ese_ctx.is_resync_recovery_flag = true;
+                g_ese_ctx.next_T1_state = S_RESYNC_REQ;
+                g_ese_ctx.p_T1_params->tx_frame_type = SFRAME;
+                g_ese_ctx.p_T1_params->tx_sub_Sframe_type = RESYNC_REQ;
+            }
+            else if (g_ese_ctx.is_resync_recovery_flag && (NULL != g_ese_ctx.p_T1_params->p_data_tx))
+            {
+                free_tx_part_mem();
+                g_ese_ctx.is_resync_recovery_flag = false;
+                g_ese_ctx.next_T1_state = S_CIP_REQ;
+                g_ese_ctx.p_T1_params->tx_frame_type = SFRAME;
+                g_ese_ctx.p_T1_params->tx_sub_Sframe_type = CIP_REQ;
+            }
+            else
+            {
+                status = ESESTATUS_INVALID_PARAMETER;
+                LOG_INFO(TRACE_MODULE_SE,
+                         "%s: should be called when received an RFrame, but non-RFrame received, lastRecvFrameType = %d, recovery_cnt = %d, max_recovery_cnt = "
+                         "%d\r\n",
+                         __FUNCTION__, last_rx_frame_type, g_ese_ctx.p_T1_params->recovery_cnt, g_ese_ctx.max_recovery_cnt);
+                // terminate transmit
+                g_ese_ctx.next_T1_state = STATE_IDEL;
+            }
+        }
+    }
+    return status;
+}
+
+/******************************************************************************
+ * @Function     t1_recv_data_store_in_list
+ * @Param        p_data    - 7816-4 APDU response that shall be stored.
+ *               data_len  - Length of the APDU response.
+ *               total_len - T=1 total length, contains prologue and epilogue.
+ * @Returns      On Success ESESTATUS_SUCCESS else ESESTATUS error.
+ ******************************************************************************/
+static ESESTATUS t1_recv_data_store_in_list(uint8_t *p_data, uint16_t data_len, uint16_t total_len)
+{
+    if ((0 == data_len) || (data_len != (total_len - get_header_len(true))))
+    {
+        // Other error, do nothing
+        return ESESTATUS_INVALID_T1_LEN;
+    }
+
+    // if (g_recv_total_len == 0)
+    // {
+    //     memset(g_all_data_buf, 0, sizeof(g_all_data_buf));
+    // }
+    memcpy(g_all_data_buf + g_recv_total_len, p_data, data_len);
+    g_recv_total_len += data_len;
+    return ESESTATUS_SUCCESS;
+}
+
+/******************************************************************************
+ * @Function     t1_recv_data_list_destroy
+ ******************************************************************************/
+static void t1_recv_data_list_destroy(void)
+{
+    g_recv_total_len = 0;
+}
+
+static void reset_ATR(void)
+{
+    atr_info atr = {
+        .len = 0x13,
+        .vendor_ID = {0x00},
+        .dll_IC = 0x01,
+        .bgt = {0x00, 0x01},
+        .bwt = {0x03, 0xE8},
+        .max_freq = {0x4E, 0x20},
+        .checksum = 0x00,
+        .default_IFSC = 0xFE,
+        .num_channels = 0x01,
+        .max_IFSC = {0x00, 0xFF},
+        .capbilities = {0x00, 0x14}, // Extended frame length feature doesn't support
+    };
+
+    g_atr = atr;
+}
+
+/******************************************************************************
+ * @Function     t1_transmit_receive_apdu
+ * @Param        p_cmd_apdu - 7816-4 APDU that shall be sent.
+ *               cmd_len - Length of the apduCmd to be sent.
+ * @Returns      On success return ESESTATUS_SUCCESS or else ESESTATUS error.
+ ******************************************************************************/
+ESESTATUS t1_transmit_receive_apdu(uint8_t *p_cmd_apdu, uint16_t cmd_len)
+{
+    ESESTATUS status = ESESTATUS_SUCCESS;
+    // LOG_INFO(TRACE_MODULE_SE, "%s: Enter\r\n", __FUNCTION__);
+    status = init_Iframe_from_cmd_apdu(p_cmd_apdu, cmd_len);
+    if (ESESTATUS_SUCCESS != status)
+    {
+        goto cleanup;
+    }
+
+    status = Transmit_receive_process();
+
+    if (ESESTATUS_SUCCESS != status)
+    {
+        LOG_INFO(TRACE_MODULE_SE, "%s: t1_transmit_receive_apdu failed, status = %d\r\n", __FUNCTION__, status);
+    }
+
+cleanup:
+    deinit_Iframe_from_cmd_apdu();
+    return status;
+}
+
+/******************************************************************************
+ * @Function     t1_CIP_req
+ * @Returns      On success return ESESTATUS_SUCCESS or else ESESTATUS error.
+ ******************************************************************************/
+ESESTATUS t1_CIP_req(void)
+{
+    ESESTATUS status = ESESTATUS_SUCCESS;
+    // LOG_INFO(TRACE_MODULE_SE, "t1CIPReq() enter\r\n");
+
+    g_ese_ctx.p_T1_params = &g_T1_params;
+    g_ese_ctx.p_T1_params->is_device_chaining = false;
+    g_ese_ctx.next_T1_state = S_CIP_REQ;
+    g_ese_ctx.p_T1_params->tx_frame_type = SFRAME;
+    g_ese_ctx.p_T1_params->tx_sub_Sframe_type = CIP_REQ;
+
+    status = Transmit_receive_process();
+    g_ese_ctx.p_T1_params = NULL;
+
+    return status;
+}
+
+/******************************************************************************
+ * @Function     t1_ATR_req
+ * @Returns      On success return ESESTATUS_SUCCESS or else ESESTATUS error.
+ ******************************************************************************/
+ESESTATUS t1_ATR_req(void)
+{
+    ESESTATUS status = ESESTATUS_SUCCESS;
+
+    g_ese_ctx.p_T1_params = &g_T1_params;
+    g_ese_ctx.p_T1_params->is_device_chaining = false;
+    g_ese_ctx.next_T1_state = S_ATR_REQ;
+    g_ese_ctx.p_T1_params->tx_frame_type = SFRAME;
+    g_ese_ctx.p_T1_params->tx_sub_Sframe_type = ATR_REQ;
+
+    status = Transmit_receive_process();
+    g_ese_ctx.p_T1_params = NULL;
+
+    return status;
+}
+
+/******************************************************************************
+ * @Function     t1_IFSD_req
+ * @Returns      On success return ESESTATUS_SUCCESS or else ESESTATUS error.
+ ******************************************************************************/
+ESESTATUS t1_IFSD_req(void)
+{
+    ESESTATUS status = ESESTATUS_SUCCESS;
+
+    g_ese_ctx.p_T1_params = &g_T1_params;
+    g_ese_ctx.p_T1_params->is_device_chaining = false;
+    g_ese_ctx.next_T1_state = S_IFS_REQ;
+    g_ese_ctx.p_T1_params->tx_frame_type = SFRAME;
+    g_ese_ctx.p_T1_params->tx_sub_Sframe_type = IFS_REQ;
+
+    status = Transmit_receive_process();
+    g_ese_ctx.p_T1_params = NULL;
+
+    return status;
+}
+
+/******************************************************************************
+ * @Function     t1_prop_end_apdu_req
+ * @Returns      On success return ESESTATUS_SUCCESS or else ESESTATUS error.
+ ******************************************************************************/
+ESESTATUS t1_prop_end_apdu_req(void)
+{
+    ESESTATUS status = ESESTATUS_SUCCESS;
+
+    g_ese_ctx.p_T1_params = &g_T1_params;
+    g_ese_ctx.p_T1_params->is_device_chaining = false;
+    g_ese_ctx.next_T1_state = S_PROP_END_APDU_REQ;
+    g_ese_ctx.p_T1_params->tx_frame_type = SFRAME;
+    g_ese_ctx.p_T1_params->tx_sub_Sframe_type = PROP_END_APDU_REQ;
+
+    status = Transmit_receive_process();
+    g_ese_ctx.p_T1_params = NULL;
+
+    return status;
+}
+
+/******************************************************************************
+ * Function     t1_receive_data_and_get
+ * @Param        pp_Data - a pointer address to the received data.
+ *               data_len - a pointer to the length of the received data.
+ * Returns       On success return ESESTATUS_SUCCESS or else ESESTATUS error.
+ ******************************************************************************/
+ESESTATUS t1_receive_data_and_get(uint8_t **pp_Data, uint16_t *data_len)
+{
+    *data_len = (uint16_t)g_recv_total_len;
+    *pp_Data = g_all_data_buf;
+    return ESESTATUS_SUCCESS;
+}

--
Gitblit v1.9.3