/** * @file debug_link.c * @brief 调试链路层实现(comm_link_ctx + TCP Socket + comm_link 分发) */ #include "debug_link.h" #include "tcp_protocol.h" #include "publicdata/public_define.h" #include "lwip/sockets.h" #include "lwip/netdb.h" #include #include #include "FreeRTOS.h" #include "task.h" #include "semphr.h" #include "app_fatfs/fatfs_init.h" #if BLE_DEBUG_EN #include "ble_link/fc41d_ble.h" #endif #if TCP_DEBUG_EN /* ============================================================================= * 会话上下文(原 comm_link_ctx.c) * ============================================================================= */ static comm_link_ctx_t s_comm_link_ctx; comm_link_ctx_t *comm_link_ctx_get(void) { return &s_comm_link_ctx; } comm_link_session_t *comm_link_session(void) { return &s_comm_link_ctx.session; } void comm_link_ctx_reset_session(void) { comm_link_type_t saved_type = s_comm_link_ctx.session.type; memset(&s_comm_link_ctx.session, 0, sizeof(s_comm_link_ctx.session)); s_comm_link_ctx.session.type = saved_type; } void comm_link_ctx_reset_all(void) { memset(&s_comm_link_ctx, 0, sizeof(s_comm_link_ctx)); } /* ============================================================================= * TCP Socket 后端(原 tcp_server_socket.c,本文件内 static) * ============================================================================= */ #ifndef AF_INET #define AF_INET 2 #endif #ifndef SOCK_STREAM #define SOCK_STREAM 1 #endif #ifndef SOL_SOCKET #define SOL_SOCKET 0xFFF #endif #ifndef SO_REUSEADDR #define SO_REUSEADDR 0x0004 #endif #ifndef INADDR_ANY #define INADDR_ANY 0x00000000 #endif #ifndef F_GETFL #define F_GETFL 3 #endif #ifndef F_SETFL #define F_SETFL 4 #endif #ifndef O_NONBLOCK #define O_NONBLOCK 0x0004 #endif #ifndef EWOULDBLOCK #define EWOULDBLOCK 11 #endif #ifndef EAGAIN #define EAGAIN 11 #endif #ifndef ECONNRESET #define ECONNRESET 104 #endif #ifndef EPIPE #define EPIPE 32 #endif #ifndef ECONNABORTED #define ECONNABORTED 103 #endif #ifndef ETIMEDOUT #define ETIMEDOUT 110 #endif #ifndef ENETDOWN #define ENETDOWN 100 #endif #ifndef ENETUNREACH #define ENETUNREACH 101 #endif #ifndef EHOSTUNREACH #define EHOSTUNREACH 113 #endif #ifndef errno extern int errno; #endif #define TCP_LOCAL_PORT TCP_DEBUG_PORT #define MAX_CLIENTS TCP_DEBUG_MAX_CLIENTS typedef struct { int server_socket; int client_socket; uint8_t is_client_connected; struct sockaddr_in client_addr; } tcp_socket_server_t; static tcp_socket_server_t socket_server = { .server_socket = -1, .client_socket = -1, .is_client_connected = 0, }; static SemaphoreHandle_t socket_mutex = NULL; static int tcp_socket_create_server(void) { int sock; struct sockaddr_in server_addr; int opt = 1; sock = lwip_socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { TCP_PRINT("Failed to create socket: %d\r\n", sock); return -1; } lwip_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = htons(TCP_LOCAL_PORT); if (lwip_bind(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { TCP_PRINT("Failed to bind socket to port %d\r\n", TCP_LOCAL_PORT); lwip_close(sock); return -1; } if (lwip_listen(sock, MAX_CLIENTS) < 0) { TCP_PRINT("Failed to listen on socket\r\n"); lwip_close(sock); return -1; } { int flags = lwip_fcntl(sock, F_GETFL, 0); lwip_fcntl(sock, F_SETFL, flags | O_NONBLOCK); } TCP_PRINT("TCP server socket created on port %d\r\n", TCP_LOCAL_PORT); return sock; } static int tcp_socket_init(void) { socket_mutex = xSemaphoreCreateMutex(); if (socket_mutex == NULL) { TCP_PRINT("Failed to create socket mutex\r\n"); return -1; } socket_server.server_socket = tcp_socket_create_server(); if (socket_server.server_socket < 0) { vSemaphoreDelete(socket_mutex); socket_mutex = NULL; return -1; } socket_server.client_socket = -1; socket_server.is_client_connected = 0; TCP_PRINT("Socket server initialized successfully\r\n"); return 0; } static int tcp_socket_accept_client(void) { struct sockaddr_in client_addr; socklen_t addr_len = sizeof(client_addr); int new_sock; if (socket_server.server_socket < 0) { return -1; } if (socket_mutex != NULL) { xSemaphoreTake(socket_mutex, portMAX_DELAY); } new_sock = lwip_accept(socket_server.server_socket, (struct sockaddr *)&client_addr, &addr_len); if (new_sock >= 0) { if (socket_server.is_client_connected) { TCP_PRINT("Rejecting new connection - already have a client\r\n"); lwip_close(new_sock); if (socket_mutex != NULL) { xSemaphoreGive(socket_mutex); } return 0; } { int flags = lwip_fcntl(new_sock, F_GETFL, 0); lwip_fcntl(new_sock, F_SETFL, flags | O_NONBLOCK); } socket_server.client_socket = new_sock; socket_server.is_client_connected = 1; memcpy(&socket_server.client_addr, &client_addr, sizeof(client_addr)); TCP_PRINT("Client connected from %s:%d\r\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); } if (socket_mutex != NULL) { xSemaphoreGive(socket_mutex); } return (new_sock >= 0) ? 1 : 0; } static int tcp_socket_receive_data(uint8_t *buffer, uint32_t buffer_size) { int received; if (buffer == NULL || buffer_size == 0U) { return -1; } if (socket_mutex != NULL) { xSemaphoreTake(socket_mutex, portMAX_DELAY); } if (!socket_server.is_client_connected || socket_server.client_socket < 0) { if (socket_mutex != NULL) { xSemaphoreGive(socket_mutex); } return -1; } received = lwip_recv(socket_server.client_socket, buffer, buffer_size, 0); if (received > 0) { TCP_PRINT("Received %d bytes from client\r\n", received); } else if (received == 0) { TCP_PRINT("Client disconnected\r\n"); lwip_close(socket_server.client_socket); socket_server.client_socket = -1; socket_server.is_client_connected = 0; received = -1; #if FATFS_EN fatfs_set_write_disable_flag(FATFS_WRITE_DISABLE_TCP_DEBUG, 0); #endif } else { int err = errno; if (err != EWOULDBLOCK && err != EAGAIN) { TCP_PRINT("Socket receive error: %d\r\n", err); if (err == ECONNRESET || err == EPIPE || err == ECONNABORTED || err == ETIMEDOUT || err == ENETDOWN || err == ENETUNREACH || err == EHOSTUNREACH) { TCP_PRINT("Connection error detected, closing socket\r\n"); lwip_close(socket_server.client_socket); socket_server.client_socket = -1; socket_server.is_client_connected = 0; #if FATFS_EN fatfs_set_write_disable_flag(FATFS_WRITE_DISABLE_TCP_DEBUG, 0); #endif } received = -1; } else { received = 0; } } if (socket_mutex != NULL) { xSemaphoreGive(socket_mutex); } return received; } static int tcp_socket_send_data(const uint8_t *data, uint32_t len) { int sent; if (data == NULL || len == 0U) { return -1; } if (socket_mutex != NULL) { xSemaphoreTake(socket_mutex, portMAX_DELAY); } if (!socket_server.is_client_connected || socket_server.client_socket < 0) { if (socket_mutex != NULL) { xSemaphoreGive(socket_mutex); } return -1; } sent = lwip_send(socket_server.client_socket, data, len, 0); if (sent > 0) { TCP_PRINT("Sent %d bytes to client\r\n", sent); } else { TCP_PRINT("Failed to send data: %d\r\n", sent); if (sent < 0) { int err = errno; if (err == ECONNRESET || err == EPIPE) { TCP_PRINT("Connection broken, closing socket\r\n"); lwip_close(socket_server.client_socket); socket_server.client_socket = -1; socket_server.is_client_connected = 0; } } } if (socket_mutex != NULL) { xSemaphoreGive(socket_mutex); } return sent; } static int tcp_socket_is_client_connected(void) { int connected; if (socket_mutex != NULL) { xSemaphoreTake(socket_mutex, portMAX_DELAY); } connected = socket_server.is_client_connected; if (socket_mutex != NULL) { xSemaphoreGive(socket_mutex); } return connected; } static void tcp_socket_close_client(void) { if (socket_mutex != NULL) { xSemaphoreTake(socket_mutex, portMAX_DELAY); } if (socket_server.client_socket >= 0) { lwip_close(socket_server.client_socket); socket_server.client_socket = -1; } socket_server.is_client_connected = 0; #if FATFS_EN fatfs_set_write_disable_flag(FATFS_WRITE_DISABLE_TCP_DEBUG, 0); #endif TCP_PRINT("Client connection closed\r\n"); if (socket_mutex != NULL) { xSemaphoreGive(socket_mutex); } } static void tcp_socket_close_server(void) { if (socket_mutex != NULL) { xSemaphoreTake(socket_mutex, portMAX_DELAY); } if (socket_server.client_socket >= 0) { lwip_close(socket_server.client_socket); socket_server.client_socket = -1; } if (socket_server.server_socket >= 0) { lwip_close(socket_server.server_socket); socket_server.server_socket = -1; } socket_server.is_client_connected = 0; #if FATFS_EN fatfs_set_write_disable_flag(FATFS_WRITE_DISABLE_TCP_DEBUG, 0); #endif if (socket_mutex != NULL) { xSemaphoreGive(socket_mutex); vSemaphoreDelete(socket_mutex); socket_mutex = NULL; } TCP_PRINT("Socket server closed\r\n"); } static int tcp_socket_get_client_ip(char *ip_buffer, uint32_t buffer_size) { const char *ip_str; if (ip_buffer == NULL || buffer_size == 0U) { return -1; } if (socket_mutex != NULL) { xSemaphoreTake(socket_mutex, portMAX_DELAY); } if (!socket_server.is_client_connected) { if (socket_mutex != NULL) { xSemaphoreGive(socket_mutex); } return -1; } ip_str = inet_ntoa(socket_server.client_addr.sin_addr); if (ip_str != NULL) { strncpy(ip_buffer, ip_str, buffer_size - 1U); ip_buffer[buffer_size - 1U] = '\0'; } else { if (socket_mutex != NULL) { xSemaphoreGive(socket_mutex); } return -1; } if (socket_mutex != NULL) { xSemaphoreGive(socket_mutex); } return 0; } /* ============================================================================= * comm_link 分发(原 comm_link.c) * ============================================================================= */ #define SESS (comm_link_session()) static uint8_t comm_link_using_ble(void) { #if BLE_DEBUG_EN return (SESS->type == COMM_LINK_BLE) ? 1U : 0U; #else return 0U; #endif } void comm_link_set_type(comm_link_type_t type) { SESS->type = type; } comm_link_type_t comm_link_get_type(void) { return SESS->type; } comm_link_type_t comm_link_type_from_dip(void) { #if BLE_DEBUG_EN return ble_link_is_bt_mode() ? COMM_LINK_BLE : COMM_LINK_TCP; #else return COMM_LINK_TCP; #endif } int comm_link_start(void) { if (comm_link_using_ble() != 0U) { #if BLE_DEBUG_EN return comm_link_ble_start(); #endif } return tcp_socket_init(); } void comm_link_stop(void) { if (comm_link_using_ble() != 0U) { #if BLE_DEBUG_EN comm_link_ble_stop(); #endif return; } tcp_socket_close_server(); } void comm_link_process(void) { #if BLE_DEBUG_EN if (comm_link_using_ble() != 0U) { comm_link_ble_process(); } #endif } int comm_link_accept_client(void) { if (comm_link_using_ble() != 0U) { return 0; } return tcp_socket_accept_client(); } int comm_link_is_client_connected(void) { if (comm_link_using_ble() != 0U) { #if BLE_DEBUG_EN return comm_link_ble_is_client_connected(); #endif return 0; } return tcp_socket_is_client_connected(); } void comm_link_close_client(void) { if (comm_link_using_ble() != 0U) { #if BLE_DEBUG_EN comm_link_ble_close_client(); #endif return; } tcp_socket_close_client(); } int comm_link_receive_data(uint8_t *buffer, uint32_t buffer_size) { if (comm_link_using_ble() != 0U) { #if BLE_DEBUG_EN return comm_link_ble_receive_data(buffer, buffer_size); #endif return 0; } return tcp_socket_receive_data(buffer, buffer_size); } int comm_link_send_data(const uint8_t *data, uint32_t len) { if (comm_link_using_ble() != 0U) { #if BLE_DEBUG_EN return comm_link_ble_send_data(data, len); #endif return -1; } return tcp_socket_send_data(data, len); } int comm_link_get_peer_info(char *buf, uint32_t buf_size) { if ((buf == NULL) || (buf_size == 0U)) { return -1; } if (SESS->peer_info[0] != '\0') { (void)snprintf(buf, buf_size, "%s", SESS->peer_info); return 0; } if (comm_link_using_ble() != 0U) { #if BLE_DEBUG_EN return comm_link_ble_get_peer_info(buf, buf_size); #endif } return tcp_socket_get_client_ip(buf, buf_size); } #else /* TCP_DEBUG_EN */ comm_link_ctx_t *comm_link_ctx_get(void) { return NULL; } comm_link_session_t *comm_link_session(void) { return NULL; } void comm_link_ctx_reset_session(void) { } void comm_link_ctx_reset_all(void) { } void comm_link_set_type(comm_link_type_t type) { (void)type; } comm_link_type_t comm_link_get_type(void) { return COMM_LINK_TCP; } comm_link_type_t comm_link_type_from_dip(void) { return COMM_LINK_TCP; } int comm_link_start(void) { return -1; } void comm_link_stop(void) { } void comm_link_process(void) { } int comm_link_accept_client(void) { return -1; } int comm_link_is_client_connected(void) { return 0; } void comm_link_close_client(void) { } int comm_link_receive_data(uint8_t *buffer, uint32_t buffer_size) { (void)buffer; (void)buffer_size; return -1; } int comm_link_send_data(const uint8_t *data, uint32_t len) { (void)data; (void)len; return -1; } int comm_link_get_peer_info(char *buf, uint32_t buf_size) { (void)buf; (void)buf_size; return -1; } #endif /* TCP_DEBUG_EN */