对比新文件 |
| | |
| | | |
| | | #include <errno.h> |
| | | #include <string.h> |
| | | #include <stdlib.h> |
| | | |
| | | #include "phdriver.h" |
| | | #include "se_api.h" |
| | | #include "mk_misc.h" |
| | | #include "mk_trace.h" |
| | | |
| | | /****************************************************************************** |
| | | * @Function t1_read_no_wait |
| | | * @Param p_data_len - point to data length. |
| | | * @Returns On success return ESESTATUS_SUCCESS, else ESESTATUS_xxx. |
| | | ******************************************************************************/ |
| | | static ESESTATUS t1_read_no_wait(uint16_t *p_data_len) |
| | | { |
| | | ESESTATUS status = ESESTATUS_SUCCESS; |
| | | int ret = -1; |
| | | 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)); |
| | | |
| | | // sys_timer_delay_ms(1); // 10 |
| | | |
| | | ret = phdriver_read(gp_data_rx, 1); |
| | | |
| | | if ((ret < 0) || (NAD_C2DT != gp_data_rx[0])) |
| | | { |
| | | return ESESTATUS_NO_DATA_TO_RECEIVE; |
| | | } |
| | | else |
| | | { |
| | | ret = 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]; |
| | | |
| | | // CRC has 2 bytes, so the second read len is INF len + 1 |
| | | if (CRC == g_atr.checksum) |
| | | { |
| | | num_bytes_to_read += 1; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | // LRC has 1 bytes, so the second read len is INF len |
| | | num_bytes_to_read = gp_data_rx[T1_FRAME_LEN_OFFSET]; |
| | | } |
| | | read_index = hdrLen; |
| | | total_cnt += hdrLen; |
| | | } |
| | | |
| | | #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 |
| | | { |
| | | status = ESESTATUS_FAILED; |
| | | } |
| | | } |
| | | 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; |
| | | } |
| | | else |
| | | { |
| | | total_cnt += num_bytes_to_read; |
| | | } |
| | | } |
| | | } |
| | | #endif |
| | | |
| | | if (ESESTATUS_SUCCESS != status) |
| | | { |
| | | *p_data_len = 0; |
| | | } |
| | | else |
| | | { |
| | | *p_data_len = total_cnt; |
| | | } |
| | | |
| | | return status; |
| | | } |
| | | |
| | | /****************************************************************************** |
| | | * @Function response_no_wait_process |
| | | * @Returns On success return ESESTATUS_SUCCESS or else ESESTATUS error. |
| | | ******************************************************************************/ |
| | | static ESESTATUS response_no_wait_process(void) |
| | | { |
| | | ESESTATUS status = ESESTATUS_SUCCESS; |
| | | uint16_t data_len = 0; |
| | | |
| | | status = t1_read_no_wait(&data_len); |
| | | if (status == ESESTATUS_NO_DATA_TO_RECEIVE) |
| | | { |
| | | return ESESTATUS_NO_DATA_TO_RECEIVE; |
| | | } |
| | | |
| | | 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 |
| | | { |
| | | status = do_T1_recovery_at_undecode(); |
| | | } |
| | | } |
| | | else if (ESESTATUS_FATAL_ERROR == status) |
| | | { |
| | | g_ese_ctx.next_T1_state = STATE_IDEL; |
| | | } |
| | | else |
| | | { |
| | | status = do_T1_recovery_at_undecode(); |
| | | } |
| | | |
| | | return status; |
| | | } |
| | | |
| | | /****************************************************************************** |
| | | * @Function transmit_only_process |
| | | * @Returns On success return ESESTATUS_SUCCESS or else ESESTATUS error. |
| | | ******************************************************************************/ |
| | | static ESESTATUS transmit_only_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(); // just send |
| | | 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) |
| | | { |
| | | if ((g_ese_ctx.p_T1_params->is_device_chaining == true) && (g_ese_ctx.next_T1_state != STATE_IDEL)) |
| | | { |
| | | #ifdef DBG_LEVEL_STACK |
| | | gDumpStackFlag = false; |
| | | #endif |
| | | g_ese_ctx.p_T1_params->blk_retry_cnt = 0; |
| | | status = response_process(); |
| | | // status = response_no_wait_process(); |
| | | } |
| | | else |
| | | { |
| | | break; |
| | | } |
| | | } |
| | | 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 receive_only_process |
| | | * @Returns On success return ESESTATUS_SUCCESS or else ESESTATUS error. |
| | | ******************************************************************************/ |
| | | static ESESTATUS receive_only_process(void) |
| | | { |
| | | ESESTATUS status = ESESTATUS_SUCCESS; |
| | | #ifdef DBG_LEVEL_STACK |
| | | gDumpStackFlag = false; |
| | | #endif |
| | | g_ese_ctx.p_T1_params->blk_retry_cnt = 0; |
| | | status = response_no_wait_process(); |
| | | |
| | | while ((status != ESESTATUS_NO_DATA_TO_RECEIVE) && (g_ese_ctx.next_T1_state != STATE_IDEL)) |
| | | { |
| | | if (g_ese_ctx.p_T1_params->last_rx_frame_type == IFRAME) |
| | | { |
| | | if ((g_ese_ctx.p_T1_params->is_card_chaining == true) && (g_ese_ctx.next_T1_state == R_ACK)) |
| | | { |
| | | status = Transmit_receive_process(); |
| | | // status = transmit_only_process(); |
| | | } |
| | | break; |
| | | } |
| | | else // if (g_ese_ctx.p_T1_params->last_rx_frame_type == RFRAME) |
| | | { |
| | | transmit_only_process(); |
| | | status = response_no_wait_process(); |
| | | } |
| | | } |
| | | |
| | | return status; |
| | | } |
| | | |
| | | /****************************************************************************** |
| | | * @Function t1_transmit_only_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_only_apdu(uint8_t *p_cmd_apdu, uint16_t cmd_len) |
| | | { |
| | | ESESTATUS status = ESESTATUS_SUCCESS; |
| | | status = init_Iframe_from_cmd_apdu(p_cmd_apdu, cmd_len); |
| | | if (ESESTATUS_SUCCESS != status) |
| | | { |
| | | goto cleanup; |
| | | } |
| | | |
| | | status = transmit_only_process(); |
| | | |
| | | if (ESESTATUS_SUCCESS != status) |
| | | { |
| | | LOG_INFO(TRACE_MODULE_SE, "%s: failed, status = %d\r\n", __FUNCTION__, status); |
| | | } |
| | | else |
| | | { |
| | | // if success,after receiving the resp,execu deinit_Iframe_from_cmd_apdu |
| | | return status; |
| | | } |
| | | |
| | | cleanup: |
| | | deinit_Iframe_from_cmd_apdu(); |
| | | return status; |
| | | } |
| | | |
| | | /****************************************************************************** |
| | | * @Function t1_receive_only_apdu |
| | | * @Returns On success return ESESTATUS_SUCCESS or else ESESTATUS error. |
| | | ******************************************************************************/ |
| | | ESESTATUS t1_receive_only_apdu(void) |
| | | { |
| | | ESESTATUS status = ESESTATUS_SUCCESS; |
| | | |
| | | status = receive_only_process(); // response_no_wait_process(); |
| | | |
| | | if (ESESTATUS_NO_DATA_TO_RECEIVE == status) |
| | | { |
| | | return ESESTATUS_NO_DATA_TO_RECEIVE; |
| | | } |
| | | |
| | | if (ESESTATUS_SUCCESS != status) |
| | | { |
| | | LOG_INFO(TRACE_MODULE_SE, "%s: failed, status = %d\r\n", __FUNCTION__, status); |
| | | } |
| | | |
| | | deinit_Iframe_from_cmd_apdu(); |
| | | return status; |
| | | } |