chen
2024-11-08 cc432b761c884a0bd8e9d83db0a4e26109fc08b1
keil/include/components/se/src/t1_split.c
对比新文件
@@ -0,0 +1,319 @@
#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;
}