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