Files
STM32F4-Base/Drivers/BSP/NET/net_socket.c
2026-07-19 15:27:49 +08:00

1112 lines
33 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.
/*
* 模块名称Network Socket Core
* 模块功能BSD Socket API 核心实现<EFBC8C>?Socket 管理、状态机<E68081>? * 事件处理、数据收发等功能底层调<E5B182>?CH395F 驱动
* 适用平台STM32F4 系列CH395F 以太网芯片)
* 作者王建<E78E8B>? * 创建日期<E697A5>?026-07-18
* 修改记录<E8AEB0>? */
#include <string.h>
#include <stdio.h>
#include "net_socket.h"
#include "ch395f.h"
#include "main.h"
/*
* 调试输出配置
*/
#define DBG_TAG "[NET]"
#include "dbg_log.h"
/*
* 私有宏定义区
*/
/*
* 私有变量<E58F98>? */
static net_sock_t s_net_socks[NET_MAX_SOCKETS]; /* Socket 控制块数<E59D97>?*/
static int s_net_errno = 0; /* 最后错误码 */
static uint8_t s_net_initialized = 0; /* 初始化标<E58C96>?*/
/*
* 私有宏定义区 - 补充
*/
#define NET_PHY_CHECK_INTERVAL_MS 5000U /* PHY 状态定期检查间隔ms<6D>?*/
/*
* 私有函数声明<E5A3B0>? */
static int alloc_socket(void);
static void handle_connect_event(net_sock_t *p_sock);
static void handle_disconnect_event(net_sock_t *p_sock);
static void handle_recv_event(net_sock_t *p_sock);
static void handle_send_event(net_sock_t *p_sock);
static void handle_timeout_event(net_sock_t *p_sock);
static void fire_event(net_sock_t *p_sock, net_event_t event);
static void parse_ip_string(const char *str, uint8_t *ip_arr);
/*
* 公共函数实现<E5AE9E>? */
/*
* 函数功能网络子系统初始<E5889D>? */
int net_init(const char *ip, const char *mask, const char *gateway) {
ch395f_status_t ret;
/* 清零 Socket 控制<E68EA7>?*/
memset(s_net_socks, 0, sizeof(s_net_socks));
s_net_errno = 0;
s_net_initialized = 0;
/* 检<>?CH395F 芯片 */
if (ch395f_check_exist() != CH395F_STATUS_OK) {
s_net_errno = NET_ERR;
return -1;
}
/* 复位芯片 */
ch395f_reset();
/* 启用 TCP Server 多连接模式bit1=1<>? * Socket 0 专职监听Socket 1~7 自动分配给新连接 */
ch395f_set_fun_para(0x02);
/* 设置 TCP MSS */
ch395f_set_tcp_mss(1460);
/* 设置 TCP 重传参数(必须在 INIT_CH395 之前<E4B98B>?*/
ch395f_set_retrans_count(8); /* 重传 8 <20>?*/
ch395f_set_retrans_period(500); /* 每次间隔 500ms总计 4s 重传窗口 */
/* 设置 TCP KeepAlive 参数(必须在 INIT_CH395 之前<EFBC8C>?ms必须为 500 的倍数IDLE > INTVL<56>?*/
ch395f_set_keepalive_idle(60000); /* 空闲 60 秒后开始探<E5A78B>?*/
ch395f_set_keepalive_intvl(5000); /* <20>?5 秒探测一<E6B58B>?*/
ch395f_set_keepalive_cnt(3); /* 最多探<E5A49A>?3 <20>?*/
/* 设置网络参数(必须在 INIT_CH395 之前<E4B98B>?*/
if (ip != NULL) {
uint8_t ip_arr[4];
uint8_t mask_arr[4];
uint8_t gw_arr[4];
parse_ip_string(ip, ip_arr);
parse_ip_string(mask, mask_arr);
parse_ip_string(gateway, gw_arr);
ch395f_set_ip_addr(ip_arr);
ch395f_set_gwip_addr(gw_arr);
ch395f_set_mask_addr(mask_arr);
} else {
/* 启用 DHCP */
ch395f_set_dhcp(1);
}
/* 初始<E5889D>?CH395F 协议栈(先不配置 buffer测试默认值是否工作 */
ret = ch395f_init();
if (ret != CH395F_STATUS_OK) {
s_net_errno = NET_ERR;
return -1;
}
/* 使能 PING 响应 */
ch395f_ping_enable(1);
s_net_initialized = 1;
return 0;
}
/*
* 函数功能轮询所<E8AFA2>?Socket 状<>? */
int net_poll(void) {
int event_count = 0;
int i;
uint16_t int_status;
if (!s_net_initialized) {
return 0;
}
/*
* GPIO 轮询模式<EFBC9A>?INT# 有效低电平时读取中断状<E696AD>? * 读取 GET_GLOB_INT_STATUS_ALL <20>?CH395F 拉高 INT#若仍有中断则再次拉<E6ACA1>? */
do
{
if (HAL_GPIO_ReadPin(CH395_INT_GPIO_Port, CH395_INT_Pin) == GPIO_PIN_SET) {
break;
}
int_status = ch395f_get_glob_int_status_all();
if (int_status == 0) {
break;
}
/* 诊断:每 3 秒打印一次全局中断状态和 Socket 状<>? * 注意:使用已读取的 int_status不要再读 GINT读即清除<E6B885>?*/
static uint32_t s_last_diag = 0;
uint32_t now_diag = HAL_GetTick();
if ((now_diag - s_last_diag >= 3000) || s_last_diag == 0) {
s_last_diag = now_diag;
DBG_INFO("GINT=0x%04X", int_status);
for (int di = 0; di < NET_MAX_SOCKETS; di++) {
DBG_INFO(" s%d: in_use=%d state=%d",
di, s_net_socks[di].in_use, s_net_socks[di].state);
}
}
if (int_status & CH395F_GINT_STAT_PHY_CHANGE) {
uint8_t phy = ch395f_get_phy_status();
DBG_INFO("PHY_CHANGE: 0x%02X", phy);
if (phy == CH395F_PHY_DISCONN) {
DBG_ERROR("PHY disconnected, sockets may need recovery");
}
}
/* 处理每个 Socket */
for (i = 0; i < NET_MAX_SOCKETS; i++) {
net_sock_t *p_sock = &s_net_socks[i];
/* 检查该 Socket 是否有中断全局中断状<E696AD>?bit4~bit11 对应 socket0~7<>?*/
if (!(int_status & (1U << (i + 4)))) {
continue;
}
/* 读取 Socket 中断状<E696AD>?*/
uint8_t sock_int = ch395f_get_sock_int_status(i);
/* 连接事件 */
if (sock_int & CH395F_SINT_STAT_CONNECT) {
handle_connect_event(p_sock);
event_count++;
}
/* 断开事件 */
if (sock_int & CH395F_SINT_STAT_DISCONNECT) {
handle_disconnect_event(p_sock);
event_count++;
}
/* 数据接收事件 */
if (sock_int & CH395F_SINT_STAT_RECV_OK) {
handle_recv_event(p_sock);
event_count++;
}
/* 发送完成事<E68890>?*/
if (sock_int & CH395F_SINT_STAT_SEND_OK) {
handle_send_event(p_sock);
event_count++;
}
/* 发送缓冲区空闲 */
if (sock_int & CH395F_SINT_STAT_SENBUF_FREE) {
p_sock->send_ready = 1;
}
/* 超时事件 */
if (sock_int & CH395F_SINT_STAT_SOCK_TIMEOUT) {
handle_timeout_event(p_sock);
event_count++;
}
}
/*
* 处理完毕后检<E5908E>?INT# 是否仍为低电<E4BD8E>? * 如果是说明在处理期间有新中断产生需要再次读<E6ACA1>? *
* 注意CH395F <20>?RECV 中断是电平触发的只要接收缓冲区有数据就保持低电平<E5B9B3>? * 如果不跳出循环net_poll() 会无限循环处<E78EAF>?RECV 中断<E4B8AD>? * 导致主循环中的应用代码<E7A081>?echo永远无法执行<E689A7>? * 因此每次 net_poll() 调用只处理一批中断由主循环负责读取数据<E695B0>? */
} while (0);
/* <20>?2 秒打印一次诊断信息(调试用) */
{
static uint32_t s_last_dbg = 0;
uint32_t now = HAL_GetTick();
if (now - s_last_dbg >= 2000) {
s_last_dbg = now;
uint8_t int_level = (HAL_GPIO_ReadPin(CH395_INT_GPIO_Port, CH395_INT_Pin) == GPIO_PIN_RESET) ? 1 : 0;
DBG_DEBUG("INT#=%d", int_level);
for (i = 0; i < NET_MAX_SOCKETS; i++) {
if (s_net_socks[i].in_use) {
uint8_t st[2];
ch395f_get_socket_status((uint8_t)i, st);
uint16_t rl = ch395f_get_recv_len((uint8_t)i);
DBG_DEBUG(" s%d:sw%d/tcp%d rl%d", i, st[0], st[1], rl);
}
}
}
}
return event_count;
}
/*
* 函数功能<EFBC9A>?socket
*/
int net_socket(int domain, int type, int protocol) {
int sockfd;
net_sock_t *p_sock;
/* 参数检<E695B0>?*/
if (domain != NET_AF_INET) {
s_net_errno = NET_ERR_INVAL;
return -1;
}
/* 分配空闲 Socket */
sockfd = alloc_socket();
if (sockfd < 0) {
s_net_errno = NET_ERR_NOMEM;
return -1;
}
p_sock = &s_net_socks[sockfd];
p_sock->ch395_sock = (uint8_t)sockfd;
p_sock->type = (uint8_t)type;
p_sock->state = NET_SOCK_STATE_CREATED;
p_sock->in_use = 1;
p_sock->send_ready = 1;
return sockfd;
}
/*
* 函数功能绑定本地地址和端<E5928C>? */
int net_bind(int sockfd, const struct net_sockaddr *addr, int addrlen) {
net_sock_t *p_sock;
const struct net_sockaddr_in *p_addr_in;
/* 参数检<E695B0>?*/
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
s_net_errno = NET_ERR_BADF;
return -1;
}
p_sock = &s_net_socks[sockfd];
if (!p_sock->in_use) {
s_net_errno = NET_ERR_BADF;
return -1;
}
if (addr == NULL || addrlen < (int)sizeof(struct net_sockaddr_in)) {
s_net_errno = NET_ERR_INVAL;
return -1;
}
p_addr_in = (const struct net_sockaddr_in *)addr;
/* 设置本地端口(转换为主机序) */
p_sock->local_port = net_ntohs(p_addr_in->sin_port);
/* UDP (SOCK_DGRAM): 直接在此打开 CH395F Socket */
if (p_sock->type == NET_SOCK_DGRAM) {
uint8_t status;
/* Socket 4-7 默认无收发缓冲,需显式分配 */
if (sockfd >= 4) {
ch395f_set_send_buf((uint8_t)sockfd, 28, 2);
ch395f_set_recv_buf((uint8_t)sockfd, 30, 2);
}
ch395f_set_proto_type((uint8_t)sockfd, CH395F_PROTO_TYPE_UDP);
ch395f_set_sour_port((uint8_t)sockfd, p_sock->local_port);
/* DesIP=0xFFFFFFFF <20>?UDP Server 模式(接受任意来源) */
{
uint8_t broadcast[4] = {0xFF, 0xFF, 0xFF, 0xFF};
ch395f_set_des_ip((uint8_t)sockfd, broadcast);
}
ch395f_set_des_port((uint8_t)sockfd, 0);
status = ch395f_open_socket((uint8_t)sockfd);
if (status != CH395F_ERR_SUCCESS) {
s_net_errno = NET_ERR_BUSY;
return -1;
}
p_sock->state = NET_SOCK_STATE_UDP_OPEN;
} else {
p_sock->state = NET_SOCK_STATE_BOUND;
}
return 0;
}
/*
* 函数功能TCP Server 监听
*/
int net_listen(int sockfd, int backlog) {
net_sock_t *p_sock;
uint8_t status;
/* 参数检<E695B0>?*/
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
s_net_errno = NET_ERR_BADF;
return -1;
}
p_sock = &s_net_socks[sockfd];
if (!p_sock->in_use || p_sock->type != NET_SOCK_STREAM) {
s_net_errno = NET_ERR_INVAL;
return -1;
}
if (p_sock->state != NET_SOCK_STATE_BOUND &&
p_sock->state != NET_SOCK_STATE_CREATED) {
s_net_errno = NET_ERR_INVAL;
return -1;
}
/* 多连接模式:先为数据 Socket 设置协议类型、源端口和独立缓冲区<E586B2>? * 必须在监听话<E590AC>?Socket OPEN+LISTEN 之前配置<EFBC8C>?CH395F <20>? * 自动分配机制能扫描到所有可<E69C89>?Socket
* CH395F 根据源端口匹配、协议类<E8AEAE>?TCP、状<E38081>?CLOSED 查找可用 Socket */
for (int ds = NET_TCP_SERVER_DATA_SOCK_START; ds < NET_MAX_SOCKETS; ds++) {
uint8_t base = (uint8_t)(ds * 4);
ch395f_set_send_buf((uint8_t)ds, base, 2);
ch395f_set_recv_buf((uint8_t)ds, base + 2, 2);
/* <20>?CH395F 手册 9.2.6 节顺序:先设源端口,再设协议类型 */
ch395f_set_sour_port((uint8_t)ds, p_sock->local_port);
ch395f_set_proto_type((uint8_t)ds, CH395F_PROTO_TYPE_TCP);
s_net_socks[ds].in_use = 1;
s_net_socks[ds].state = NET_SOCK_STATE_TCP_ACCEPT;
s_net_socks[ds].type = NET_SOCK_STREAM;
s_net_socks[ds].ch395_sock = (uint8_t)ds;
s_net_socks[ds].send_ready = 1;
}
/* 最后配置监<E7BDAE>?Socket 并启动监<E58AA8>?*/
ch395f_set_send_buf((uint8_t)sockfd, 0, 2);
ch395f_set_recv_buf((uint8_t)sockfd, 2, 2);
ch395f_set_proto_type(sockfd, CH395F_PROTO_TYPE_TCP);
ch395f_set_sour_port(sockfd, p_sock->local_port);
status = ch395f_open_socket(sockfd);
if (status != CH395F_ERR_SUCCESS) {
s_net_errno = NET_ERR_BUSY;
return -1;
}
/* 启动 TCP 监听 */
ch395f_tcp_listen(sockfd);
p_sock->state = NET_SOCK_STATE_LISTENING;
for (int j = 0; j < NET_MAX_SOCKETS; j++) {
(void)ch395f_get_sock_int_status((uint8_t)j);
}
(void)ch395f_get_glob_int_status_all();
return 0;
}
/*
* 函数功能TCP Server 接受连接
*/
int net_accept(int sockfd, struct net_sockaddr *addr, int *addrlen) {
net_sock_t *p_listen_sock;
int i;
/* 参数检<E695B0>?*/
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
s_net_errno = NET_ERR_BADF;
return -1;
}
p_listen_sock = &s_net_socks[sockfd];
if (!p_listen_sock->in_use || p_listen_sock->state != NET_SOCK_STATE_LISTENING) {
s_net_errno = NET_ERR_INVAL;
return -1;
}
/* 轮询查找已建立连接的数据 Socket */
net_poll();
for (i = 0; i < p_listen_sock->data_sock_count; i++) {
int data_sock = p_listen_sock->data_socks[i];
net_sock_t *p_data_cb = &s_net_socks[data_sock];
if (p_data_cb->state == NET_SOCK_STATE_ESTABLISHED) {
/* 找到已建立连接的 Socket */
if (addr != NULL && addrlen != NULL) {
struct net_sockaddr_in *p_addr_in = (struct net_sockaddr_in *)addr;
p_addr_in->sin_family = NET_AF_INET;
p_addr_in->sin_port = net_htons(p_data_cb->remote_port);
p_addr_in->sin_addr.s_addr = p_data_cb->remote_ip;
*addrlen = sizeof(struct net_sockaddr_in);
}
return data_sock;
}
}
/* 没有新连<E696B0>?*/
s_net_errno = NET_ERR_WOULDBLOCK;
return -1;
}
/*
* 函数功能TCP Client 发起连接
*/
int net_connect(int sockfd, const struct net_sockaddr *addr, int addrlen) {
net_sock_t *p_sock;
const struct net_sockaddr_in *p_addr_in;
uint8_t status;
/* 参数检<E695B0>?*/
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
s_net_errno = NET_ERR_BADF;
return -1;
}
p_sock = &s_net_socks[sockfd];
if (!p_sock->in_use || p_sock->type != NET_SOCK_STREAM) {
s_net_errno = NET_ERR_INVAL;
return -1;
}
if (addr == NULL || addrlen < (int)sizeof(struct net_sockaddr_in)) {
s_net_errno = NET_ERR_INVAL;
return -1;
}
p_addr_in = (const struct net_sockaddr_in *)addr;
/* 保存远端地址 */
p_sock->remote_ip = p_addr_in->sin_addr.s_addr;
p_sock->remote_port = net_ntohs(p_addr_in->sin_port);
/* 转换 IP 为数组格式(低字节在前) */
p_sock->remote_ip_arr[0] = (uint8_t)(p_sock->remote_ip);
p_sock->remote_ip_arr[1] = (uint8_t)(p_sock->remote_ip >> 8);
p_sock->remote_ip_arr[2] = (uint8_t)(p_sock->remote_ip >> 16);
p_sock->remote_ip_arr[3] = (uint8_t)(p_sock->remote_ip >> 24);
/* 配置 CH395F Socket */
ch395f_set_proto_type(sockfd, CH395F_PROTO_TYPE_TCP);
ch395f_set_sour_port(sockfd, p_sock->local_port);
ch395f_set_des_ip(sockfd, p_sock->remote_ip_arr);
ch395f_set_des_port(sockfd, p_sock->remote_port);
status = ch395f_open_socket(sockfd);
if (status != CH395F_ERR_SUCCESS) {
s_net_errno = NET_ERR_BUSY;
return -1;
}
/* 发起 TCP 连接 */
ch395f_tcp_connect(sockfd);
p_sock->state = NET_SOCK_STATE_CONNECTING;
return 0;
}
/*
* 函数功能发送数据TCP<43>? */
int net_send(int sockfd, const void *buf, int len, int flags) {
net_sock_t *p_sock;
int sent = 0;
uint32_t tick_start;
/* 参数检<E695B0>?*/
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
s_net_errno = NET_ERR_BADF;
return -1;
}
p_sock = &s_net_socks[sockfd];
if (!p_sock->in_use || p_sock->state != NET_SOCK_STATE_ESTABLISHED) {
s_net_errno = NET_ERR_NOTCONN;
return -1;
}
if (buf == NULL || len <= 0) {
s_net_errno = NET_ERR_INVAL;
return -1;
}
tick_start = HAL_GetTick();
/* 分块发<E59D97>?*/
while (sent < len) {
int chunk = len - sent;
if (chunk > NET_SEND_BUF_SIZE) {
chunk = NET_SEND_BUF_SIZE;
}
/* 检查发送缓冲区是否空闲 */
if (!p_sock->send_ready) {
/* 超时检<E697B6>?*/
if (NET_SEND_TIMEOUT_MS > 0 &&
(HAL_GetTick() - tick_start) >= NET_SEND_TIMEOUT_MS) {
s_net_errno = NET_ERR_TIMEDOUT;
break;
}
/* 继续轮询 */
net_poll();
continue;
}
ch395f_write_send_buf(sockfd, (uint8_t *)buf + sent, (uint16_t)chunk);
p_sock->send_ready = 0;
sent += chunk;
p_sock->send_bytes += (uint32_t)chunk;
/* 短暂延时等待发送完<E98081>?*/
tick_start = HAL_GetTick();
while (!p_sock->send_ready) {
net_poll();
if (NET_SEND_TIMEOUT_MS > 0 &&
(HAL_GetTick() - tick_start) >= NET_SEND_TIMEOUT_MS) {
break;
}
}
}
return sent;
}
/*
* 函数功能接收数据TCP<43>? */
int net_recv(int sockfd, void *buf, int len, int flags) {
net_sock_t *p_sock;
uint16_t recv_len;
uint32_t tick_start;
/* 参数检<E695B0>?*/
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
s_net_errno = NET_ERR_BADF;
return -1;
}
p_sock = &s_net_socks[sockfd];
if (!p_sock->in_use) {
s_net_errno = NET_ERR_BADF;
return -1;
}
/* 检查连接状<E68EA5>?*/
if (p_sock->type == NET_SOCK_STREAM &&
p_sock->state != NET_SOCK_STATE_ESTABLISHED) {
s_net_errno = NET_ERR_NOTCONN;
return -1;
}
if (buf == NULL || len <= 0) {
s_net_errno = NET_ERR_INVAL;
return -1;
}
tick_start = HAL_GetTick();
while (1) {
net_poll();
recv_len = ch395f_get_recv_len(sockfd);
if (recv_len > 0) {
/* 有数据可<E68DAE>?*/
int read_len = (recv_len > (uint16_t)len) ? len : (int)recv_len;
ch395f_read_recv_buf(sockfd, (uint8_t *)buf, (uint16_t)read_len);
p_sock->recv_bytes += (uint32_t)read_len;
return read_len;
}
/* 非阻塞模式检<E5BC8F>?*/
if (flags & NET_MSG_DONTWAIT) {
s_net_errno = NET_ERR_WOULDBLOCK;
return -1;
}
/* 超时检<E697B6>?*/
if (NET_RECV_TIMEOUT_MS > 0 &&
(HAL_GetTick() - tick_start) >= NET_RECV_TIMEOUT_MS) {
s_net_errno = NET_ERR_TIMEDOUT;
return -1;
}
/* 连接已断开检<E5BC80>?*/
if (p_sock->state == NET_SOCK_STATE_TCP_ACCEPT) {
return 0; /* 对端关闭 */
}
}
}
/*
* 函数功能<EFBC9A>?UDP 数据
*/
int net_sendto(int sockfd, const void *buf, int len, int flags,
const struct net_sockaddr *dest_addr, int addrlen) {
net_sock_t *p_sock;
const struct net_sockaddr_in *p_addr_in;
int sent = 0;
uint32_t tick_start;
/* 参数检<E695B0>?*/
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
s_net_errno = NET_ERR_BADF;
return -1;
}
p_sock = &s_net_socks[sockfd];
if (!p_sock->in_use) {
s_net_errno = NET_ERR_BADF;
return -1;
}
if (buf == NULL || len <= 0) {
s_net_errno = NET_ERR_INVAL;
return -1;
}
/* UDP 模式:设置目标地址 */
if (dest_addr != NULL && addrlen >= (int)sizeof(struct net_sockaddr_in)) {
p_addr_in = (const struct net_sockaddr_in *)dest_addr;
/* 转换 IP 为数组格<E7BB84>?*/
uint8_t ip_arr[4];
uint32_t ip = p_addr_in->sin_addr.s_addr;
ip_arr[0] = (uint8_t)(ip);
ip_arr[1] = (uint8_t)(ip >> 8);
ip_arr[2] = (uint8_t)(ip >> 16);
ip_arr[3] = (uint8_t)(ip >> 24);
ch395f_set_des_ip(sockfd, ip_arr);
ch395f_set_des_port(sockfd, net_ntohs(p_addr_in->sin_port));
}
tick_start = HAL_GetTick();
/* 发送数<E98081>?*/
while (sent < len) {
int chunk = len - sent;
if (chunk > NET_SEND_BUF_SIZE) {
chunk = NET_SEND_BUF_SIZE;
}
/* 检查发送缓冲区 */
if (!p_sock->send_ready) {
if (NET_SEND_TIMEOUT_MS > 0 &&
(HAL_GetTick() - tick_start) >= NET_SEND_TIMEOUT_MS) {
s_net_errno = NET_ERR_TIMEDOUT;
break;
}
net_poll();
continue;
}
ch395f_write_send_buf(sockfd, (uint8_t *)buf + sent, (uint16_t)chunk);
p_sock->send_ready = 0;
sent += chunk;
p_sock->send_bytes += (uint32_t)chunk;
/* 等待发送完<E98081>?*/
tick_start = HAL_GetTick();
while (!p_sock->send_ready) {
net_poll();
if (NET_SEND_TIMEOUT_MS > 0 &&
(HAL_GetTick() - tick_start) >= NET_SEND_TIMEOUT_MS) {
break;
}
}
}
return sent;
}
/*
* 函数功能<EFBC9A>?UDP 数据
*/
int net_recvfrom(int sockfd, void *buf, int len, int flags,
struct net_sockaddr *src_addr, int *addrlen) {
net_sock_t *p_sock;
uint16_t recv_len;
uint32_t tick_start;
/* 参数检<E695B0>?*/
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
s_net_errno = NET_ERR_BADF;
return -1;
}
p_sock = &s_net_socks[sockfd];
if (!p_sock->in_use) {
s_net_errno = NET_ERR_BADF;
return -1;
}
if (buf == NULL || len <= 0) {
s_net_errno = NET_ERR_INVAL;
return -1;
}
tick_start = HAL_GetTick();
while (1) {
net_poll();
recv_len = ch395f_get_recv_len(sockfd);
if (recv_len > 0) {
/* UDP Server 模式:前 8 字节为固定格式IP + 端口 + 长度<E995BF>?*/
if (p_sock->type == NET_SOCK_DGRAM && recv_len >= 8) {
uint8_t header[8];
ch395f_read_recv_buf(sockfd, header, 8);
recv_len -= 8;
/* 填充来源地址 */
if (src_addr != NULL && addrlen != NULL &&
*addrlen >= (int)sizeof(struct net_sockaddr_in)) {
struct net_sockaddr_in *p_addr_in = (struct net_sockaddr_in *)src_addr;
p_addr_in->sin_family = NET_AF_INET;
/* CH395F UDP <20>? [0-1] reserved [2-3] src_port(LE) [4-7] src_ip */
p_addr_in->sin_port = net_htons((uint16_t)(header[2] | (header[3] << 8)));
p_addr_in->sin_addr.s_addr = ((uint32_t)header[4]) |
((uint32_t)header[5] << 8) |
((uint32_t)header[6] << 16) |
((uint32_t)header[7] << 24);
*addrlen = sizeof(struct net_sockaddr_in);
}
}
/* 读取数据 */
if (recv_len > 0) {
int read_len = (recv_len > (uint16_t)len) ? len : (int)recv_len;
ch395f_read_recv_buf(sockfd, (uint8_t *)buf, (uint16_t)read_len);
p_sock->recv_bytes += (uint32_t)read_len;
return read_len;
}
}
/* 非阻塞模式检<E5BC8F>?*/
if (flags & NET_MSG_DONTWAIT) {
s_net_errno = NET_ERR_WOULDBLOCK;
return -1;
}
/* 超时检<E697B6>?*/
if (NET_RECV_TIMEOUT_MS > 0 &&
(HAL_GetTick() - tick_start) >= NET_RECV_TIMEOUT_MS) {
s_net_errno = NET_ERR_TIMEDOUT;
return -1;
}
}
}
/*
* 函数功能<EFBC9A>?socket
*/
int net_close(int sockfd) {
net_sock_t *p_sock;
/* 参数检<E695B0>?*/
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
s_net_errno = NET_ERR_BADF;
return -1;
}
p_sock = &s_net_socks[sockfd];
if (!p_sock->in_use) {
s_net_errno = NET_ERR_BADF;
return -1;
}
/* 关闭 CH395F Socket */
ch395f_close_socket(sockfd);
/* 清零控制<E68EA7>?*/
memset(p_sock, 0, sizeof(net_sock_t));
return 0;
}
/*
* 函数功能注册事件回<E4BBB6>? */
int net_set_event_cb(int sockfd, net_event_cb_t cb, void *arg) {
net_sock_t *p_sock;
/* 参数检<E695B0>?*/
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
s_net_errno = NET_ERR_BADF;
return -1;
}
p_sock = &s_net_socks[sockfd];
if (!p_sock->in_use) {
s_net_errno = NET_ERR_BADF;
return -1;
}
p_sock->event_cb = cb;
p_sock->event_arg = arg;
return 0;
}
/*
* 函数功能<EFBC9A>?socket 最后错误码
*/
int net_get_errno(void) {
return s_net_errno;
}
/*
* 函数功能:将 IP 地址字符串转为网络字节序
*/
uint32_t net_inet_addr(const char *cp) {
uint32_t addr = 0;
uint32_t val;
int i;
if (cp == NULL) {
return 0;
}
for (i = 0; i < 4; i++) {
val = 0;
while (*cp >= '0' && *cp <= '9') {
val = val * 10 + (*cp - '0');
cp++;
}
addr |= (val << (i * 8));
if (*cp == '.') {
cp++;
}
}
return NET_htonl(addr);
}
/*
* 函数功能将网络字节<E5AD97>?IP 转为字符<E5AD97>? */
char *net_inet_ntoa(uint32_t addr, char *buf) {
uint32_t naddr = NET_ntohl(addr);
if (buf == NULL) {
return NULL;
}
sprintf(buf, "%lu.%lu.%lu.%lu",
(unsigned long)(naddr & 0xFF),
(unsigned long)((naddr >> 8) & 0xFF),
(unsigned long)((naddr >> 16) & 0xFF),
(unsigned long)((naddr >> 24) & 0xFF));
return buf;
}
/*
* 函数功能:端口字节序转换(主机序 -> 网络序)
*/
uint16_t net_htons(uint16_t hostshort) {
return NET_htons(hostshort);
}
/*
* 函数功能:端口字节序转换(网络序 -> 主机序)
*/
uint16_t net_ntohs(uint16_t netshort) {
return NET_ntohs(netshort);
}
/*
* 函数功能IP 地址字节序转换主机<E4B8BB>?-> 网络序)
*/
uint32_t net_htonl(uint32_t hostlong) {
return NET_htonl(hostlong);
}
/*
* 函数功能IP 地址字节序转换网络<E7BD91>?-> 主机序)
*/
uint32_t net_ntohl(uint32_t netlong) {
return NET_ntohl(netlong);
}
/*
* 私有函数实现<E5AE9E>? */
/*
* 函数功能分配空<E9858D>?Socket
* 返回值Socket 索引失败返<E8B4A5>?-1
*/
static int alloc_socket(void) {
int i;
for (i = 0; i < NET_MAX_SOCKETS; i++) {
if (!s_net_socks[i].in_use) {
return i;
}
}
return -1;
}
/*
* 函数功能处理连接事<E68EA5>? */
static void handle_connect_event(net_sock_t *p_sock) {
if (p_sock->state == NET_SOCK_STATE_LISTENING) {
/* 多连接模式:监听 Socket 收到 CONNECT 中断 = 有新连接被分配到数据 Socket
* Socket 0 自身保持 LISTENING不需要改变状<E58F98>?*/
fire_event(p_sock, NET_EVENT_CONNECTED);
}
else if (!p_sock->in_use) {
/* CH395F 自动打开的数<E79A84>?Socket多连接模式首次收到 CONNECT 中断 */
int sock_idx = (int)(p_sock - s_net_socks);
p_sock->ch395_sock = (uint8_t)sock_idx;
DBG_INFO("sock%d AUTO-OPENED, CONNECTED", p_sock->ch395_sock);
uint8_t remote[6];
ch395f_get_remot_ipp(p_sock->ch395_sock, remote);
memcpy(p_sock->remote_ip_arr, remote, 4);
p_sock->remote_ip = ((uint32_t)remote[0]) |
((uint32_t)remote[1] << 8) |
((uint32_t)remote[2] << 16) |
((uint32_t)remote[3] << 24);
p_sock->remote_port = (uint16_t)(remote[4] | (remote[5] << 8));
p_sock->in_use = 1;
p_sock->state = NET_SOCK_STATE_ESTABLISHED;
p_sock->send_ready = 1;
ch395f_set_keepalive_enable(p_sock->ch395_sock, 1);
fire_event(p_sock, NET_EVENT_CONNECTED);
}
else if (p_sock->state == NET_SOCK_STATE_CONNECTING) {
/* TCP Client 连接成功 */
uint8_t remote[6];
ch395f_get_remot_ipp(p_sock->ch395_sock, remote);
memcpy(p_sock->remote_ip_arr, remote, 4);
p_sock->remote_ip = ((uint32_t)remote[0]) |
((uint32_t)remote[1] << 8) |
((uint32_t)remote[2] << 16) |
((uint32_t)remote[3] << 24);
p_sock->remote_port = (uint16_t)(remote[4] | (remote[5] << 8));
p_sock->state = NET_SOCK_STATE_ESTABLISHED;
ch395f_set_keepalive_enable(p_sock->ch395_sock, 1);
fire_event(p_sock, NET_EVENT_CONNECTED);
}
else if (p_sock->state == NET_SOCK_STATE_TCP_ACCEPT) {
/* 数据 Socket 被分配了连接 */
DBG_INFO("data sock%d TCP_ACCEPT -> CONNECTED", p_sock->ch395_sock);
uint8_t remote[6];
ch395f_get_remot_ipp(p_sock->ch395_sock, remote);
memcpy(p_sock->remote_ip_arr, remote, 4);
p_sock->remote_ip = ((uint32_t)remote[0]) |
((uint32_t)remote[1] << 8) |
((uint32_t)remote[2] << 16) |
((uint32_t)remote[3] << 24);
p_sock->remote_port = (uint16_t)(remote[4] | (remote[5] << 8));
p_sock->state = NET_SOCK_STATE_ESTABLISHED;
p_sock->send_ready = 1;
ch395f_set_keepalive_enable(p_sock->ch395_sock, 1);
fire_event(p_sock, NET_EVENT_CONNECTED);
}
}
/*
* 函数功能:处理断开事件
* 函数说明CH395F <20>?DISCONNECT 中断后自动关<E58AA8>?Socket<EFBC88>?FUN_PARA_FLAG_SOCKET_CLOSE=0
* 必须重新 OPEN_SOCKET + TCP_LISTEN 才能接受新连<E696B0>? */
static void handle_disconnect_event(net_sock_t *p_sock) {
if (p_sock->state == NET_SOCK_STATE_LISTENING) {
DBG_ERROR("WARNING: listen sock%d got disconnect", p_sock->ch395_sock);
}
else if (p_sock->state == NET_SOCK_STATE_ESTABLISHED) {
/* CH395F 自动关闭<E585B3>?Socket恢复为未使用状<E794A8>?*/
DBG_INFO("sock%d DISCONNECTED, back to idle", p_sock->ch395_sock);
memset(p_sock->remote_ip_arr, 0, 4);
p_sock->remote_port = 0;
p_sock->send_ready = 1;
p_sock->state = NET_SOCK_STATE_TCP_ACCEPT;
fire_event(p_sock, NET_EVENT_DISCONNECTED);
} else if (p_sock->state == NET_SOCK_STATE_TCP_ACCEPT) {
memset(p_sock->remote_ip_arr, 0, 4);
p_sock->remote_port = 0;
p_sock->send_ready = 1;
} else {
/* 未预期的断开 */
DBG_ERROR("sock%d disconnect in state %d", p_sock->ch395_sock, p_sock->state);
fire_event(p_sock, NET_EVENT_DISCONNECTED);
}
}
/*
* 函数功能处理数据接收事<E694B6>? */
static void handle_recv_event(net_sock_t *p_sock) {
uint16_t recv_len = ch395f_get_recv_len(p_sock->ch395_sock);
if (recv_len > 0) {
fire_event(p_sock, NET_EVENT_DATA_RECEIVED);
}
}
/*
* 函数功能处理发送完成事<E68890>? */
static void handle_send_event(net_sock_t *p_sock) {
fire_event(p_sock, NET_EVENT_SEND_COMPLETE);
}
/*
* 函数功能处理超时事<E697B6>? * 函数说明CH395F <20>?TIMEOUT 中断后同样自动关<E58AA8>?Socket<65>? * 需要重新打开并恢复监<E5A48D>? */
static void handle_timeout_event(net_sock_t *p_sock) {
if (p_sock->state == NET_SOCK_STATE_CONNECTING) {
/* TCP Client 连接超时 */
DBG_ERROR("sock%d CONNECT TIMEOUT", p_sock->ch395_sock);
p_sock->state = NET_SOCK_STATE_CREATED;
}
else if (p_sock->state == NET_SOCK_STATE_ESTABLISHED) {
/* 多连接模式:数据 Socket 超时,恢复为 TCP_ACCEPT 等待新连<E696B0>?*/
DBG_INFO("sock%d TIMEOUT, back to ACCEPT", p_sock->ch395_sock);
memset(p_sock->remote_ip_arr, 0, 4);
p_sock->remote_port = 0;
p_sock->send_ready = 1;
p_sock->state = NET_SOCK_STATE_TCP_ACCEPT;
}
else if (p_sock->state == NET_SOCK_STATE_LISTENING) {
/* 监听超时(异常情况) */
DBG_ERROR("sock%d LISTEN TIMEOUT", p_sock->ch395_sock);
}
fire_event(p_sock, NET_EVENT_TIMEOUT);
}
/*
* 函数功能触发事件回<E4BBB6>? */
static void fire_event(net_sock_t *p_sock, net_event_t event) {
if (p_sock->event_cb != NULL) {
p_sock->event_cb(p_sock->ch395_sock, event, p_sock->event_arg);
}
}
/*
* 函数功能<EFBC9A>?IP 地址字符串为数组
*/
static void parse_ip_string(const char *str, uint8_t *ip_arr) {
uint32_t val;
int i;
if (str == NULL || ip_arr == NULL) {
return;
}
for (i = 0; i < 4; i++) {
val = 0;
while (*str >= '0' && *str <= '9') {
val = val * 10 + (*str - '0');
str++;
}
ip_arr[i] = (uint8_t)val;
if (*str == '.') {
str++;
}
}
}
/*
* 函数功能<EFBC9A>?Socket 控制块指针内部使用<E4BDBF>? */
net_sock_t *net_get_sock(int sockfd) {
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
return NULL;
}
if (!s_net_socks[sockfd].in_use) {
return NULL;
}
return &s_net_socks[sockfd];
}