mcu_hi3321_watch/middleware/utils/dfx/diag/diag_pkt_router.c
2025-05-26 20:15:20 +08:00

426 lines
15 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) @CompanyNameMagicTag 2021-2023. All rights reserved.
* Description: pkt router
* This file should be changed only infrequently and with great care.
*/
#include "diag_pkt_router.h"
#include "securec.h"
#include "diag_msg.h"
#include "diag_mem.h"
#include "diag_cmd_dst.h"
#include "diag_ind_dst.h"
#include "diag_tx.h"
#include "diag_debug.h"
#include "zdiag_adapt_layer.h"
#include "diag_dfx.h"
#include "dfx_adapt_layer.h"
#include "errcode.h"
#include "debug_print.h"
#include "diag_service.h"
#include "uapi_crc.h"
#define DIAG_ROUTER_EXTRAS_MAX_LEN (DIAG_ROUTER_HEADER_MAX_LEN + DIAG_ROUTER_CRC_LEN + DIAG_ROUTER_EOF_LEN)
typedef struct {
diag_merge_data_status status;
uint8_t module_id;
} diag_merge_flag_t;
#if (CONFIG_DFX_SUPPORT_DIAG_MULTI_FRAME == DFX_YES)
static diag_merge_flag_t g_diag_merge_flag[DIAG_SUPPORT_CHANNEL_CNT] = {0};
#endif
static void diag_router_build_frame(diag_router_frame_t *frame, uint16_t send_len, diag_router_data_t *data)
{
diag_router_inner_frame_t *inner = (diag_router_inner_frame_t *)frame->inner;
uint16_t offset = 0;
uint16_t payload_len = send_len - DIAG_ROUTER_HEADER_LEN;
frame->sof = DIAG_ROUTER_FRAME_START_FLAG;
frame->ctrl = frame_ctrl_build(data->ctrl.en_crc, data->ctrl.en_fid, data->ctrl.en_sn, data->ctrl.en_eof,
data->ctrl.en_full_crc, data->ctrl.en_crypto, data->ctrl.en_extend);
if ((data->ctrl.en_extend) != 0) {
inner = (diag_router_inner_frame_t *)(frame->inner + DIAG_ROUTER_CTRL2_LEN);
frame->inner[0] = frame_ctrl2_build(data->ctrl2.ack_type);
payload_len -= DIAG_ROUTER_CTRL2_LEN;
}
inner->len_msb = (uint8_t)(payload_len >> DIAG_FRAME_SHIFT_8);
inner->len_lsb = (uint8_t)payload_len;
if ((data->ctrl.en_fid) != 0) {
inner->payload[offset] = data->fid;
offset++;
}
if ((data->ctrl.en_sn) != 0) {
inner->payload[offset] = data->sn_count;
offset++;
}
if ((data->echo) != 0) {
inner->payload[offset] = data->echo;
offset++;
}
memcpy_s((void *)(inner->payload + offset), data->data_len, data->data, data->data_len);
offset += data->data_len;
if ((data->ctrl.en_crc) != 0) {
uint16_t crc16;
if ((data->ctrl.en_full_crc) != 0) {
crc16 = uapi_crc16(0, (uint8_t *)frame, DIAG_ROUTER_HEADER_LEN + data->ctrl.en_extend + offset);
} else {
crc16 = uapi_crc16(0, (uint8_t *)inner->payload, offset);
}
memcpy_s((void *)(inner->payload + offset), sizeof(uint16_t), &crc16, sizeof(uint16_t));
offset += (uint16_t)sizeof(uint16_t);
}
if ((data->ctrl.en_eof) != 0) {
inner->payload[offset] = DIAG_ROUTER_FRAME_END_FLAG;
}
}
/* 回复ack */
static void diag_router_check_and_send_ack(diag_router_frame_t *frame, diag_pkt_process_param_t *process_param,
uint8_t echo)
{
/* 是否有扩展CTRL字段 */
if (get_frame_ctrl_extend_en(frame->ctrl) == 0) {
return;
}
diag_router_ctrl2_t *ctrl2 = (diag_router_ctrl2_t *)&frame->inner[0];
/* 是否需要ACK */
if (ctrl2->ack_type != FRAME_ACK_TYPE_ACK) {
return;
}
dfx_log_debug("diag pkt send ack\r\n");
diag_router_data_t router_data = {0};
router_data.ctrl.en_crc = 1;
router_data.ctrl.en_fid = 0;
router_data.ctrl.en_sn = FRAME_SN_FLAG_NONE;
router_data.ctrl.en_eof = 0;
router_data.ctrl.en_full_crc = 0;
router_data.ctrl.en_crypto = 0;
router_data.ctrl.en_extend = 1;
router_data.ctrl2.ack_type = FRAME_ACK_TYPE_ECHO;
router_data.sn_count = 0;
router_data.echo = echo;
router_data.data = NULL;
router_data.data_len = 0;
uint16_t send_len = DIAG_ROUTER_HEADER_LEN + DIAG_ROUTER_CTRL2_LEN + DIAG_ROUTER_ECHO_LEN + DIAG_ROUTER_CRC_LEN;
uint8_t *ack_buffer = dfx_malloc(0, send_len);
if (ack_buffer != NULL) {
diag_router_build_frame((diag_router_frame_t *)ack_buffer, send_len, &router_data);
diag_pkt_handle_t pkt;
diag_pkt_handle_init(&pkt, 1);
diag_pkt_handle_set_data(&pkt, DIAG_PKT_DATA_ID_0, ack_buffer, send_len, DIAG_PKT_STACK_DATA);
process_param->dst_addr = process_param->src_addr;
diag_pkt_router_output(&pkt, process_param);
dfx_free(0, ack_buffer);
}
}
#if (CONFIG_DFX_SUPPORT_DIAG_RX_PKT == DFX_YES)
/* 接收处理 */
STATIC errcode_t diag_pkt_router_notify(diag_pkt_handle_t *pkt, diag_pkt_process_param_t *process_param)
{
if ((pkt == NULL) || (pkt->data[0] == NULL) || (pkt->data_len[0] == 0)) {
return ERRCODE_INVALID_PARAM;
}
diag_router_frame_t *frame = (diag_router_frame_t *)pkt->data[0];
if (frame->sof != DIAG_ROUTER_FRAME_START_FLAG) {
return ERRCODE_FAIL;
}
diag_router_ctrl_t *ctrl = (diag_router_ctrl_t *)&frame->ctrl;
diag_router_inner_frame_t *inner = (diag_router_inner_frame_t *)(frame->inner + ctrl->en_extend);
uint16_t payload_len = get_frame_len(inner->len_msb, inner->len_lsb);
uint16_t calc_crc_len = payload_len;
/* data_len使用uint32_t防止翻转 */
uint32_t data_len = (uint32_t)DIAG_ROUTER_HEADER_LEN + (uint32_t)ctrl->en_extend + (uint32_t)payload_len;
/* 如果payload_len大于pkt数据长度payload_len错误 */
if (data_len > (uint32_t)pkt->data_len[0]) {
return ERRCODE_FAIL;
}
/* 是否有结束标志 */
if ((ctrl->en_eof) != 0) {
calc_crc_len -= ((calc_crc_len > DIAG_ROUTER_EOF_LEN) ? DIAG_ROUTER_EOF_LEN : calc_crc_len);
}
/* 校验crc */
if ((ctrl->en_crc) != 0) {
uint16_t crc_val;
calc_crc_len -= ((calc_crc_len > DIAG_ROUTER_CRC_LEN) ? DIAG_ROUTER_CRC_LEN : calc_crc_len);
if ((ctrl->en_full_crc) != 0) {
crc_val = uapi_crc16(0, (uint8_t *)frame, DIAG_FRAME_HEADER_SIZE + ctrl->en_extend + calc_crc_len);
} else {
crc_val = uapi_crc16(0, (uint8_t *)inner->payload, calc_crc_len);
}
uint16_t frame_crc = *(uint16_t *)(&inner->payload[calc_crc_len]);
uint8_t frame_echo = (crc_val != frame_crc) ? 1 : 0;
diag_router_check_and_send_ack(frame, process_param, frame_echo);
/* 校验失败 */
if (frame_echo != 0) {
dfx_log_err("diag pkt check crc error! frame_crc = 0x%x crc_val = 0x%x\r\n", frame_crc, crc_val);
return ERRCODE_DIAG_CRC_ERROR;
}
} else {
/* 如果有效数据长度为0去掉头尾payload_len错误 */
if (calc_crc_len == 0) {
return ERRCODE_FAIL;
}
}
/* frame len is no longer used and is used to record addr */
inner->len_msb = process_param->dst_addr;
inner->len_lsb = process_param->src_addr;
return diag_service_data_proc(frame, (uint16_t)data_len);
}
#endif /* #if (CONFIG_DFX_SUPPORT_DIAG_RX_PKT == DFX_YES) */
static uint8_t diag_get_frame_module_id(diag_router_frame_t *frame, uint8_t extra_len, uint8_t src_addr)
{
diag_ser_frame_t *ser_frame = (diag_ser_frame_t *)((uint8_t *)frame + extra_len);
uint8_t module_id = ser_frame->module_id;
#if (CONFIG_DFX_SUPPORT_DIAG_MULTI_FRAME == DFX_YES)
diag_channel_id_t id = diag_adapt_addr_2_channel_id((diag_addr)src_addr);
if (id >= DIAG_SUPPORT_CHANNEL_CNT) {
return module_id;
}
uint8_t sn = get_frame_ctrl_sn(frame->ctrl);
/* 不是分包数据 */
if (sn == 0) {
g_diag_merge_flag[id].status = DIAG_DATA_NO_MERGE;
g_diag_merge_flag[id].module_id = 0;
return module_id;
}
/* 分包数据只有第一包中包含module_id和cmd id */
if (sn == DIAG_FRAME_SN_START) {
/* 第一包保存module_id */
g_diag_merge_flag[id].module_id = module_id;
g_diag_merge_flag[id].status = DIAG_DATA_MERGING;
return module_id;
} else if ((sn == DIAG_FRAME_SN_INSIDE) && (g_diag_merge_flag[id].status == DIAG_DATA_MERGING)) {
return g_diag_merge_flag[id].module_id;
} else if ((sn == DIAG_FRAME_SN_END) && (g_diag_merge_flag[id].status == DIAG_DATA_MERGING)) {
g_diag_merge_flag[id].status = DIAG_DATA_MERGED;
return g_diag_merge_flag[id].module_id;
} else {
dfx_log_err("the SN of package is incorrect.\r\n");
return module_id;
}
#else
return module_id;
#endif /* #if (CONFIG_DFX_SUPPORT_DIAG_MULTI_FRAME == DFX_YES) */
}
static bool diag_check_transmit_pkt(diag_pkt_handle_t *pkt, diag_pkt_process_param_t *process_param)
{
uint8_t extra_len = 0;
diag_router_frame_t *frame = (diag_router_frame_t *)pkt->data[0];
uint8_t module_id;
/* 数据保存至Flash的类型如离线日志 */
if (pkt->output_type == 1) {
return false;
}
/* 加密的数据 */
#ifdef CONFIG_DIAG_WITH_SECURE
if (get_frame_ctrl_secure_flag(frame->ctrl) != 0) {
return false;
}
#endif /* CONFIG_DIAG_WITH_SECURE */
if (frame->sof != DIAG_ROUTER_FRAME_START_FLAG) {
return false;
}
extra_len = diag_pkt_router_calc_prefix_len((diag_router_ctrl_t *)&(frame->ctrl),
(diag_router_ctrl2_t *)&(frame->inner[0]));
module_id = diag_get_frame_module_id(frame, extra_len, process_param->src_addr);
if (module_id == DIAG_SER_FILE_TRANFER || module_id == DIAG_SER_OTA) {
return true;
}
return false;
}
STATIC errcode_t diag_pkt_router_enqueue(diag_pkt_handle_t *pkt, diag_pkt_process_param_t *process_param)
{
errcode_t ret;
diag_pkt_msg_t msg;
ret = diag_pkt_need_cross_task(pkt);
if (ret != ERRCODE_SUCC) {
dfx_log_err("[ERROR][diag_pkt_router_enqueue][%d][errcode=%u]\r\n", __LINE__, ret);
return ret;
}
msg.pkt = *pkt;
msg.param.cur_proc = DIAG_PKT_PROC_SYNC;
msg.param.src_addr = process_param->src_addr;
msg.param.dst_addr = process_param->dst_addr;
if (diag_check_transmit_pkt(pkt, process_param)) {
ret = transmit_msg_write(DFX_MSG_ID_DIAG_PKT, (uint8_t *)&msg, sizeof(diag_pkt_msg_t), false);
} else {
ret = dfx_msg_write(DFX_MSG_ID_DIAG_PKT, (uint8_t *)&msg, sizeof(diag_pkt_msg_t), false);
}
if (ret == ERRCODE_SUCC) {
zdiag_dfx_send_local_q_success();
diag_pkt_handle_clean(pkt);
} else {
zdiag_dfx_send_local_q_fail();
}
return ret;
}
STATIC errcode_t diag_pkt_router_process(diag_pkt_handle_t *pkt, diag_pkt_process_param_t *process_param)
{
diag_frame_fid_t dst_addr = process_param->dst_addr;
if (dst_addr != DIAG_FRAME_FID_LOCAL) {
return diag_pkt_router_output(pkt, process_param);
} else {
#if (CONFIG_DFX_SUPPORT_DIAG_RX_PKT == DFX_YES)
return diag_pkt_router_notify(pkt, process_param);
#else
return ERRCODE_DIAG_NOT_SUPPORT;
#endif
}
}
errcode_t diag_pkt_router(diag_pkt_handle_t *pkt, diag_pkt_process_param_t *process_param)
{
errcode_t ret = ERRCODE_FAIL;
if (process_param->cur_proc == DIAG_PKT_PROC_ASYNC) {
ret = diag_pkt_router_enqueue(pkt, process_param);
} else {
ret = diag_pkt_router_process(pkt, process_param);
}
diag_pkt_free(pkt);
return ret;
}
/* 发送流程 */
STATIC errcode_t diag_pkt_router_send_single(diag_router_data_t *data)
{
diag_pkt_handle_t pkt;
diag_pkt_process_param_t process_param;
uint16_t send_len = data->data_len + diag_pkt_router_calc_prefix_len(&(data->ctrl), &(data->ctrl2)) +
diag_pkt_router_calc_suffix_len(&(data->ctrl));
uint8_t *buffer = dfx_malloc(0, send_len);
if (buffer == NULL) {
return ERRCODE_MALLOC;
}
diag_router_build_frame((diag_router_frame_t *)buffer, send_len, data);
diag_pkt_handle_init(&pkt, 1);
diag_pkt_handle_set_data(&pkt, DIAG_PKT_DATA_ID_0, buffer, send_len, DIAG_PKT_STACK_DATA);
process_param.cur_proc = DIAG_PKT_PROC_SYNC;
process_param.dst_addr = data->fid >> DIAG_ROUTER_FID_DST_BIT;
process_param.src_addr = data->fid & DIAG_ROUTER_FID_MASK;
errcode_t ret = diag_pkt_router(&pkt, &process_param);
dfx_free(0, buffer);
return ret;
}
#if (CONFIG_DFX_SUPPORT_DIAG_MULTI_FRAME == DFX_YES)
/* 拆包 */
STATIC errcode_t diag_pkt_router_send_loop(diag_router_data_t *router_data)
{
errcode_t ret;
uint16_t offset = 0;
uint16_t valid_mfs = 0;
uint16_t size = router_data->data_len;
uint16_t non_payload_len = diag_pkt_router_calc_prefix_len(&(router_data->ctrl), &(router_data->ctrl2)) +
diag_pkt_router_calc_suffix_len(&(router_data->ctrl));
if (router_data->mfs <= non_payload_len) {
dfx_log_err("diag pkt mfs error! valid_mfs = 0x%x\r\n", valid_mfs);
return ERRCODE_DIAG_BAD_DATA;
}
valid_mfs = router_data->mfs - non_payload_len;
diag_router_data_t *send_data = router_data;
while (offset < size) {
/* first frame data */
if (offset == 0) {
send_data->data_len = valid_mfs;
send_data->ctrl.en_sn = FRAME_SN_FLAG_START;
} else if (offset + valid_mfs > size) {
send_data->data_len = size - offset;
send_data->ctrl.en_sn = FRAME_SN_FLAG_END;
} else {
send_data->data_len = valid_mfs;
send_data->ctrl.en_sn = FRAME_SN_FLAG_ONGOING;
}
ret = diag_pkt_router_send_single(send_data);
if (ret != ERRCODE_SUCC) {
return ret;
}
offset += valid_mfs;
send_data->data += valid_mfs;
send_data->sn_count++;
}
return ERRCODE_SUCC;
}
#endif /* #if (CONFIG_DFX_SUPPORT_DIAG_MULTI_FRAME == DFX_YES) */
errcode_t diag_pkt_router_send(diag_router_data_t *router_data)
{
if (router_data == NULL) {
return ERRCODE_INVALID_PARAM;
}
if ((router_data->ctrl.en_sn) != 0) {
#if (CONFIG_DFX_SUPPORT_DIAG_MULTI_FRAME == DFX_YES)
return diag_pkt_router_send_loop(router_data);
#else
return ERRCODE_DIAG_NOT_SUPPORT;
#endif
} else {
return diag_pkt_router_send_single(router_data);
}
}
void diag_pkt_msg_proc(uint32_t msg_id, uint8_t *msg, uint32_t msg_len)
{
diag_pkt_msg_t *pkt_msg = (diag_pkt_msg_t *)msg;
diag_pkt_process_param_t process_param;
process_param.cur_proc = pkt_msg->param.cur_proc;
process_param.src_addr = pkt_msg->param.src_addr;
process_param.dst_addr = pkt_msg->param.dst_addr;
diag_pkt_router(&pkt_msg->pkt, &process_param);
unused(msg_id);
unused(msg_len);
}