261 lines
8.5 KiB
C
261 lines
8.5 KiB
C
/*
|
||
* Copyright (c) @CompanyNameMagicTag 2021-2023. All rights reserved.
|
||
* Description: diag rx
|
||
* This file should be changed only infrequently and with great care.
|
||
*/
|
||
#include "diag_rx_api.h"
|
||
#include "securec.h"
|
||
#include "diag_mem.h"
|
||
#include "diag_pkt.h"
|
||
#include "errcode.h"
|
||
#include "diag_channel_item.h"
|
||
#include "diag_pkt_router.h"
|
||
#include "zdiag_adapt_layer.h"
|
||
#include "diag_dfx.h"
|
||
#include "uapi_crc.h"
|
||
|
||
#define MUX_START_OFFSET 0
|
||
#define MAX_MUX_PARAM_SIZE 1024
|
||
|
||
#if (CONFIG_DFX_SUPPORT_DIAG_RX_PKT == DFX_YES)
|
||
|
||
STATIC int32_t diag_hso_find_start_flag(uint8_t *data, uint16_t size)
|
||
{
|
||
int i;
|
||
int pos = -1;
|
||
for (i = 0; i < size; i++) {
|
||
if (data[i] == DIAG_ROUTER_FRAME_START_FLAG) {
|
||
pos = i;
|
||
break;
|
||
}
|
||
}
|
||
return pos;
|
||
}
|
||
|
||
STATIC uint16_t diag_get_frame_len(diag_router_frame_t *frame)
|
||
{
|
||
diag_router_inner_frame_t *inner = (diag_router_inner_frame_t *)frame->inner;
|
||
uint16_t frame_len = DIAG_ROUTER_HEADER_LEN;
|
||
if (get_frame_ctrl_extend_en(frame->ctrl) != 0) {
|
||
inner = (diag_router_inner_frame_t *)(frame->inner + DIAG_ROUTER_CTRL2_LEN);
|
||
frame_len += DIAG_ROUTER_CTRL2_LEN;
|
||
}
|
||
frame_len += get_frame_len(inner->len_msb, inner->len_lsb);
|
||
return frame_len;
|
||
}
|
||
|
||
STATIC int32_t soc_diag_chan_copy_data(diag_channel_item_t *item, uint8_t *data, uint16_t size)
|
||
{
|
||
uint16_t free_size = item->rx_buf_len - item->rx_buf_pos;
|
||
uint16_t copy_size = uapi_min(size, free_size);
|
||
if (memcpy_s(&item->rx_buf[item->rx_buf_pos], free_size, data, copy_size) != EOK) {
|
||
return 0;
|
||
}
|
||
item->rx_buf_pos += copy_size;
|
||
return copy_size;
|
||
}
|
||
|
||
STATIC void diag_rest_rx_buf(diag_channel_item_t *item)
|
||
{
|
||
item->rx_buf_pos = MUX_START_OFFSET;
|
||
item->rx_buf_is_using = false;
|
||
}
|
||
|
||
STATIC uint16_t diag_get_rx_data_size(diag_channel_item_t *item)
|
||
{
|
||
return item->rx_buf_pos - MUX_START_OFFSET;
|
||
}
|
||
|
||
STATIC errcode_t diag_chan_move_buf(diag_channel_item_t *item, uint32_t dst, uint32_t src, uint32_t len)
|
||
{
|
||
if (memmove_s(&item->rx_buf[dst], item->rx_buf_len, &item->rx_buf[src], len) != EOK) {
|
||
return ERRCODE_FAIL;
|
||
}
|
||
item->rx_buf_pos -= (uint16_t)(src - dst);
|
||
return ERRCODE_SUCC;
|
||
}
|
||
|
||
STATIC errcode_t diag_check_frame_crc(diag_router_frame_t *frame, uint16_t frame_len)
|
||
{
|
||
uint16_t cal_crc;
|
||
uint16_t frame_crc;
|
||
|
||
unused(frame_len);
|
||
|
||
diag_router_ctrl_t *ctrl = (diag_router_ctrl_t *)&frame->ctrl;
|
||
if ((ctrl->en_crc) == 0) {
|
||
/* CRC校验未使能,直接返回成功 */
|
||
return ERRCODE_SUCC;
|
||
}
|
||
|
||
diag_router_inner_frame_t *inner = (diag_router_inner_frame_t *)frame->inner;
|
||
/* 是否有扩展CTRL字段 */
|
||
if ((ctrl->en_extend) != 0) {
|
||
inner = (diag_router_inner_frame_t *)(frame->inner + DIAG_ROUTER_CTRL2_LEN);
|
||
}
|
||
|
||
uint16_t payload_len = get_frame_len(inner->len_msb, inner->len_lsb);
|
||
/* 是否有结束标志 */
|
||
if ((ctrl->en_eof) != 0) {
|
||
/* 确保payload_len不发生翻转 */
|
||
payload_len -= ((payload_len > DIAG_ROUTER_EOF_LEN) ? DIAG_ROUTER_EOF_LEN : payload_len);
|
||
}
|
||
|
||
/* 确保payload_len不发生翻转 */
|
||
payload_len -= ((payload_len > DIAG_ROUTER_CRC_LEN) ? DIAG_ROUTER_CRC_LEN : payload_len);
|
||
|
||
/* 校验crc */
|
||
if ((ctrl->en_full_crc) != 0) {
|
||
cal_crc = uapi_crc16(0, (uint8_t *)frame, DIAG_FRAME_HEADER_SIZE + ctrl->en_extend + payload_len);
|
||
} else {
|
||
cal_crc = uapi_crc16(0, (uint8_t *)inner->payload, payload_len);
|
||
}
|
||
frame_crc = *(uint16_t *)(&inner->payload[payload_len]);
|
||
if (cal_crc != frame_crc) {
|
||
return ERRCODE_FAIL;
|
||
}
|
||
return ERRCODE_SUCC;
|
||
}
|
||
|
||
STATIC diag_router_frame_t *diag_chan_full_pkt_receive(diag_channel_item_t *item)
|
||
{
|
||
if (diag_get_rx_data_size(item) < DIAG_ROUTER_HEADER_LEN) {
|
||
return NULL;
|
||
}
|
||
diag_router_frame_t *frame = (diag_router_frame_t *)&item->rx_buf[MUX_START_OFFSET];
|
||
|
||
uint16_t frame_len = diag_get_frame_len(frame);
|
||
if (frame_len >= item->rx_buf_len) {
|
||
/*
|
||
* 帧长度大于buf长度,可能是找到了一个错误的帧头,取出一个字节,继续向后查找SOF。
|
||
*/
|
||
diag_chan_move_buf(item, MUX_START_OFFSET, 1, (uint32_t)(item->rx_buf_pos - 1));
|
||
return NULL;
|
||
}
|
||
|
||
if (diag_get_rx_data_size(item) < frame_len) {
|
||
return NULL;
|
||
}
|
||
|
||
if (diag_check_frame_crc(frame, frame_len) != ERRCODE_SUCC) {
|
||
/*
|
||
* CRC校验失败,可能是找到了一个错误的帧头,取出一个字节,继续向后查找SOF。
|
||
*/
|
||
diag_chan_move_buf(item, MUX_START_OFFSET, 1, (uint32_t)(item->rx_buf_pos - 1));
|
||
return NULL;
|
||
}
|
||
|
||
return frame;
|
||
}
|
||
|
||
STATIC errcode_t diag_channel_process_frame(diag_channel_id_t id, diag_router_frame_t *frame)
|
||
{
|
||
diag_pkt_handle_t pkt;
|
||
diag_pkt_process_param_t process_param;
|
||
|
||
uint16_t frame_len = diag_get_frame_len(frame);
|
||
diag_pkt_handle_init(&pkt, 1);
|
||
diag_pkt_handle_set_data(&pkt, DIAG_PKT_DATA_ID_0, (uint8_t*)frame, frame_len, DIAG_PKT_STACK_DATA);
|
||
|
||
process_param.cur_proc = DIAG_PKT_PROC_ASYNC;
|
||
process_param.src_addr = diag_adapt_channel_id_2_addr(id);
|
||
process_param.dst_addr = DIAG_FRAME_FID_LOCAL; /* 接收到的数据dst_addr改为LOCAL */
|
||
return diag_pkt_router(&pkt, &process_param);
|
||
}
|
||
|
||
STATIC int32_t diag_chan_rx_frame_uart_data(diag_channel_id_t id, uint8_t *data, uint16_t size)
|
||
{
|
||
int32_t copied_size = 0;
|
||
int32_t start_flag_pos;
|
||
int32_t frame_count = 0;
|
||
diag_router_frame_t *frame = NULL;
|
||
|
||
diag_channel_item_t *item = diag_chan_idx_2_item(id);
|
||
if (item == NULL) {
|
||
return 0;
|
||
}
|
||
|
||
while (copied_size != size && item->rx_buf_pos != item->rx_buf_len) { /* 数据未处理完成 并且 接收缓存有空间 */
|
||
copied_size += soc_diag_chan_copy_data(item, data + copied_size, (uint16_t)(size - copied_size));
|
||
if (item->rx_buf_is_using) {
|
||
return frame_count;
|
||
}
|
||
|
||
if (diag_get_rx_data_size(item) < DIAG_ROUTER_HEADER_LEN) {
|
||
continue;
|
||
}
|
||
|
||
start_flag_pos = diag_hso_find_start_flag(&item->rx_buf[MUX_START_OFFSET], item->rx_buf_pos - MUX_START_OFFSET);
|
||
if (start_flag_pos < 0) {
|
||
diag_rest_rx_buf(item);
|
||
continue;
|
||
} else if (start_flag_pos > 0) {
|
||
diag_chan_move_buf(item, MUX_START_OFFSET, (uint32_t)start_flag_pos,
|
||
(uint32_t)(item->rx_buf_pos - start_flag_pos));
|
||
}
|
||
|
||
do {
|
||
frame = diag_chan_full_pkt_receive(item);
|
||
if (frame == NULL) {
|
||
break;
|
||
}
|
||
uint16_t frame_len = diag_get_frame_len(frame);
|
||
(void)diag_channel_process_frame(id, frame);
|
||
|
||
frame_count++;
|
||
diag_chan_move_buf(item, MUX_START_OFFSET, frame_len, item->rx_buf_pos - frame_len);
|
||
} while (true);
|
||
}
|
||
return frame_count;
|
||
}
|
||
|
||
STATIC errcode_t diag_channel_rx_data(diag_channel_id_t id, uint8_t *data, uint16_t size)
|
||
{
|
||
errcode_t ret;
|
||
|
||
if (data == NULL || size == 0) {
|
||
return ERRCODE_INVALID_PARAM;
|
||
}
|
||
|
||
diag_router_frame_t *frame = (diag_router_frame_t *)data;
|
||
|
||
ret = diag_check_mux_pkt(frame, size);
|
||
if (ret != ERRCODE_SUCC) {
|
||
return ret;
|
||
}
|
||
|
||
return diag_channel_process_frame(id, frame);
|
||
}
|
||
|
||
#endif /* #if (CONFIG_DFX_SUPPORT_DIAG_RX_PKT == DFX_YES) */
|
||
|
||
/* 字符串数据接收函数,data中是字符数据,可能需要组包(形成完整Diag帧数据),也可能包含多个帧 */
|
||
int32_t uapi_diag_channel_rx_mux_char_data(diag_channel_id_t id, uint8_t *data, uint16_t size)
|
||
{
|
||
#if (CONFIG_DFX_SUPPORT_DIAG_RX_PKT == DFX_YES)
|
||
int32_t frame_cnt;
|
||
|
||
diag_dfx_channel_receive_data(id, size);
|
||
frame_cnt = diag_chan_rx_frame_uart_data(id, data, size);
|
||
diag_dfx_channel_receive_frame(id, (uint32_t)frame_cnt);
|
||
return frame_cnt;
|
||
#else
|
||
return 0;
|
||
#endif
|
||
}
|
||
|
||
/* Diag帧数据接收函数,data中是一个完整的Diag帧数据,无需组包 */
|
||
errcode_t uapi_diag_channel_rx_frame_data(diag_channel_id_t id, uint8_t *data, uint16_t size)
|
||
{
|
||
#if (CONFIG_DFX_SUPPORT_DIAG_RX_PKT == DFX_YES)
|
||
diag_dfx_channel_receive_data(id, size);
|
||
errcode_t ret = diag_channel_rx_data(id, data, size);
|
||
if (ret == ERRCODE_SUCC) {
|
||
diag_dfx_channel_receive_frame(id, 1);
|
||
}
|
||
return ret;
|
||
#else
|
||
return ERRCODE_DIAG_NOT_SUPPORT;
|
||
#endif
|
||
}
|