/***************************************************************************** * file lib/process/pd_dbg.c * author YuLiang * version 1.0.0 * date 01-June-2023 * brief This file provides all the debug server related operation functions. ****************************************************************************** * Attention * *

© COPYRIGHT(c) 2021 LandPower

* * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of LandPower nor the names of its contributors may be used to * endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ******************************************************************************/ /* Includes ------------------------------------------------------------------*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef CFG_DEV_TYPE_LAND_PD /* 标准C库头文件. */ #include #include #include #include #include #include /* 用户代码头文件. */ #include "cJSON.h" #include "main.h" #include "mtimer.h" #include "pd_dbg.h" #include "pd_csg.h" #include "pd_dau.h" #include "pd_upgrade.h" /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private typedef -----------------------------------------------------------*/ enum DEBUG_CMD_TYPE { DEBUG_CMD_INFO_GET = 1, DEBUG_CMD_INFO_SET = 2, DEBUG_CMD_SLOT_GET = 3, DEBUG_CMD_STATE_SEND = 4, DEBUG_CMD_UPDATE = 5, DEBUG_CMD_UPDATE_RV = 6 }; /* 报文头结构. */ typedef struct { uint16_t len; uint8_t dev_type_m; uint8_t dev_type_s; uint32_t dev_id; uint8_t cmd_type; uint8_t cmd; uint16_t pkt_id; uint8_t version; uint8_t reserve[19]; } debug_pkt_head_t; /* 设备信息 */ typedef struct { uint8_t type_m; // 主设备号 uint8_t type_s; // 次设备号 uint8_t slot; // slot id uint8_t reserved0[1]; // 保留 uint32_t dev_id; // 设备ID char hostname[FILE_NAME_LEN]; // 设备名 128byte uint32_t factory_date; // 出厂日期. uint32_t deployment_date; // 部署日期. uint8_t app_version[DEV_VERSION_STR_LEN]; // 软件版本 uint8_t app_compile_time[DEV_VERSION_STR_LEN]; // 软件编译时间 uint8_t hardware_version[DEV_VERSION_STR_LEN]; // 硬件版本 uint8_t FPGA_version[DEV_VERSION_STR_LEN]; // fpga版本 uint32_t ip; // 本机 IP. uint32_t mask; // 本机 MASK. uint32_t gw; // 本机网关 uint8_t mac[6]; // MAC地址. uint16_t server_port; // 服务器端口号. uint32_t server_ipv4; // 服务器 IP. uint8_t port[8]; uint8_t port_type[8]; } debug_pkt_info_t; /* 设备信息 */ typedef struct { uint8_t is_insert; uint8_t is_connect; uint8_t port_sum; uint8_t reserved0; } debug_pkt_slot_state_t; /* 设备信息 */ typedef struct { debug_pkt_info_t info; debug_pkt_slot_state_t state; } debug_pkt_slot_t; /* 设备信息 */ typedef struct { uint32_t utc; uint32_t run_time; uint8_t is_insert[PD_SLOTS_MAX]; uint8_t is_connect[PD_SLOTS_MAX]; } debug_pkt_state_t; typedef struct { uint32_t index; uint32_t len; } debug_pkt_msg_t; /* Private variables ---------------------------------------------------------*/ debug_ctrl_t debug_ctrl; /* Private function prototypes -----------------------------------------------*/ /* Internal functions --------------------------------------------------------*/ /* 包头填充. */ void _debug_pkt_head_init(uint8_t *buf, uint16_t len, uint8_t cmd) { debug_pkt_head_t *head = (debug_pkt_head_t*)buf; /* 封装报文头. */ head->len = len; head->dev_type_m = device_info.type_m; head->dev_type_s= device_info.type_s; head->dev_id = device_info.dev_id; head->cmd = cmd; } /* 数据发送 */ void _debug_pkt_send(uint8_t *buf, uint16_t len) { int32_t rv = 0; //printh("#Send %d:\r\n", len); //buf_print((char*)buf, len > 64 ? 64 : len); //printh("\r\n"); rv = sendto(debug_ctrl.fd, buf, len, 0, (struct sockaddr*)&debug_ctrl.server, sizeof(debug_ctrl.server)); if (rv < 0) { DBG(DBG_M_DEBUG, "Sendto return %s!\r\n", safe_strerror(errno)); } } int32_t _debug_recv_info_get(uint8_t *buf, int32_t len) { debug_pkt_info_t *pinfo = (debug_pkt_info_t*)(buf + sizeof(debug_pkt_head_t)); memcpy(&debug_ctrl.server, &debug_ctrl.state.server, sizeof(struct sockaddr_in)); debug_ctrl.state.is_connect = TRUE; pinfo->type_m = device_info.type_m; pinfo->type_s = device_info.type_s; pinfo->dev_id = device_info.dev_id; snprintf(pinfo->hostname, FILE_NAME_LEN, "%s", device_info.hostname); pinfo->factory_date = device_info.factory_date; pinfo->deployment_date = device_info.deployment_date; snprintf((char*)pinfo->app_version, DEV_VERSION_STR_LEN, "%s", device_info.app_version); snprintf((char*)pinfo->app_compile_time, DEV_VERSION_STR_LEN, "%s", device_info.app_compile_time); snprintf((char*)pinfo->hardware_version, DEV_VERSION_STR_LEN, "%s", device_info.hardware_version); snprintf((char*)pinfo->FPGA_version, DEV_VERSION_STR_LEN, "%s", device_info.FPGA_version); pinfo->ip = device_info.ip; pinfo->mask = device_info.mask; pinfo->gw = device_info.gw; pinfo->server_port = csg.server_port; pinfo->server_ipv4 = csg.server_ip; /* 封装报文头. */ _debug_pkt_head_init(buf, sizeof(debug_pkt_head_t) + sizeof(debug_pkt_info_t), DEBUG_CMD_INFO_GET); /* 发送报文 */ _debug_pkt_send(buf, sizeof(debug_pkt_head_t) + sizeof(debug_pkt_info_t)); return E_NONE; } int32_t _debug_recv_info_set(uint8_t *buf, int32_t len) { debug_pkt_info_t *pinfo = (debug_pkt_info_t*)(buf + sizeof(debug_pkt_head_t)); uint8_t mac[MAC_ADDR_LEN] = {0}; bool change_ip = FALSE; device_info.dev_id = pinfo->dev_id; snprintf(device_info.hostname, FILE_NAME_LEN, "%s", pinfo->hostname); snprintf((char*)pinfo->hardware_version, DEV_VERSION_STR_LEN, "%s", device_info.hardware_version); if (device_info.ip != pinfo->ip) { device_info.ip = pinfo->ip; change_ip = TRUE; } device_info.mask = pinfo->mask; device_info.gw = pinfo->gw; csg.server_port = pinfo->server_port; csg.server_ip = pinfo->server_ipv4; device_info.factory_date = pinfo->factory_date; /* 封装报文头. */ _debug_pkt_head_init(buf, sizeof(debug_pkt_head_t), DEBUG_CMD_INFO_SET); /* 发送报文 */ _debug_pkt_send(buf, sizeof(debug_pkt_head_t)); /* 保存配置 */ vtysh_config_save(); if (change_ip) { mac_generate_from_ip(device_info.ip, mac); memcpy(device_info.mac, mac, MAC_ADDR_LEN); vtysh_eth0_save(); } vtysh_device_save(); return E_NONE; } int32_t _debug_recv_slot_get(uint8_t *buf, int32_t len) { debug_pkt_slot_t *pinfo = (debug_pkt_slot_t*)(buf + sizeof(debug_pkt_head_t)); dau_contact_t *dau = NULL; uint32_t slot = *(uint32_t*)(buf + sizeof(debug_pkt_head_t)); if (slot > PD_SLOTS_MAX || slot < 1) { return E_BAD_PARAM; } slot--; if (daus[slot].state.is_connect) { dau = &daus[slot].info; pinfo->info.type_m = dau->type_m; pinfo->info.type_s = dau->type_s; pinfo->info.slot = slot + 1; pinfo->info.dev_id = dau->dev_id; snprintf(pinfo->info.hostname, FILE_NAME_LEN, "%s", dau->hostname); pinfo->info.factory_date = dau->factory_date; pinfo->info.deployment_date = dau->deployment_date; snprintf((char*)pinfo->info.app_version, DEV_VERSION_STR_LEN, "%s", dau->app_version); snprintf((char*)pinfo->info.app_compile_time, DEV_VERSION_STR_LEN, "%s", dau->app_compile_time); snprintf((char*)pinfo->info.hardware_version, DEV_VERSION_STR_LEN, "%s", dau->hardware_version); snprintf((char*)pinfo->info.FPGA_version, DEV_VERSION_STR_LEN, "%s", dau->FPGA_version); pinfo->info.ip = dau->ip; pinfo->info.mask = dau->mask; pinfo->info.gw = dau->gw; pinfo->info.server_port = dau->server_port; pinfo->info.server_ipv4 = dau->server_ipv4; pinfo->state.is_insert = daus[slot].state.is_insert; pinfo->state.is_connect = daus[slot].state.is_connect; pinfo->state.port_sum = daus[slot].state.port_sum; } else { pinfo->info.type_m = 0; pinfo->info.type_s = 0; } /* 封装报文头. */ _debug_pkt_head_init(buf, sizeof(debug_pkt_head_t) + sizeof(debug_pkt_slot_t), DEBUG_CMD_SLOT_GET); /* 发送报文 */ _debug_pkt_send(buf, sizeof(debug_pkt_head_t) + sizeof(debug_pkt_slot_t)); return E_NONE; } int32_t _debug_recv_state_get(uint8_t *buf, int32_t len) { debug_ctrl.state.state_cnt = 0; return E_NONE; } /* 升级文件接收 */ int32_t _debug_recv_update(uint8_t *buf, int32_t len) { static int fd = -1; debug_pkt_msg_t *head_msg = (debug_pkt_msg_t*)(buf + sizeof(debug_pkt_head_t)); char *data = (char*)(buf + sizeof(debug_pkt_head_t) + sizeof(debug_pkt_msg_t)); int32_t len_wr = 0; /* 首保处理, 打开文件描述符, 初始化变量 */ if (0 == head_msg->index) { if (fd > 0) { close(fd); fd = -1; } fd = open(PD_UPG_SOFTWARE, O_WRONLY | O_CREAT | O_TRUNC, 0777); if (fd < 0) { DBG(DBG_M_DEBUG, "Open file " PD_UPG_SOFTWARE " error!\n"); return E_SYS_CALL; } } /* 收包流程 */ len_wr = write(fd, data, head_msg->len); if (len_wr != head_msg->len) { DBG(DBG_M_DEBUG, "Write file " PD_UPG_SOFTWARE " error!\n"); return E_SYS_CALL; } /* 封装报文头. */ _debug_pkt_head_init(buf, sizeof(debug_pkt_head_t) + sizeof(debug_pkt_msg_t), DEBUG_CMD_UPDATE); /* 发送报文 */ _debug_pkt_send(buf, sizeof(debug_pkt_head_t) + sizeof(debug_pkt_msg_t)); /* 最后一个报文处理 */ if (head_msg->len < 1024) { close(fd); fd = -1; DBG(DBG_M_DEBUG, "Receive upgrade file end.\r\n"); pd_upg_start(PD_UPG_FROM_DBG, PD_UPG_SEL_CMU); } return E_NONE; } /* 报文校验. */ int32_t _debug_recv_check(uint8_t *buf, int len) { debug_pkt_head_t *head = (debug_pkt_head_t*)buf; /* 报文长度检查 */ if (head->len > DEBUG_BUG_SIZE) { return E_ERROR; } /* 只收主控设备 */ if (head->dev_type_m != 3 || head->dev_type_s != 99) { return E_ERROR; } if (debug_ctrl.state.is_connect && debug_ctrl.server.sin_addr.s_addr != debug_ctrl.state.server.sin_addr.s_addr) { return E_ERROR; } return E_NONE; } /* 调试工具报文数据处理. */ int32_t _debug_recv_process(uint8_t *buf, int32_t len) { debug_pkt_head_t *head = (debug_pkt_head_t*)buf; /* 报文格式检查. */ LD_E_RETURN(DBG_M_DEBUG, _debug_recv_check(buf, len)); /* 报文处理. */ switch(head->cmd) { case DEBUG_CMD_INFO_GET: _debug_recv_info_get(buf, len); break; case DEBUG_CMD_INFO_SET: _debug_recv_info_set(buf, len); break; case DEBUG_CMD_SLOT_GET: _debug_recv_slot_get(buf, len); break; case DEBUG_CMD_STATE_SEND: _debug_recv_state_get(buf, len); break; case DEBUG_CMD_UPDATE: _debug_recv_update(buf, len); break; default: DBG(DBG_M_DEBUG, "Debug not support cmd:%x\n", head->cmd); break; } return E_NONE; } /* 调试工具报文接收处理线程. */ void *_debug_recv_handle(void *arg) { struct sockaddr_in server; socklen_t server_len = sizeof(struct sockaddr_in); uint16_t data_len = 0; /* 等待初始化完成 */ while(!is_system_init) { sleep(1); } while(1) { /* 读取数据. */ data_len = recvfrom(debug_ctrl.fd, debug_ctrl.buf, DEBUG_BUG_SIZE, 0, (struct sockaddr*)&server, &server_len); if (data_len <= 0) { DBG(DBG_M_DEBUG, "Recvfrom return ERROR %s!\r\n", safe_strerror(errno)); continue; } //printh("#Recv %d:\r\n", data_len); //buf_print((char*)debug_ctrl.buf, data_len > 64 ? 64 : data_len); //printh("\r\n"); /* 收包长度小于头长度则不处理 */ if (data_len < sizeof(debug_pkt_head_t)) { continue; } memcpy(&debug_ctrl.state.server, &server, sizeof(struct sockaddr_in)); _debug_recv_process(debug_ctrl.buf, data_len); } return NULL; } int32_t _debug_send_state(void) { uint8_t *buf = debug_ctrl.buf_send; debug_pkt_state_t *pinfo = (debug_pkt_state_t*)(buf + sizeof(debug_pkt_head_t)); uint8_t i = 0; /* 封装报文头. */ _debug_pkt_head_init(buf, sizeof(debug_pkt_head_t) + sizeof(debug_pkt_state_t), DEBUG_CMD_STATE_SEND); pinfo->utc = time(NULL); pinfo->run_time = start_time; for(i = 0; i < PD_SLOTS_MAX; i++) { pinfo->is_insert[i] = daus[i].state.is_insert; pinfo->is_connect[i] = daus[i].state.is_connect; } /* 发送报文 */ _debug_pkt_send(buf, sizeof(debug_pkt_head_t) + sizeof(debug_pkt_state_t)); return E_NONE; } /* 调试工具报文接收处理线程. */ void *_debug_send_handle(void *arg) { /* 等待初始化完成 */ while(!is_system_init) { sleep(1); } while(1) { sleep(3); if (debug_ctrl.state.is_connect) { _debug_send_state(); debug_ctrl.state.state_cnt++; if (debug_ctrl.state.state_cnt > 3) { debug_ctrl.state.is_connect = FALSE; debug_ctrl.state.state_cnt = 0; } } } return NULL; } /* Interface functions -------------------------------------------------------*/ /* 调试工具初始化. */ int32_t debug_handle_init(void) { return E_NONE; } int32_t debug_handle_init_after(void) { struct sockaddr_in server; thread_param_t param = {0}; int fd = 0; /* 创建 socket. */ fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { log_err(LOG_DEBUG, "ERROR at socket create return %s!", safe_strerror(errno)); return E_SYS_CALL; } /* 绑定端口 */ bzero(&server, sizeof(server)); server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); server.sin_port = htons(42971); if(bind(fd, (struct sockaddr*)&server, sizeof(server)) < 0) { log_err(LOG_CSG, "ERROR at socket bind return %s!", safe_strerror(errno)); close(fd); return E_SYS_CALL; } /* 保存数据. */ debug_ctrl.fd = fd; param.priority = 25; param.log_module = LOG_DEBUG; snprintf(param.thread_name, THREAD_NAME_LEN, "DEBUG_RECV"); create_thread(_debug_recv_handle, ¶m); param.priority = 25; param.log_module = LOG_DEBUG; snprintf(param.thread_name, THREAD_NAME_LEN, "DEBUG_STATE"); create_thread(_debug_send_handle, ¶m); return E_NONE; } /* 升级结果回复处理 */ void debug_upgrade_result_send(int32_t rv, char *buf) { uint8_t *buf_send = debug_ctrl.buf_update; int32_t *ret = (int32_t*)(buf_send + sizeof(debug_pkt_head_t)); /* 封装报文头. */ _debug_pkt_head_init(buf_send, sizeof(debug_pkt_head_t) + sizeof(int32_t), DEBUG_CMD_UPDATE_RV); /* 0-错误 1-正常 */ *ret = rv; /* 发送报文 */ _debug_pkt_send(buf_send, sizeof(debug_pkt_head_t) + sizeof(int32_t)); } #endif /************************ (C) COPYRIGHT LandPower ***** END OF FILE ****************/