You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1133 lines
31 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* Copyright (c) Hisilicon Technologies Co., Ltd. 2012-2021. All rights reserved.
* Description: Initial Draft
* Author: Hisilicon
* Create: 2012-12-22
*/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <arpa/inet.h>
#include "soc_errno.h"
#ifndef SOCT_MDBG_VERSION_LINUX // Android version
#include <cutils/properties.h>
#include <cutils/log.h>
#endif
#include "soc_log.h"
#include "securec.h"
#include "mpi_dbg_ir_debug.h"
#include "mpi_dbg_gpio_debug.h"
#include "mpi_dbg_i2c_debug.h"
#include "mpi_dbg_pwm_debug.h"
#include "mpi_dbg_panel_debug.h"
#include "mpi_dbg_pq_debug.h"
#include "uapi_uart.h"
#include "mpi_mdbg.h"
#include "mpi_system_ext.h"
#include "uapi_system.h"
#include "mpi_dbg_aq.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
#undef LOG_MODULE_ID
#define LOG_MODULE_ID SOC_ID_SYS
#define BACKLOG 20
#define MAXLEN 32
#define MDBG_CMDBUF_SIZE (0xFFFF + 0x100)
#define mdbg_offset_of(s, m) ((size_t) & (((s *)0)->m))
#define mdbg_size_of(s, m) (sizeof(((s *)0)->m))
#define mdbg_get_value(buf, s, m) ((*(s *)(buf)).m)
#define BUFLEN 1000
#define mdbg_check_return_if_fail(param, errno, str) do { \
if (param) { \
fprintf(stderr, "[%s %d] %s\n", __FUNCTION__, __LINE__, (str)); \
return errno; \
} \
} while (0)
/* ----------------------------------------------------------------------------- */
/* Local Types Declarations */
/* ----------------------------------------------------------------------------- */
static td_s32 g_server_sock_fd = -1;
static td_s32 g_net_process_flag = 1;
static td_s32 g_port = 4321;
static td_bool g_init = TD_FALSE;
static pthread_t g_muart_debug_pid;
static pthread_t g_mnet_debug_pid;
static td_u8 *g_buf = TD_NULL;
static td_bool g_pq_dbg = TD_TRUE;
static td_bool g_debug_request = TD_FALSE;
static td_bool g_debug_mode = TD_FALSE;
static td_bool g_exit_dbg = TD_FALSE;
static td_s32 g_net_dev_fd = -1;
static td_bool g_net_use = TD_TRUE;
static td_bool g_is_cts_enable = TD_FALSE;
static td_bool g_uart_open_dev = TD_TRUE;
static td_bool g_uart_switch = TD_FALSE;
static struct timespec g_delay = { 0 };
static ext_mdbg_chip g_mdbg_chip;
static td_u8 g_magic_char[] = {'s', 'o', 'c', 't', '_', 'p', 'q', '_', 't', 'o', 'o', 'l', '.', 's', 'h'};
/* 串口消息数据包 */
/* VRC send "soct_pq_tool.sh" then send 12byte data to dbg thread. */
/* so this message struct should 2 byte alignment. */
#pragma pack(2)
typedef struct {
td_u8 magic_num[4]; /* 魔数: 'H''L''T''V' 最多4个字符组成 */
td_u16 cmd; /* 命令, 参考MDBG_CMD_E */
td_u16 length; /* mdbg_data 的有效数据长度 */
td_u32 header_check_sum; /* 头校验码 */
td_u8 *mdbg_data; /* 有效数据 */
td_u32 data_check_sum; /* 有效数据校验码 */
} ext_mdbg_msg;
#pragma pack()
/* PQ命令 */
typedef enum {
/* COMMON */
EXT_MDBG_CMD_UART_SWITCH = 0x1000,
EXT_MDBG_CMD_ECHO_ACK = 0x1001,
/* TV */
EXT_MDBG_CMD_PQ = 0x6000,
EXT_MDBG_CMD_AQ = 0x7000,
/* PANEL */
EXT_MDBG_CMD_PANEL = 0x8000,
/* IR */
EXT_MDBG_CMD_IR = 0x9000,
EXT_MDBG_CMD_VIR,
/* 新添加COMM,GPIO,I2C,PWM */
EXT_MDBG_CMD_COMM,
EXT_MDBG_CMD_GPIO,
EXT_MDBG_CMD_I2C,
EXT_MDBG_CMD_PWM
} ext_mdbg_cmd_type;
static td_void *iapi_mdbg_net_server_start(td_void *para);
static td_s32 iapi_mdbg_net_create_thread(td_void);
static td_void *iapi_mdbg_net_process(td_void *args);
static td_void iapi_mdbg_net_send_flag(td_s32 client_sockfd, td_u8 error);
static td_void iapi_mdbg_net_read_data(td_u8 *buf, td_s32 count, td_s32 *read_size);
static td_void iapi_mdbg_net_write_data(const td_u8 *buf, td_s32 count);
static td_s32 iapi_mdbg_net_recv_data(td_s32 client_sockfd, td_u8 *buf, td_u32 count, td_s32 *read_size);
static td_s32 iapi_mdbg_net_check_data(const td_u8 *buf);
static td_s32 iapi_mdbg_parser_msg(const td_u8 *buf);
static td_void iapi_mdbg_uart_read_data(td_u8 *buf, td_s32 count, td_s32 *read_size);
static td_void iapi_mdbg_uart_write_data(td_u8 *buf, td_s32 count);
static td_s32 iapi_mdbg_uart_open_dev(td_void);
static td_void *iapi_mdbg_uart_thread(td_void *para);
static td_s32 iapi_mdbg_uart_close_dev(td_void);
static td_s32 iapi_mdbg_uart_read_msg(td_u8 *buf);
td_bool iapi_mdbg_is_valid_msg(const td_u8 *magic_num)
{
if (magic_num == TD_NULL) {
soc_err_print_null_pointer(magic_num);
return TD_FALSE;
}
/* 判断0,1,2,3个数组元素的值 */
if ((magic_num[0] != 'H') || (magic_num[1] != 'L') || (magic_num[2] != 'T') || (magic_num[3] != 'V')) {
return TD_FALSE;
}
return TD_TRUE;
}
/* 数据头数据校验 */
td_s32 iapi_mdbg_verify_header_checksum(const td_u8 *buf)
{
td_size_t total_len, i;
td_u32 check_sum1;
td_u32 check_sum2 = 0;
if (buf == TD_NULL) {
soc_err_print_null_pointer(buf);
return TD_FAILURE;
}
/* re-calculate checksum */
total_len = mdbg_offset_of(ext_mdbg_msg, header_check_sum);
check_sum1 = mdbg_get_value(buf, ext_mdbg_msg, header_check_sum);
for (i = 0; i < total_len; i++) {
check_sum2 += buf[i];
}
/* compare checksum */
if (check_sum1 != check_sum2) {
fprintf(stderr, "check header check_sum error!,check_sum1=%x,check_sum2=%x\n", check_sum1, check_sum2);
return TD_FAILURE;
}
return TD_SUCCESS;
}
/* 数据有效数据校验 */
td_s32 iapi_mdbg_verify_data_checksum(const td_u8 *buf, td_u32 checksum)
{
td_u32 total_len, i;
td_u32 check_sum1 = 0;
td_size_t header_size;
if (buf == TD_NULL) {
soc_err_print_null_pointer(buf);
return TD_FAILURE;
}
/* re-calculate checksum */
header_size = mdbg_offset_of(ext_mdbg_msg, mdbg_data);
total_len = mdbg_get_value(buf, ext_mdbg_msg, length);
for (i = 0; i < total_len; i++) {
check_sum1 += buf[i + header_size];
}
/* compare checksum */
if (checksum != check_sum1) {
return TD_FAILURE;
}
return TD_SUCCESS;
}
/* 解析数据 */
td_s32 iapi_mdbg_parser_msg(const td_u8 *buf)
{
td_u32 data_length;
td_u16 mdbg_cmd;
const td_u8 *cmd_buf = TD_NULL;
if (buf == TD_NULL) {
soc_err_print_null_pointer(buf);
return TD_FAILURE;
}
mdbg_cmd = mdbg_get_value(buf, ext_mdbg_msg, cmd);
cmd_buf = buf + mdbg_offset_of(ext_mdbg_msg, mdbg_data);
data_length = mdbg_get_value(buf, ext_mdbg_msg, length);
soc_log_info("iapi:%u\n", mdbg_cmd);
switch (mdbg_cmd) {
case EXT_MDBG_CMD_UART_SWITCH:
uapi_uart_switch(0); // switch to system uart
g_debug_mode = TD_FALSE;
g_net_use = TD_TRUE;
break;
case EXT_MDBG_CMD_ECHO_ACK:
case EXT_MDBG_CMD_VIR:
break;
case EXT_MDBG_CMD_PQ:
mpi_pq_dbg_parser(cmd_buf, data_length);
break;
case EXT_MDBG_CMD_AQ:
mpi_aq_dbg_parser((td_u8 *)cmd_buf, (td_s32)data_length);
break;
case EXT_MDBG_CMD_PANEL:
mpi_panel_dbg_parser(cmd_buf, data_length);
break;
case EXT_MDBG_CMD_IR:
mpi_ir_dbg_parser(cmd_buf, data_length);
break;
case EXT_MDBG_CMD_COMM:
// don't delete mpi_comm_dbg_parser(cmd_buf, data_length);
break;
case EXT_MDBG_CMD_GPIO:
mpi_gpio_dbg_parser(cmd_buf, data_length);
break;
case EXT_MDBG_CMD_I2C:
mpi_i2c_dbg_parser(cmd_buf, data_length);
break;
case EXT_MDBG_CMD_PWM:
// don't delete mpi_pwm_dbg_parser(cmd_buf, data_length);
break;
default:
fprintf(stderr, "MDBG not have this CMD: %X\n", mdbg_cmd);
}
return TD_SUCCESS;
}
td_void iapi_mdbg_read_data(td_u8 *buf, td_s32 count, td_s32 *read_size)
{
if (buf == TD_NULL) {
soc_log_err("buf was null!\n");
return;
}
if (read_size == TD_NULL) {
soc_log_err("read_size was null!\n");
return;
}
if (g_net_use == TD_TRUE) {
iapi_mdbg_net_read_data(buf, count, read_size);
} else {
iapi_mdbg_uart_read_data(buf, count, read_size);
}
return;
}
td_void iapi_mdbg_write_data(td_u8 *buf, td_s32 count)
{
if (buf == TD_NULL) {
soc_log_err("buf was null!\n");
return;
}
if (g_net_use == TD_TRUE) {
iapi_mdbg_net_write_data(buf, count);
} else {
iapi_mdbg_uart_write_data(buf, count);
}
return;
}
static td_void iapi_mdbg_reigster_func(td_void)
{
mpi_pq_dbg_register_uart_func(iapi_mdbg_read_data, iapi_mdbg_write_data);
mpi_aq_dbg_register_uart_func(iapi_mdbg_read_data, iapi_mdbg_write_data);
mpi_panel_dbg_register_uart_func(iapi_mdbg_read_data, iapi_mdbg_write_data);
// don't delete mpi_pwm_dbg_register_uart_func(iapi_mdbg_read_data, iapi_mdbg_write_data);
// don't delete mpi_comm_dbg_register_uart_func(iapi_mdbg_read_data, iapi_mdbg_write_data);
mpi_ir_dbg_register_uart_func(iapi_mdbg_read_data, iapi_mdbg_write_data);
mpi_gpio_dbg_register_uart_func(iapi_mdbg_read_data, iapi_mdbg_write_data);
mpi_i2c_dbg_register_uart_func(iapi_mdbg_read_data, iapi_mdbg_write_data);
}
#ifndef SOCT_MDBG_VERSION_LINUX // Android version
static td_void iapi_mdbg_check_user_version(td_bool *cts_enable)
{
char value[PROPERTY_VALUE_MAX] = {0};
property_get("ro.build.type", value, "eng");
value[PROPERTY_VALUE_MAX - 1] = '\0';
if (strcmp(value, "user") == 0) {
*cts_enable = TD_TRUE;
fprintf(stderr, "android user version, close port 4321 \n");
}
}
#endif
static td_s32 iapi_mdbg_start_net_server(td_void)
{
td_s32 ret;
if (!g_is_cts_enable) {
g_net_process_flag = 1;
ret = pthread_create(&g_mnet_debug_pid, NULL, iapi_mdbg_net_server_start, NULL);
if (ret != TD_SUCCESS) {
/* here free g_buf will make uart fail,so not do it */
soc_log_err("Server thread create error\n");
return TD_FAILURE;
}
}
return TD_SUCCESS;
}
/* Debug模块初始化 */
td_s32 uapi_mdbg_init(td_void)
{
td_s32 ret;
uapi_sys_init();
if (g_init == TD_TRUE) {
return TD_SUCCESS;
}
ret = ext_mpi_mdbg_get_chipversion(&g_mdbg_chip);
if (ret != TD_SUCCESS) {
fprintf(stderr, "get chipversion failed...\n");
return TD_FAILURE;
}
/* alloc cmd buffer memory */
g_buf = (td_u8 *)malloc(MDBG_CMDBUF_SIZE);
if (g_buf == TD_NULL) {
fprintf(stderr, "mdebug cmd buffer malloc error\n");
return TD_FAILURE;
}
ret = memset_s(g_buf, MDBG_CMDBUF_SIZE, 0x00, MDBG_CMDBUF_SIZE);
if (ret != EOK) {
goto ERR_EXIT;
}
/* 注册回调函数 */
iapi_mdbg_reigster_func();
/* open uart device */
ret = iapi_mdbg_uart_open_dev();
if (ret != TD_SUCCESS) {
soc_log_err("iapi_mdbg_uart_open_dev failed!\n");
}
/* create uart recv thread */
ret = pthread_create(&g_muart_debug_pid, NULL, iapi_mdbg_uart_thread, g_buf);
if (ret != TD_SUCCESS) {
g_uart_open_dev = TD_FALSE;
// don't delete mpi_pq_dbg_update_uart_status(g_uart_open_dev, g_pq_dbg, g_uart_switch, g_is_cts_enable);
fprintf(stderr, "open_uart_dev or mdebug thread create error\n");
goto ERR_EXIT;
}
/* 4. 启动Net server */
#ifndef SOCT_MDBG_VERSION_LINUX // Android version
iapi_mdbg_check_user_version(&g_is_cts_enable);
#endif
// don't delete mpi_pq_dbg_update_uart_status(g_uart_open_dev, g_pq_dbg, g_uart_switch, g_is_cts_enable);
ret = iapi_mdbg_start_net_server();
if (ret != TD_SUCCESS) {
goto ERR_EXIT;
}
g_init = TD_TRUE;
// #endif
return TD_SUCCESS;
ERR_EXIT:
free(g_buf);
g_buf = TD_NULL;
return TD_FAILURE;
}
/* Debug模块去初始化 */
td_s32 uapi_mdbg_deinit(td_void)
{
td_s32 ret;
soc_dbg_func_enter();
if (g_init == TD_FALSE) {
soc_dbg_func_exit();
return TD_SUCCESS;
}
g_net_process_flag = -1;
g_exit_dbg = TD_TRUE;
ret = pthread_join(g_muart_debug_pid, NULL);
if (ret != TD_SUCCESS) {
soc_log_err("uart thread join error\n");
return TD_FAILURE;
}
soc_log_info("uart thread join success\n");
ret = iapi_mdbg_uart_close_dev();
if (ret != TD_SUCCESS) {
soc_log_err("uart device close error\n");
return TD_FAILURE;
}
soc_log_info("iapi_mdbg_uart_close_dev success\n");
g_debug_mode = TD_FALSE;
soc_info_print_bool(g_is_cts_enable);
if (!g_is_cts_enable) {
ret = pthread_join(g_mnet_debug_pid, NULL);
if (ret != TD_SUCCESS) {
soc_log_err("net thread join error\n");
return TD_FAILURE;
}
soc_log_info("net thread join success\n");
shutdown(g_server_sock_fd, 2); // 2代表关屏
soc_log_info("shutdown g_server_sock_fd success\n");
close(g_server_sock_fd);
g_server_sock_fd = -1;
soc_log_info("close g_server_sock_fd success\n");
}
if (g_buf != TD_NULL) {
free(g_buf);
g_buf = TD_NULL;
}
g_init = TD_FALSE;
uapi_sys_deinit();
soc_dbg_func_exit();
// #endif
return TD_SUCCESS;
}
td_s32 uapi_mdbg_enter_debug_mode(td_bool enable)
{
g_pq_dbg = enable;
return TD_SUCCESS;
}
/* 获取调试模式 */
td_s32 uapi_mdbg_get_debug_mode(td_bool *enable)
{
if (enable == TD_NULL) {
soc_log_err("enable was null!\n");
return TD_FAILURE;
}
*enable = g_pq_dbg;
return TD_SUCCESS;
}
td_void *iapi_mdbg_net_server_start(td_void *para)
{
td_s32 ret, temp_fd;
td_u32 client_len;
struct sockaddr_in addr_serv, addr_client;
(td_void)(para);
g_server_sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if (g_server_sock_fd < 0) {
perror("socket fail");
return NULL;
}
if (memset_s(&addr_serv, sizeof(addr_serv), 0, sizeof(addr_serv)) != EOK) {
perror("call memset_s failed!\n");
close(g_server_sock_fd);
g_server_sock_fd = -1;
return NULL;
}
addr_serv.sin_family = AF_INET;
addr_serv.sin_port = htons(g_port);
addr_serv.sin_addr.s_addr = htonl(INADDR_ANY);
client_len = sizeof(struct sockaddr_in);
if (bind(g_server_sock_fd, (struct sockaddr *)&addr_serv, sizeof(struct sockaddr_in)) < 0) {
perror("bind fail");
}
if (listen(g_server_sock_fd, BACKLOG) < 0) {
perror("listen fail");
}
while (g_net_process_flag == 1) {
printf("begin accept:\n");
temp_fd = accept(g_server_sock_fd, (struct sockaddr *)&addr_client, (socklen_t *)&client_len);
if (temp_fd < 0) {
perror("accept fail");
continue;
}
if (g_net_dev_fd < 0) {
g_net_dev_fd = temp_fd;
} else {
fprintf(stderr, "last connection is not closed!\n");
(void)close(temp_fd);
continue;
}
ret = iapi_mdbg_net_create_thread();
if (ret != TD_SUCCESS) {
fprintf(stderr, "UAPI_MDBG_CreateThread error!\n");
continue;
}
}
return TD_NULL;
}
td_s32 iapi_mdbg_net_create_thread(td_void)
{
pthread_t thread;
td_s32 ret;
pthread_attr_t child_thread_attr;
pthread_attr_init(&child_thread_attr);
pthread_attr_setdetachstate(&child_thread_attr, PTHREAD_CREATE_DETACHED);
ret = pthread_create(&thread, &child_thread_attr, iapi_mdbg_net_process, (void *)g_buf); // 创建子线程
if (ret != TD_SUCCESS) {
fprintf(stderr, "pthread_create error!\n");
pthread_attr_destroy(&child_thread_attr);
return TD_FAILURE;
}
pthread_attr_destroy(&child_thread_attr);
return TD_SUCCESS;
}
td_void *iapi_mdbg_net_process(td_void *args)
{
td_s32 ret;
if (args == TD_NULL) {
soc_log_err("args was null!\n");
return TD_NULL;
}
if (g_net_use != TD_TRUE) {
fprintf(stderr, "Uart is use, Net can't use!\n");
return TD_NULL;
}
while (1) {
td_s32 readesize = 0;
/* 1.接收数据 */
ret = iapi_mdbg_net_recv_data(g_net_dev_fd, (td_u8 *)args, MDBG_CMDBUF_SIZE, &readesize);
if (ret != TD_SUCCESS || readesize <= 0) {
fprintf(stderr, "iapi_mdbg_net_recv_data failed!\n");
iapi_mdbg_net_send_flag(g_net_dev_fd, 0xC0);
break;
}
/* 2.校验数据 */
ret = iapi_mdbg_net_check_data((td_u8 *)args);
if (ret != TD_SUCCESS) {
fprintf(stderr, "check data failed! [%i]\n", ret);
iapi_mdbg_net_send_flag(g_net_dev_fd, 0xC0);
break;
}
/* 3.解析数据 */
iapi_mdbg_net_send_flag(g_net_dev_fd, 0xD0);
ret = iapi_mdbg_parser_msg((td_u8 *)args);
if (ret != TD_SUCCESS) {
fprintf(stderr, "Parser data failed!\n");
}
iapi_mdbg_net_send_flag(g_net_dev_fd, 0xE0);
break;
}
ret = close(g_net_dev_fd);
while (errno == EINTR) {
g_delay.tv_sec = 0;
g_delay.tv_nsec = 10 * 1000; // 10 * 1000 ns = 10us
nanosleep(&g_delay, TD_NULL);
ret = close(g_net_dev_fd);
}
if (ret != TD_SUCCESS) {
fprintf(stdout, "close net_dev_fd failed!\n");
return TD_NULL;
} else {
g_net_dev_fd = -1;
}
fprintf(stdout, "connection close!\n");
return TD_NULL;
}
td_void iapi_mdbg_net_send_flag(td_s32 client_sockfd, td_u8 error)
{
td_u8 ack;
ack = error;
send(client_sockfd, (void *)&ack, 1, 0);
while (errno == EINTR || errno == EAGAIN) {
g_delay.tv_sec = 0;
g_delay.tv_nsec = 10 * 1000; // 10 * 1000 ns = 10us
nanosleep(&g_delay, TD_NULL);
send(client_sockfd, (void *)&ack, 1, 0);
}
}
static td_u32 mdbg_get_msg_header_size(td_void)
{
td_u32 header_size;
header_size = mdbg_size_of(ext_mdbg_msg, magic_num);
header_size += mdbg_size_of(ext_mdbg_msg, cmd);
header_size += mdbg_size_of(ext_mdbg_msg, length);
header_size += mdbg_size_of(ext_mdbg_msg, header_check_sum);
return header_size;
}
td_s32 iapi_mdbg_net_recv_data(td_s32 client_sockfd, td_u8 *buf, td_u32 count, td_s32 *read_size)
{
td_s32 recv_cnt;
fd_set read_fds;
struct timeval timeout;
td_s32 ret;
td_u32 header_size, data_offset, len;
mdbg_check_return_if_fail(buf == TD_NULL, TD_FAILURE, "buf is NULL!");
mdbg_check_return_if_fail(read_size == TD_NULL, TD_FAILURE, "read_size is NULL!");
FD_ZERO(&read_fds);
FD_SET(client_sockfd, &read_fds);
timeout.tv_sec = 5; // 设置时间5s
timeout.tv_usec = 0;
if (select(client_sockfd + 1, &read_fds, NULL, NULL, &timeout) <= 0) {
fprintf(stderr, "socketfd select failed or time out\n");
return TD_FAILURE;
}
header_size = mdbg_get_msg_header_size();
if (FD_ISSET(client_sockfd, &read_fds)) { // 测试sock是否可读即网络上是否有数据
ret = recv(client_sockfd, buf, header_size, MSG_WAITALL); // 前12个字节代表头
while (errno == EINTR || errno == EAGAIN) {
g_delay.tv_sec = 0;
g_delay.tv_nsec = 10 * 1000; // 10 * 1000ns is 10us
nanosleep(&g_delay, TD_NULL);
if (recv(client_sockfd, buf, header_size, MSG_WAITALL) >= 0) {
break;
}
}
if ((ret < (td_s32)header_size) || (header_size > count)) {
return TD_FAILURE;
}
len = mdbg_get_value(buf, ext_mdbg_msg, length) + sizeof(td_u32); // mdbg_data length+chceksum
if (len > count - header_size) {
return TD_FAILURE;
}
data_offset = (td_u32)mdbg_offset_of(ext_mdbg_msg, mdbg_data);
do {
recv_cnt = recv(client_sockfd, buf + data_offset, len, MSG_WAITALL);
} while ((recv_cnt < 0) && (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN));
mdbg_check_return_if_fail(recv_cnt <= 0, TD_FAILURE, "error! recv_cnt <= 0");
mdbg_check_return_if_fail(recv_cnt != (td_s32)len, TD_FAILURE, "error! recv_cnt != (td_s32)len");
*read_size = (td_s32)(len + header_size);
}
return TD_SUCCESS;
}
td_s32 iapi_mdbg_net_check_data(const td_u8 *buf)
{
td_u32 checksum = 0;
td_size_t header_size;
td_u32 len;
errno_t sec_ret;
if (buf == NULL) {
soc_err_print_null_pointer(buf);
return TD_FAILURE;
}
/* check Magic number is valid */
if (iapi_mdbg_is_valid_msg(((ext_mdbg_msg *)buf)->magic_num) != TD_TRUE) {
fprintf(stderr, "check magic number error\n");
return TD_FAILURE;
}
/* check header checksum */
if (iapi_mdbg_verify_header_checksum((td_u8 *)buf) != TD_SUCCESS) {
fprintf(stderr, "check header checksum error\n");
return TD_FAILURE;
}
/* verify data checksum */
header_size = mdbg_offset_of(ext_mdbg_msg, mdbg_data);
len = mdbg_get_value(buf, ext_mdbg_msg, length);
sec_ret = memcpy_s(&checksum, sizeof(td_u32), buf + header_size + len, sizeof(checksum));
if (sec_ret != EOK) {
fprintf(stderr, "call memcpy_s failed!errno=%d\n", sec_ret);
return TD_FAILURE;
}
if (iapi_mdbg_verify_data_checksum(buf, checksum) != TD_SUCCESS) {
fprintf(stderr, "check valid data checksum error\n");
return TD_FAILURE;
}
return TD_SUCCESS;
}
td_void iapi_mdbg_net_read_data(td_u8 *buf, td_s32 count, td_s32 *read_size)
{
td_s32 recv_cnt;
fd_set read_fds;
struct timeval timeout;
td_s32 ret;
if (buf == TD_NULL) {
soc_err_print_null_pointer(buf);
return;
}
if (read_size == TD_NULL) {
soc_err_print_null_pointer(read_size);
return;
}
FD_ZERO(&read_fds);
FD_SET(g_net_dev_fd, &read_fds);
timeout.tv_sec = 5; // 设置时间为5s
timeout.tv_usec = 0;
ret = select(g_net_dev_fd + 1, &read_fds, NULL, NULL, &timeout);
if (ret < 0) {
fprintf(stderr, "socketfd select failed!\n");
return;
}
if (ret == 0) {
fprintf(stderr, "time out!\n");
return;
}
if (FD_ISSET(g_net_dev_fd, &read_fds)) { // 测试sock是否可读即网络上是否有数据
do {
recv_cnt = recv(g_net_dev_fd, buf, count, MSG_WAITALL);
} while ((recv_cnt < 0) && (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN));
if (recv_cnt < 0 || recv_cnt != count) {
fprintf(stderr, "recv data error!\n");
return;
} else if (recv_cnt == 0) {
fprintf(stderr, "socket is disconnected!\n");
return;
} else {
*read_size = count;
}
}
return;
}
td_void iapi_mdbg_net_write_data(const td_u8 *buf, td_s32 count)
{
if (buf == TD_NULL) {
soc_err_print_null_pointer(buf);
return;
}
send(g_net_dev_fd, buf, count, 0);
while (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
g_delay.tv_sec = 0;
g_delay.tv_nsec = 10 * 1000; // 10 * 1000 ns = 10us
nanosleep(&g_delay, TD_NULL);
send(g_net_dev_fd, buf, count, 0);
}
return;
}
td_bool iapi_mdbg_uart_is_open_flag(const td_u8 *magic_num)
{
td_u8 i;
if (magic_num == TD_NULL) {
soc_err_print_null_pointer(magic_num);
return TD_FALSE;
}
for (i = 0; i < sizeof(g_magic_char) / sizeof(td_u8); i++) {
if (magic_num[i] != g_magic_char[i]) {
return TD_FALSE;
}
}
return TD_TRUE;
}
td_void iapi_mdbg_uart_read_data(td_u8 *buf, td_s32 count, td_s32 *read_size)
{
td_s32 ret_val;
td_s32 read_bytes = 0;
if (buf == NULL) {
soc_err_print_null_pointer(buf);
return;
}
if (read_size == NULL) {
soc_err_print_null_pointer(read_size);
return;
}
*read_size = 0;
while (1) {
if (read_bytes >= count) {
break;
}
ret_val = uapi_uart_read((char *)(buf + read_bytes), 1);
if (ret_val <= 0) {
break;
} else {
read_bytes += ret_val;
}
}
*read_size = read_bytes;
return;
}
td_void iapi_mdbg_uart_write_data(td_u8 *buf, td_s32 count)
{
td_s32 ret_val;
if (buf == NULL) {
fprintf(stderr, "buf is null!\n");
return;
}
ret_val = uapi_uart_write((td_char *)buf, (td_u32)count);
if (ret_val < count) {
fprintf(stderr, "write uart date error!\n");
}
}
td_s32 iapi_mdbg_uart_open_dev(td_void)
{
td_s32 ret_val;
ret_val = uapi_uart_init();
if (ret_val != TD_SUCCESS && ret_val != SOC_ERR_UART_OPENED) {
perror("open uart dev fail!");
return TD_FAILURE;
}
/* set defaulty baud speed to 115200 */
if (uapi_uart_set_speed(115200) != TD_SUCCESS) { // 设置波特率为115200
uapi_uart_deinit();
return TD_FAILURE;
}
/* set defaulty uart attribue */
if (uapi_uart_set_attr(8, 1, 'N') != TD_SUCCESS) { // 设置串口的读写数据为8位
uapi_uart_deinit();
return TD_FAILURE;
}
return TD_SUCCESS;
}
td_s32 iapi_mdbg_uart_close_dev(td_void)
{
td_s32 ret;
// 把串口切换回系统使用
uapi_uart_switch(0);
ret = uapi_uart_deinit();
if (ret < 0) {
fprintf(stderr, "Can't close PQ uart\n");
return TD_FAILURE;
}
return TD_SUCCESS;
}
static td_s32 iapi_mdbg_send_uart_ack(td_u8 ack)
{
td_s32 ret_val;
ret_val = uapi_uart_write((td_char *)&ack, sizeof(td_u8));
if (ret_val < 0) {
fprintf(stderr, "send ack1 error\n");
return TD_FAILURE;
}
return TD_SUCCESS;
}
static td_s32 iapi_mdbg_get_uart_data(td_s32 read_size, td_u8 *buf)
{
td_s32 ret_val = 0;
td_u32 checksum = 0;
td_s32 read_total_byte = 0;
td_u32 tmp_val;
/* read data */
read_total_byte += read_size;
tmp_val = mdbg_get_value(buf, ext_mdbg_msg, length), read_size = (td_s32)tmp_val;
if ((read_size == 0) || (read_size > MDBG_CMDBUF_SIZE - read_total_byte - 4)) { // 读取数据最大size4握手字节长度
fprintf(stderr, "read size is zero or out of range!\n");
return TD_SUCCESS;
}
g_delay.tv_sec = 0;
g_delay.tv_nsec = 100000 * 1000; // 100000 * 1000 ns = 10 ms
nanosleep(&g_delay, TD_NULL);
iapi_mdbg_uart_read_data(buf + read_total_byte, read_size, &ret_val);
if (ret_val < read_size) {
fprintf(stderr, "read data time out\n");
return TD_FAILURE;
}
/* read data checksum */
read_total_byte += read_size;
tmp_val = sizeof(td_u32), read_size = (td_s32)tmp_val;
iapi_mdbg_uart_read_data(buf + read_total_byte, read_size, &ret_val);
if (ret_val < (td_s32)sizeof(td_u32)) {
fprintf(stderr, "read CheckSum error\n");
return TD_FAILURE;
}
/* verify data checksum */
if (memcpy_s(&checksum, sizeof(td_u32), buf + read_total_byte, sizeof(checksum)) != EOK) {
fprintf(stderr, "call memcpy_s failed!");
return TD_FAILURE;
}
if (iapi_mdbg_verify_data_checksum(buf, checksum) != TD_SUCCESS) {
fprintf(stderr, "check data checksum error\n");
return TD_FAILURE;
}
return TD_SUCCESS;
}
td_s32 iapi_mdbg_uart_read_msg(td_u8 *buf)
{
td_s32 read_size;
td_s32 ret_val = 0;
if (buf == TD_NULL) {
soc_err_print_null_pointer(buf);
return TD_FAILURE;
}
/* read msg magic number + cmd + len+headerchecsum */
read_size = (td_s32)mdbg_offset_of(ext_mdbg_msg, mdbg_data);
iapi_mdbg_uart_read_data(buf, read_size, &ret_val);
if (ret_val < read_size) {
if (ret_val > 0) {
fprintf(stderr, "read header error\n");
}
return TD_FAILURE;
}
/* check Magic number is valid */
if (iapi_mdbg_is_valid_msg(((ext_mdbg_msg *)buf)->magic_num) != TD_TRUE) {
fprintf(stderr, "check magic number error\n");
return TD_FAILURE;
}
/* check header checksum */
if (iapi_mdbg_verify_header_checksum((td_u8 *)buf) != TD_SUCCESS) {
fprintf(stderr, "check header checksum error\n");
return TD_FAILURE;
}
if (iapi_mdbg_send_uart_ack(0xA0) < 0) {
return TD_FAILURE;
}
ret_val = (td_s32)mdbg_get_value(buf, ext_mdbg_msg, cmd);
if (ret_val == EXT_MDBG_CMD_UART_SWITCH) {
return TD_SUCCESS;
}
/* read data */
ret_val = iapi_mdbg_get_uart_data(read_size, buf);
if (ret_val != TD_SUCCESS) {
return TD_SUCCESS;
}
/* send ack */
if (iapi_mdbg_send_uart_ack(0xB0) < 0) {
return TD_FAILURE;
}
return TD_SUCCESS;
}
static td_void iapi_mdbg_uart_switch(td_void)
{
int ret;
td_u32 boardid = 0;
ret = ext_mpi_sys_get_board_id(&boardid);
if (ret != TD_SUCCESS) {
soc_fatal_print_call_fun_err(uapi_sys_get_board_id, ret);
return;
}
boardid &= 0x2000;
/* switch to mdbg uart */
if (g_mdbg_chip == MDBG_CHIP_RESERVED5 || g_mdbg_chip == MDBG_CHIP_RESERVED19 ||
g_mdbg_chip == MDBG_CHIP_HI3751V811) {
uapi_uart_switch(1); /* reserved5 use uart1 to mdbg feature */
} else if (g_mdbg_chip == MDBG_CHIP_RESERVED9 || g_mdbg_chip == MDBG_CHIP_RESERVED13) {
if (boardid != 0x2000) {
uapi_uart_switch(2); /* reserved9 or reserved13 use uart2 to mdbg feature */
} else {
uapi_uart_switch(5); /* uart5 */
}
} else {
fprintf(stdout, "unkown chip version .... \n");
return;
}
fprintf(stdout, "Start PQ TOOL DBG!\n");
g_uart_switch = TD_TRUE;
g_net_use = TD_FALSE;
g_debug_request = TD_TRUE;
mpi_pq_dbg_update_uart_status(g_uart_open_dev, g_pq_dbg, g_uart_switch, g_is_cts_enable);
if (g_debug_request == TD_TRUE) {
g_debug_mode = TD_TRUE;
g_debug_request = TD_FALSE;
}
}
/* MDGB线程 */
td_void *iapi_mdbg_uart_thread(td_void *para)
{
td_s32 ret_val = TD_FAILURE;
if (para == TD_NULL) {
soc_log_err("para was null!\n");
return TD_NULL;
}
g_delay.tv_sec = 0;
g_delay.tv_nsec = 400000 * 1000; // 400000 * 1000 ns = 40ms
while (1) {
if (g_exit_dbg == TD_TRUE) {
break;
}
if (g_pq_dbg == TD_FALSE) {
nanosleep(&g_delay, TD_NULL);
continue;
}
/* Enter the debug mode */
if (g_debug_mode == TD_FALSE) {
iapi_mdbg_uart_read_data((td_u8 *)para, 15, &ret_val); // 读取数据的最大长度为15
if (iapi_mdbg_uart_is_open_flag(para) != TD_TRUE) {
nanosleep(&g_delay, TD_NULL);
continue;
}
iapi_mdbg_uart_switch();
nanosleep(&g_delay, TD_NULL);
continue;
}
/* recive data */
if (iapi_mdbg_uart_read_msg((td_u8 *)para) != TD_SUCCESS) {
continue;
}
/* parser data */
if (iapi_mdbg_parser_msg((td_u8 *)para) != TD_SUCCESS) {
continue;
}
}
return TD_NULL;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */