554 lines
16 KiB
C
554 lines
16 KiB
C
/*
|
|
* Copyright (c) @CompanyNameMagicTag 2021-2021. All rights reserved.
|
|
* Description: transmit data
|
|
* This file should be changed only infrequently and with great care.
|
|
*/
|
|
#include "transmit_item.h"
|
|
#include "securec.h"
|
|
#include "transmit_st.h"
|
|
#include "transmit_send_recv_pkt.h"
|
|
#include "soc_osal.h"
|
|
#include "zdiag_adapt_layer.h"
|
|
#include "transmit_src.h"
|
|
#include "transmit_dst.h"
|
|
#include "dfx_adapt_layer.h"
|
|
#include "errcode.h"
|
|
#if CONFIG_DFX_SUPPORT_FILE_SYSTEM == DFX_YES
|
|
#include "dfx_file_operation.h"
|
|
#endif
|
|
#include "transmit_debug.h"
|
|
#include "transmit_cmd_id.h"
|
|
#include "transmit.h"
|
|
#include "diag_msg.h"
|
|
#include "diag_dfx.h"
|
|
|
|
#define TRANSMIT_ITEM_CNT 3
|
|
#define TRANSMIT_TIMER_PERIOD 1000
|
|
#define TRANSMIT_ITEM_BUF_LEN 0x600
|
|
#define TRANSMIT_MSG_PROC_MAX 10
|
|
|
|
typedef struct {
|
|
void *is_busy;
|
|
uint32_t transmit_id;
|
|
uint8_t used_cnt;
|
|
uint8_t period_cnt;
|
|
uint32_t buf_used : 1;
|
|
uint32_t pkt_size;
|
|
uint8_t *pkt_buf;
|
|
uint8_t timer_cnt;
|
|
osal_timer timer;
|
|
transmit_item_t item[TRANSMIT_ITEM_CNT];
|
|
} transmit_ctrl_t;
|
|
|
|
transmit_ctrl_t g_transmit_ctrl;
|
|
static transmit_msg_proc_t g_transmit_msg_proc[TRANSMIT_MSG_PROC_MAX] = {0};
|
|
|
|
STATIC void transmit_timer_stop(void);
|
|
errcode_t transmit_send_invalid_id(uint32_t transmit_id, diag_option_t *option, bool down_machine)
|
|
{
|
|
errcode_t ret;
|
|
uint32_t pkt_size = (uint32_t)sizeof(transmit_pkt_tlv_t) + (uint32_t)sizeof(transmit_state_notify_pkt_t);
|
|
transmit_pkt_tlv_t *tlv = transmit_item_get_pkt_buf(NULL, pkt_size);
|
|
if (tlv == NULL) {
|
|
return ERRCODE_MALLOC;
|
|
}
|
|
tlv->type = transmit_build_tlv_type(1, 1);
|
|
tlv->len = transmit_build_tlv_len(sizeof(transmit_state_notify_pkt_t));
|
|
transmit_state_notify_pkt_t *pkt = (transmit_state_notify_pkt_t *)tlv->data;
|
|
|
|
pkt->transmit_id = transmit_id;
|
|
pkt->state_code = TRANSMIT_STATE_NOTIFY_INVALID_ID;
|
|
pkt->len = 0;
|
|
ret = transmit_send_packet(DIAG_CMD_ID_TRANSMIT_NOTIFY, (uint8_t *)tlv, pkt_size, option, down_machine);
|
|
transmit_item_free_pkt_buf(NULL, tlv);
|
|
return ret;
|
|
}
|
|
|
|
errcode_t transmit_send_finish_pkt(uint32_t transmit_id, diag_option_t *option, bool down_machine)
|
|
{
|
|
errcode_t ret;
|
|
uint32_t pkt_size = (uint32_t)sizeof(transmit_pkt_tlv_t) + (uint32_t)sizeof(transmit_state_notify_pkt_t);
|
|
transmit_pkt_tlv_t *tlv = transmit_item_get_pkt_buf(NULL, pkt_size);
|
|
if (tlv == NULL) {
|
|
return ERRCODE_MALLOC;
|
|
}
|
|
tlv->type = transmit_build_tlv_type(1, 1);
|
|
tlv->len = transmit_build_tlv_len(sizeof(transmit_state_notify_pkt_t));
|
|
transmit_state_notify_pkt_t *pkt = (transmit_state_notify_pkt_t *)tlv->data;
|
|
|
|
pkt->transmit_id = transmit_id;
|
|
pkt->state_code = TRANSMIT_STATE_NOTIFY_FINISH;
|
|
pkt->len = 0;
|
|
ret = transmit_send_packet(DIAG_CMD_ID_TRANSMIT_NOTIFY, (uint8_t *)tlv, pkt_size, option, down_machine);
|
|
transmit_item_free_pkt_buf(NULL, tlv);
|
|
return ret;
|
|
}
|
|
|
|
errcode_t transmit_send_failed_pkt(uint32_t transmit_id, diag_option_t *option, bool down_machine)
|
|
{
|
|
errcode_t ret;
|
|
uint32_t pkt_size = (uint32_t)sizeof(transmit_pkt_tlv_t) + (uint32_t)sizeof(transmit_state_notify_pkt_t);
|
|
transmit_pkt_tlv_t *tlv = transmit_item_get_pkt_buf(NULL, pkt_size);
|
|
if (tlv == NULL) {
|
|
return ERRCODE_MALLOC;
|
|
}
|
|
tlv->type = transmit_build_tlv_type(1, 1);
|
|
tlv->len = transmit_build_tlv_len(sizeof(transmit_state_notify_pkt_t));
|
|
transmit_state_notify_pkt_t *pkt = (transmit_state_notify_pkt_t *)tlv->data;
|
|
|
|
pkt->transmit_id = transmit_id;
|
|
pkt->state_code = TRANSMIT_STATE_NOTIFY_SAVE_FAILED_ID;
|
|
pkt->len = 0;
|
|
ret = transmit_send_packet(DIAG_CMD_ID_TRANSMIT_NOTIFY, (uint8_t *)tlv, pkt_size, option, down_machine);
|
|
transmit_item_free_pkt_buf(NULL, tlv);
|
|
return ret;
|
|
}
|
|
|
|
void transmit_item_process_notify_frame(transmit_state_notify_pkt_t *pkt, diag_option_t *option,
|
|
bool from_upper_machine)
|
|
{
|
|
dfx_assert(pkt);
|
|
transmit_item_t *item = transmit_item_match_id(pkt->transmit_id);
|
|
if (item == NULL) {
|
|
if (pkt->state_code != TRANSMIT_STATE_NOTIFY_INVALID_ID) {
|
|
dfx_log_err("[ERR]notify_frame match id failed!, id = 0x%x\r\n", pkt->transmit_id);
|
|
transmit_send_invalid_id(pkt->transmit_id, option, from_upper_machine);
|
|
}
|
|
return;
|
|
}
|
|
transmit_result_hook result_hook = (transmit_result_hook)item->result_hook;
|
|
|
|
switch (pkt->state_code) {
|
|
case TRANSMIT_STATE_NOTIFY_INVALID_ID:
|
|
transmit_item_finish(item, TRANSMIT_DISABLE_RECV_INVALID_ID);
|
|
break;
|
|
case TRANSMIT_STATE_NOTIFY_FINISH:
|
|
case TRANSMIT_STATE_NOTIFY_FINISH_2:
|
|
transmit_item_finish(item, TRANSMIT_DISABLE_RECV_FINISH);
|
|
if (item->remote_type == TRANSMIT_TYPE_READ_FILE || item->remote_type == TRANSMIT_TYPE_DUMP) {
|
|
transmit_send_finish_pkt(item->transmit_id, &item->option, item->down_machine);
|
|
}
|
|
if (result_hook != NULL && item->local_start == true) {
|
|
result_hook(true, (uintptr_t)NULL);
|
|
}
|
|
break;
|
|
case TRANSMIT_STATE_NOTIFY_DUPLICATE_ID:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
transmit_item_t *transmit_item_match_id(uint32_t transmit_id)
|
|
{
|
|
transmit_item_t *item = NULL;
|
|
for (int i = 0; i < TRANSMIT_ITEM_CNT; i++) {
|
|
item = &g_transmit_ctrl.item[i];
|
|
if ((item->used != 0) && (item->transmit_id == transmit_id) && (transmit_id != 0)) {
|
|
return item;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
transmit_item_t *transmit_item_match_type_and_dst(transmit_type_t transmit_type, diag_addr dst)
|
|
{
|
|
transmit_item_t *item = NULL;
|
|
for (int i = 0; i < TRANSMIT_ITEM_CNT; i++) {
|
|
item = &g_transmit_ctrl.item[i];
|
|
if ((item->used != 0) && (item->remote_type == transmit_type) && (item->option.peer_addr == dst)) {
|
|
return item;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
transmit_item_t *transmit_item_init(uint32_t transmit_id)
|
|
{
|
|
transmit_item_t *item = NULL;
|
|
for (int i = 0; i < TRANSMIT_ITEM_CNT; i++) {
|
|
item = &g_transmit_ctrl.item[i];
|
|
if (item->used == true) {
|
|
continue;
|
|
}
|
|
memset_s(item, sizeof(transmit_item_t), 0x0, sizeof(transmit_item_t));
|
|
|
|
if (transmit_id == 0) {
|
|
item->transmit_id = g_transmit_ctrl.transmit_id++;
|
|
} else {
|
|
item->transmit_id = transmit_id;
|
|
}
|
|
|
|
item->used = true;
|
|
if (item->pm_veto == 0) {
|
|
(void)dfx_pm_add_sleep_veto();
|
|
item->pm_veto = 1;
|
|
}
|
|
return item;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void transmit_item_init_permanent(transmit_item_t *item, bool permanent)
|
|
{
|
|
dfx_assert(item);
|
|
item->permanent = permanent;
|
|
}
|
|
|
|
void transmit_item_init_local_start(transmit_item_t *item, bool local_start)
|
|
{
|
|
dfx_assert(item);
|
|
item->local_start = local_start;
|
|
}
|
|
|
|
void transmit_item_init_local_src(transmit_item_t *item, bool local_src)
|
|
{
|
|
dfx_assert(item);
|
|
item->local_src = local_src;
|
|
}
|
|
|
|
void transmit_item_init_remote_type(transmit_item_t *item, transmit_type_t remote_type)
|
|
{
|
|
dfx_assert(item);
|
|
item->remote_type = remote_type;
|
|
}
|
|
|
|
void transmit_item_init_local_type(transmit_item_t *item, transmit_local_type_t local_type)
|
|
{
|
|
dfx_assert(item);
|
|
item->local_type = local_type;
|
|
}
|
|
|
|
void transmit_item_init_write_handler(transmit_item_t *item, transmit_write_hook handler, uintptr_t usr_data)
|
|
{
|
|
dfx_assert(item);
|
|
item->write_read = (uintptr_t)handler;
|
|
item->usr_wr_data = usr_data;
|
|
}
|
|
|
|
void transmit_item_init_read_handler(transmit_item_t *item, transmit_read_hook handler, uintptr_t usr_data)
|
|
{
|
|
dfx_assert(item);
|
|
item->write_read = (uintptr_t)handler;
|
|
item->usr_wr_data = usr_data;
|
|
}
|
|
|
|
void transmit_item_init_result_handler(transmit_item_t *item, transmit_result_hook handler, uintptr_t usr_data)
|
|
{
|
|
dfx_assert(item);
|
|
unused(usr_data);
|
|
item->result_hook = (uintptr_t)handler;
|
|
}
|
|
|
|
void transmit_item_init_local_bus_addr(transmit_item_t *item, uint32_t bus_addr)
|
|
{
|
|
dfx_assert(item);
|
|
item->bus_addr = bus_addr;
|
|
}
|
|
|
|
void transmit_item_init_file_name(transmit_item_t *item, const char *file_name, uint16_t name_len)
|
|
{
|
|
dfx_assert(file_name);
|
|
dfx_assert(item);
|
|
uint32_t name_size = name_len + 1;
|
|
item->file_name = dfx_malloc(0, name_size);
|
|
if (item->file_name == NULL) {
|
|
item->init_fail = true;
|
|
return;
|
|
}
|
|
memset_s(item->file_name, name_size, 0, name_size);
|
|
memcpy_s(item->file_name, name_len, file_name, name_len);
|
|
}
|
|
|
|
void transmit_item_init_option(transmit_item_t *item, diag_option_t *option)
|
|
{
|
|
dfx_assert(item);
|
|
item->option = *option;
|
|
}
|
|
|
|
void transmit_item_init_down_machine(transmit_item_t *item, bool down_machine)
|
|
{
|
|
dfx_assert(item);
|
|
item->down_machine = down_machine;
|
|
}
|
|
|
|
void transmit_item_init_received_size(transmit_item_t *item, uint32_t offset)
|
|
{
|
|
dfx_assert(item);
|
|
item->received_size = offset;
|
|
}
|
|
|
|
void transmit_item_init_total_size(transmit_item_t *item, uint32_t total_size)
|
|
{
|
|
dfx_assert(item);
|
|
item->total_size = total_size;
|
|
}
|
|
|
|
void transmit_item_init_re_trans(transmit_item_t *item, bool re_trans)
|
|
{
|
|
dfx_assert(item);
|
|
item->re_trans = re_trans;
|
|
}
|
|
|
|
void transmit_item_init_data_block_size(transmit_item_t *item, uint16_t data_block_size)
|
|
{
|
|
dfx_assert(item);
|
|
item->data_block_size = data_block_size;
|
|
}
|
|
|
|
void transmit_item_init_data_block_number(transmit_item_t *item, uint16_t data_block_number)
|
|
{
|
|
dfx_assert(item);
|
|
item->data_block_number = data_block_number;
|
|
}
|
|
|
|
bool transmit_item_init_is_success(const transmit_item_t *item)
|
|
{
|
|
dfx_assert(item);
|
|
if (item->init_fail != 0) {
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
void transmit_item_deinit(transmit_item_t *item)
|
|
{
|
|
dfx_assert(item);
|
|
if (item->file_name) {
|
|
dfx_free(0, item->file_name);
|
|
item->file_name = NULL;
|
|
}
|
|
|
|
if (item->pm_veto == 1) {
|
|
(void)dfx_pm_remove_sleep_veto();
|
|
item->pm_veto = 0;
|
|
}
|
|
|
|
item->used = false;
|
|
}
|
|
|
|
void transmit_item_disable(transmit_item_t *item, transmit_disable_reason_t reason)
|
|
{
|
|
dfx_assert(item);
|
|
if (item->permanent == false) {
|
|
g_transmit_ctrl.timer_cnt--;
|
|
if (g_transmit_ctrl.timer_cnt == 0) {
|
|
transmit_timer_stop();
|
|
}
|
|
}
|
|
unused(reason);
|
|
item->enable = false;
|
|
}
|
|
|
|
void transmit_item_enable(transmit_item_t *item)
|
|
{
|
|
dfx_assert(item);
|
|
uint32_t cur_time = dfx_get_cur_second();
|
|
|
|
if ((item->local_start) != 0) {
|
|
item->step = TRANSMIT_STEP_START;
|
|
transmit_src_item_send_start_frame(item, cur_time);
|
|
} else {
|
|
item->step = TRANSMIT_STEP_TRANSMIT;
|
|
}
|
|
|
|
if (item->permanent == false) {
|
|
item->last_rcv_pkt_time = cur_time;
|
|
item->last_send_pkt_time = cur_time;
|
|
item->expiration = cur_time + TRANSMIT_RETRY_TIME;
|
|
|
|
g_transmit_ctrl.timer_cnt++;
|
|
if (g_transmit_ctrl.timer_cnt == 1) {
|
|
transmit_timer_start();
|
|
}
|
|
}
|
|
item->enable = true;
|
|
}
|
|
|
|
void transmit_item_finish(transmit_item_t *item, transmit_disable_reason_t reason)
|
|
{
|
|
dfx_assert(item);
|
|
transmit_item_disable(item, reason);
|
|
if (item->file_fd != 0) {
|
|
#if CONFIG_DFX_SUPPORT_FILE_SYSTEM == DFX_YES
|
|
dfx_file_fsync(item->file_fd);
|
|
dfx_file_close(item->file_fd);
|
|
#endif
|
|
item->file_fd = 0;
|
|
}
|
|
|
|
transmit_item_deinit(item);
|
|
}
|
|
|
|
void* transmit_item_get_pkt_buf(const transmit_item_t *item, uint32_t buf_size)
|
|
{
|
|
dfx_assert(item);
|
|
unused(item);
|
|
|
|
if (g_transmit_ctrl.pkt_size == 0) {
|
|
g_transmit_ctrl.pkt_size = TRANSMIT_ITEM_BUF_LEN;
|
|
g_transmit_ctrl.pkt_buf = dfx_malloc(0, TRANSMIT_ITEM_BUF_LEN);
|
|
}
|
|
|
|
if ((buf_size < g_transmit_ctrl.pkt_size) && (g_transmit_ctrl.buf_used == 0)) {
|
|
g_transmit_ctrl.buf_used = true;
|
|
return g_transmit_ctrl.pkt_buf;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void transmit_item_free_pkt_buf(const transmit_item_t *item, const void *buf)
|
|
{
|
|
g_transmit_ctrl.buf_used = false;
|
|
|
|
unused(item);
|
|
unused(buf);
|
|
}
|
|
|
|
typedef struct {
|
|
osal_timer g_transmit_timer;
|
|
bool start;
|
|
} transmit_timer_t;
|
|
|
|
transmit_timer_t g_transmit_timer;
|
|
|
|
|
|
STATIC void transmit_item_time_out(transmit_item_t *item, uint32_t cur_time)
|
|
{
|
|
dfx_assert(item);
|
|
if ((item->local_src) != 0) {
|
|
transmit_src_item_process_timer(item, cur_time);
|
|
} else {
|
|
transmit_dst_item_process_timer(item, cur_time);
|
|
}
|
|
}
|
|
STATIC void transmit_period_msg_proc(void)
|
|
{
|
|
transmit_item_t *item = NULL;
|
|
uint32_t cur_sec = dfx_get_cur_second();
|
|
for (int i = 0; i < TRANSMIT_ITEM_CNT; i++) {
|
|
item = &g_transmit_ctrl.item[i];
|
|
if ((item->enable != 0) && (item->permanent == false) && (cur_sec > item->expiration)) {
|
|
transmit_item_time_out(item, cur_sec);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
errcode_t transmit_msg_proc_hook_register(uint32_t msg_id_start, uint32_t msg_id_end, transmit_register_hook hook)
|
|
{
|
|
if (msg_id_start >= msg_id_end || hook == NULL) {
|
|
return ERRCODE_FAIL;
|
|
}
|
|
transmit_msg_proc_t *msg_proc;
|
|
for (int i = 0; i < TRANSMIT_MSG_PROC_MAX; i++) {
|
|
msg_proc = &g_transmit_msg_proc[i];
|
|
if (!((msg_id_end < msg_proc->id_start) || (msg_id_start > msg_proc->id_end))) {
|
|
// 有msg_id范围重叠
|
|
return ERRCODE_FAIL;
|
|
}
|
|
if (msg_proc->used != 1) {
|
|
msg_proc->id_start = msg_id_start;
|
|
msg_proc->id_end = msg_id_end;
|
|
msg_proc->used = 1;
|
|
msg_proc->hook = (uintptr_t)hook;
|
|
return ERRCODE_SUCC;
|
|
}
|
|
}
|
|
return ERRCODE_FAIL;
|
|
}
|
|
|
|
errcode_t transmit_msg_proc_hook_unregister(transmit_register_hook hook)
|
|
{
|
|
transmit_msg_proc_t *msg_proc;
|
|
for (int i = 0; i < TRANSMIT_MSG_PROC_MAX; i++) {
|
|
msg_proc = &g_transmit_msg_proc[i];
|
|
if ((msg_proc->used == 1) && (((transmit_register_hook)msg_proc->hook) == hook)) {
|
|
msg_proc->id_start = 0;
|
|
msg_proc->id_end = 0;
|
|
msg_proc->used = 0;
|
|
msg_proc->hook = (uintptr_t)NULL;
|
|
return ERRCODE_SUCC;
|
|
}
|
|
}
|
|
return ERRCODE_FAIL;
|
|
}
|
|
|
|
static errcode_t transmit_run_hook(uint32_t msg_id, const uint8_t *msg, uint32_t msg_len)
|
|
{
|
|
transmit_msg_proc_t *msg_proc;
|
|
for (int i = 0; i < TRANSMIT_MSG_PROC_MAX; i++) {
|
|
msg_proc = &g_transmit_msg_proc[i];
|
|
if ((msg_proc->used == 1) && (msg_id > msg_proc->id_start) &&
|
|
(msg_id < msg_proc->id_end) && (((transmit_register_hook)msg_proc->hook) != NULL)) {
|
|
((transmit_register_hook)msg_proc->hook)(msg_id, msg, msg_len);
|
|
return ERRCODE_SUCC;
|
|
}
|
|
}
|
|
return ERRCODE_FAIL;
|
|
}
|
|
|
|
errcode_t transmit_msg_proc(uint32_t msg_id, const uint8_t *msg, uint32_t msg_len)
|
|
{
|
|
diag_dfx_transmit_rev_msg();
|
|
|
|
if (msg_id > DFX_MSG_ID_RESERVE_MAX) {
|
|
return transmit_run_hook(msg_id, msg, msg_len);
|
|
}
|
|
|
|
switch (msg_id) {
|
|
case DFX_MSG_ID_DIAG_PKT:
|
|
diag_msg_proc((uint16_t)msg_id, (uint8_t *)msg, msg_len);
|
|
break;
|
|
case DFX_MSG_ID_TRANSMIT_FILE:
|
|
transmit_period_msg_proc();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return ERRCODE_SUCC;
|
|
}
|
|
|
|
STATIC void transmit_timer_handler(unsigned long data)
|
|
{
|
|
osal_timer *timer = &g_transmit_ctrl.timer;
|
|
|
|
transmit_msg_write(DFX_MSG_ID_TRANSMIT_FILE, (uint8_t *)(uintptr_t)data, sizeof(data), false);
|
|
|
|
if ((g_transmit_ctrl.timer_cnt) != 0) {
|
|
osal_timer_start(timer);
|
|
}
|
|
}
|
|
|
|
void transmit_timer_start(void)
|
|
{
|
|
osal_timer *timer = &g_transmit_ctrl.timer;
|
|
osal_timer_start(timer);
|
|
}
|
|
|
|
STATIC void transmit_timer_stop(void) {}
|
|
STATIC errcode_t transmit_timer_init(void)
|
|
{
|
|
osal_timer *timer = &g_transmit_ctrl.timer;
|
|
timer->handler = transmit_timer_handler;
|
|
timer->data = 0;
|
|
timer->interval = TRANSMIT_TIMER_PERIOD;
|
|
if (osal_timer_init(timer) < 0) {
|
|
return ERRCODE_FAIL;
|
|
}
|
|
return ERRCODE_SUCC;
|
|
}
|
|
|
|
errcode_t transmit_item_module_init(void)
|
|
{
|
|
errcode_t ret;
|
|
ret = transmit_timer_init();
|
|
if (ret != ERRCODE_SUCC) {
|
|
return ret;
|
|
}
|
|
|
|
g_transmit_ctrl.transmit_id = 0x10;
|
|
return ERRCODE_SUCC;
|
|
}
|