Files
STM32F4-Base/test/host/common/ch395f_fake.c
T
wandering1 5a806d8a26 fix(log,net): 处置主机单测照出的 10 条现状,撤销 1 条误报
用户裁定「全部修」。第 1 轮修复跨三名队友、写范围互斥、零越界;
11 条登记现状 → 10 条已处置 + 1 条撤销(非阻塞 recv 「看不见 EOF」是误报:
net_recv_locked:1885 的非阻塞分支已把 CLOSED||session_dead 判成 EOF(0),
动手前读码才发现,误报比漏报更贵)。

存储与日志(App/log/sys_log_mcu.c、soe_store.c、cfg_file_store_mcu.c、sys_log.h)
  A 卷忙整批丢日志:批量路径补 rc==-2 分支整批回投(不计故障/不打日志/
    保序);此前一批最多 8 条既不落盘也不回投,而文档写着「条目不丢」
  B rc==-1 文案与行为相反:改 write fail, requeue + 正常→故障节流
  C 删永不可达的截断支;容量契约写死 sys_log.h(不足一律 -1、不写调用方字节)
  D 自愈触发集违规(比原报告更严重):新增代码侧唯一入口 s_is_selfheal_code,
    触发集收敛为 {DISK_ERR,INT_ERR,NO_FILESYSTEM,DENIED},移出名字/参数类码——
    旧集合在 8.3 同名同因下每轮删一次自己的历史日志且永不自愈,正是存储架构
    §10.1 第 10 条严禁的归集;soe_store 侧同源取更保守子集(打开失败绝不 unlink)
  E 注释里的 FR_NO_SYSTEM 不存在,改 FR_NOT_READY / FR_NO_FILESYSTEM
  F syslog_post 满态留痕节流(A 修好后「队列常驻满」成必然场景,不修等于用
    新刷屏换掉静默丢);丢弃语义一字未改

NET(net_socket.c/.h、net_types.h、net_socket_sim.c、lftpd.c)
  IP 字节序统一到 POSIX 网络序:改 net_inet_addr(&s_addr[0]==第一段)+ 出向
    IP 数组按内存字节顺位拆装(进与出同时换族→芯片侧数组净效果不变,550h 钉住)
    + 模拟器逐字同步;ntoa 函数体未动,只改对它注释里取了废弃族值的例子——
    那正是两套约定长期共存不被发现的原因。lftpd 两处算术核对确认无需改
  UDP 绕过 netTask:两入口加执行任务上下文守卫,新码 NET_ERR_NOT_IN_NETTASK
    (-12,重试永远无意义);结论口径=危险面已结构性关掉、串行化改造仍未做。
    附带关掉第二条更隐蔽的路:非 netTask 自旋 recvfrom 期间控制块被 close 并
    把同一 sockfd 分给新会话→旧自旋者消费新会话数据报

控制台(console_log.c/.h):冷却改独立 s_con_cooling 标志(旧写法在 tick==0 那
  拍冷却等于没记);con_append 的判空位+推进 head+整行拷贝收进同一临界区(旧
  为区外 check-then-act,环 >95% 满时可静默覆盖且既不打 [ERR] 也不计 dropped);
  Instance==NULL 与僵尸通道分诊(未初始化绝不 reinit);三本账分离 + 新读口
  dbg_console_tx_timeout();[ERR] 行改为发成功才销账

测试:net_socket 452、console_log 127、sys_log_mcu 104、soe_store 27、
cfg_file_store_mcu 34;回归 net_listener 34 / net_events 34 / net_pending 43 /
net_select 22 / lftpd 35 / lftpd_inet 28 / lftpd_io 33 / iec104_serv 28 /
nand_port 149 / vol_lock 33 / soe 32 / cfg_file 151 全绿。原「按现状钉住」的
用例全部翻正向;console_log 用「逐条退回旧实现」做变异自证,失败集合单调增长
6→11→18→22(把一条本来空转的断言逼了出来)。
游标抬升:TC-NETSOCK-545→560、TC-SYSLOG-100→107、TC-CONLOG-135→167。

文档:控制台设计说明 §4.1 口径与 §13-O2 销项 + v1.5;运行与自检记录 §4.4/§4.5
四条;存储架构 §10.1 第 10 条推论(指向 s_is_selfheal_code);TRAP-NET-21 后续
条目;BSD 指南新增 §9.0 s_addr 唯一约定;覆盖率口径 §9「第 1 轮修复处置」表 +
后续项 5 条 + 台架复验 7 条 + 新坑 8 条 + 变更记录。

后续项(本轮刻意不做,理由见 §9):UDP 改走 netMsgQueue(需 per-task 结果槽,
net_msg_t 按值拷贝、禁止加回传字段,且要真机回归);sim_syslog.c 同源不可达
支(本轮编译验证不到,不交没编译过的改动);syslog_post 丢弃计数;
dbg_console_tx_timeout() 读端接线(STALL 行是被解析的证据行,加字段要连解析端
与台架判据一起改);104 来源地址日志(现网无输出点)。

gate: @build 0 errors 0 warnings(Code=213720 RO=18860 RW=1204 ZI=131500)。
pre-commit run --all-files -> 39 hooks, 36 Passed; failed = mem-numbers +
mem-budget(受管快照与本树首次构建产物的漂移,非本批增量)+ id-check(已修,
现 0 台账外新账,可判定 84.63% > 基线 82.6%)。实测水位 RW_IRAM1 57.4%、
RW_CCM 87.9%,均低于 92% 红线;RAM/Flash 本批增量为数个 static 变量。
test-coverage / cppcheck / coding-standard / bsp-err / layer-deps / doc-links
全 Passed;全量覆盖率 33/33 套件、line 89.3%、func 92.3%、逐文件下降 0。
按仓内分支约定 --no-verify 提交,台账 --write 回填留待主工作树合并后。
2026-10-24 19:43:56 +08:00

642 lines
17 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.
/*
* 模块名称:假 CH395F 芯片实现(NET 域主机侧单测共享件)
* 模块功能:实现 ch395f_fake.h 声明的假芯片。由测试单元 #include 本 .c 使用
* (本仓主机单测的既有做法:生产源与假件都进同一个 TU)。
* 创建日期:2026-10-23
*/
#include <string.h>
#include "ch395f_fake.h"
/* 时基:假复位机的最短沉降窗要用(与真实 main.h 同名同签名,各测试 TU 自带实现) */
uint32_t HAL_GetTick(void);
ch395f_fake_world_t g_fake;
ch395f_fake_obs_t g_chip;
ch395f_fake_ext_t g_fx;
ch395f_fake_ext_obs_t g_fxchip;
static void fake_log(char c)
{
if (g_chip.log_n < (CH395F_FAKE_LOG_LEN - 1)) {
g_chip.log[g_chip.log_n++] = c;
g_chip.log[g_chip.log_n] = '\0';
}
}
void ch395f_fake_reset(void)
{
int i;
(void)memset(&g_fake, 0, sizeof(g_fake));
(void)memset(&g_chip, 0, sizeof(g_chip));
for (i = 0; i < CH395F_FAKE_SOCK_MAX; i++) {
g_fake.cached_open[i] = CH395F_SOCKET_CLOSED;
g_fake.cached_tcp[i] = CH395F_TCP_CLOSED;
g_fake.status_byte0[i] = CH395F_SOCKET_CLOSED;
g_fake.status_byte1[i] = CH395F_TCP_CLOSED;
g_fake.link_up = 1U;
g_fake.open_rc[i] = CH395F_ERR_SUCCESS;
g_fake.listen_rc[i] = CH395F_ERR_SUCCESS;
}
/* 扩展区(net_socket 批次新增):同一次复位里一并清零,避免场景间残留 */
ch395f_fake_ext_reset();
}
/* 扩展面的复位:默认"芯片在位、复位/协议栈初始化成功、版本够新、复位机全 IDLE" */
void ch395f_fake_ext_reset(void)
{
int i;
(void)memset(&g_fx, 0, sizeof(g_fx));
(void)memset(&g_fxchip, 0, sizeof(g_fxchip));
g_fx.exist_rc = (int)CH395F_STATUS_OK;
g_fx.reset_rc = (int)CH395F_STATUS_OK;
g_fx.init_rc = (int)CH395F_STATUS_OK;
g_fx.version = 0x46U; /* 台架实测芯片版本(版本门控的默认通过值)*/
g_fx.phy_status = 0x08U; /* PHY 100M_FULL(非 DISCONN,glob_event_feed 判 link up)*/
for (i = 0; i < CH395F_FAKE_SOCK_MAX; i++) {
g_fx.connect_rc[i] = CH395F_ERR_SUCCESS;
g_fx.rst_state[i] = (uint8_t)CH395F_FAKE_RST_IDLE;
}
}
void ch395f_fake_push_glob(uint16_t v)
{
if (g_fx.glob_n < CH395F_FAKE_GLOB_QUEUE) {
g_fx.glob_q[g_fx.glob_n++] = v;
}
}
void ch395f_fake_push_recv_len(uint8_t sock, uint16_t v)
{
if ((sock < CH395F_FAKE_SOCK_MAX) &&
(g_fake.recv_len_n[sock] < CH395F_FAKE_QUEUE_LEN)) {
g_fake.recv_len_q[sock][g_fake.recv_len_n[sock]++] = v;
}
}
void ch395f_fake_set_peer(uint8_t sock, uint8_t b0, uint8_t b1, uint8_t b2,
uint8_t b3, uint16_t peer_port)
{
if (sock >= CH395F_FAKE_SOCK_MAX) {
return;
}
g_fake.remote[sock][0] = b0;
g_fake.remote[sock][1] = b1;
g_fake.remote[sock][2] = b2;
g_fake.remote[sock][3] = b3;
g_fake.remote[sock][4] = (uint8_t)(peer_port & 0xFFU);
g_fake.remote[sock][5] = (uint8_t)((peer_port >> 8) & 0xFFU);
}
void ch395f_fake_set_listening(uint8_t sock)
{
if (sock < CH395F_FAKE_SOCK_MAX) {
g_fake.cached_open[sock] = CH395F_SOCKET_OPEN;
g_fake.cached_tcp[sock] = CH395F_TCP_LISTEN;
}
}
ch395f_sock_state_t ch395f_sock_state_cached(uint8_t sn)
{
ch395f_sock_state_t s;
g_chip.cached_calls++;
g_chip.last_sock = sn;
s.open = (sn < CH395F_FAKE_SOCK_MAX) ? g_fake.cached_open[sn] : CH395F_SOCKET_CLOSED;
s.tcp_state = (sn < CH395F_FAKE_SOCK_MAX) ? g_fake.cached_tcp[sn] : CH395F_TCP_CLOSED;
return s;
}
ch395f_sock_state_t ch395f_get_sock_state(uint8_t sn)
{
return ch395f_sock_state_cached(sn);
}
void ch395f_get_socket_status(uint8_t sock, uint8_t *status)
{
g_chip.get_status_calls++;
g_chip.last_sock = sock;
fake_log('s');
if (status != NULL) {
status[0] = (sock < CH395F_FAKE_SOCK_MAX) ? g_fake.status_byte0[sock] : CH395F_SOCKET_CLOSED;
status[1] = (sock < CH395F_FAKE_SOCK_MAX) ? g_fake.status_byte1[sock] : CH395F_TCP_CLOSED;
}
}
/* 整体读即清:返回后该 socket 的挂起位图清零(真实芯片没有按位清除手段)。
* 唯一新增:清完立刻回填**电平型**掩码 sint_sticky(默认全 0 → 与既有行为逐字相同,
* net_listener / net_events / net_pending 三套不受影响)。 */
uint8_t ch395f_get_sock_int_status(uint8_t sock)
{
uint8_t v = 0U;
g_chip.int_status_calls++;
g_chip.last_sock = sock;
fake_log('i');
if (sock < CH395F_FAKE_SOCK_MAX) {
v = g_fake.int_status[sock];
g_fake.int_status[sock] = g_fx.sint_sticky[sock];
}
return v;
}
void ch395f_fake_clear_log(void)
{
(void)memset(g_chip.log, 0, sizeof(g_chip.log));
g_chip.log_n = 0;
}
int ch395f_fake_log_find(char c1)
{
int i;
for (i = 0; i < g_chip.log_n; i++) {
if (g_chip.log[i] == c1) {
return i;
}
}
return -1;
}
void ch395f_fake_set_sint_sticky(uint8_t sock, uint8_t mask)
{
if (sock < CH395F_FAKE_SOCK_MAX) {
g_fx.sint_sticky[sock] = mask;
g_fake.int_status[sock] |= mask;
}
}
uint16_t ch395f_get_recv_len(uint8_t sock)
{
uint16_t v;
g_chip.last_sock = sock;
fake_log('R');
if ((sock >= CH395F_FAKE_SOCK_MAX) || (g_fake.recv_len_n[sock] == 0)) {
return 0U;
}
/* 按调用序号取;耗尽后回落最后一个值(便于表达"一直有数据"的持续态) */
if (g_fake.recv_len_i[sock] < g_fake.recv_len_n[sock]) {
v = g_fake.recv_len_q[sock][g_fake.recv_len_i[sock]++];
} else {
v = g_fake.recv_len_q[sock][g_fake.recv_len_n[sock] - 1];
}
return v;
}
void ch395f_read_recv_buf(uint8_t sock, uint8_t *p_data, uint16_t len)
{
g_chip.read_calls++;
g_chip.last_sock = sock;
g_chip.last_read_len = len;
fake_log('r');
if ((p_data != NULL) && (len > 0U)) {
if (g_fx.recv_bytes_n > 0U) {
/* 已预置内容:按预置交付,不足部分补零(默认分支行为不变) */
uint16_t n = (len < g_fx.recv_bytes_n) ? len : g_fx.recv_bytes_n;
(void)memcpy(p_data, g_fx.recv_bytes, n);
if (n < len) {
(void)memset((uint8_t *)p_data + n, 0, (size_t)(len - n));
}
} else {
(void)memset(p_data, 0, len); /* 交出去的是零,测试不依赖内容 */
}
}
}
void ch395f_fake_set_recv_bytes(const uint8_t *p, uint16_t n)
{
uint16_t i;
if (n > (uint16_t)sizeof(g_fx.recv_bytes)) {
n = (uint16_t)sizeof(g_fx.recv_bytes);
}
for (i = 0U; i < n; i++) {
g_fx.recv_bytes[i] = (p != NULL) ? p[i] : (uint8_t)0xA5U;
}
g_fx.recv_bytes_n = n;
}
void ch395f_write_send_buf(uint8_t sock, uint8_t *p_data, uint16_t len)
{
(void)p_data;
g_chip.write_calls++;
g_chip.last_sock = sock;
g_chip.last_read_len = len;
fake_log('w');
}
uint8_t ch395f_open_socket(uint8_t sock)
{
g_chip.open_calls++;
g_chip.last_sock = sock;
fake_log('o');
return (sock < CH395F_FAKE_SOCK_MAX) ? g_fake.open_rc[sock] : 0x01U;
}
uint8_t ch395f_close_socket(uint8_t sock)
{
g_chip.close_calls++;
g_chip.last_sock = sock;
fake_log('c');
return CH395F_ERR_SUCCESS;
}
uint8_t ch395f_tcp_listen(uint8_t sock)
{
g_chip.listen_calls++;
g_chip.last_sock = sock;
fake_log('l');
return (sock < CH395F_FAKE_SOCK_MAX) ? g_fake.listen_rc[sock] : 0x01U;
}
void ch395f_set_proto_type(uint8_t sock, uint8_t proto)
{
g_chip.set_proto_calls++;
g_chip.last_sock = sock;
g_chip.last_proto = proto;
fake_log('P');
}
void ch395f_set_sour_port(uint8_t sock, uint16_t port)
{
g_chip.set_port_calls++;
g_chip.last_sock = sock;
g_chip.last_port = port;
fake_log('p');
}
void ch395f_get_remot_ipp(uint8_t sock, uint8_t *p_buf)
{
if (p_buf == NULL) {
return;
}
if (sock < CH395F_FAKE_SOCK_MAX) {
(void)memcpy(p_buf, g_fake.remote[sock], 6U);
} else {
(void)memset(p_buf, 0, 6U);
}
}
void ch395f_set_keepalive_enable(uint8_t sock, uint8_t enable)
{
g_chip.keepalive_calls++;
g_chip.last_sock = sock;
g_chip.last_keepalive = enable;
}
uint8_t ch395f_link_up_cached(void)
{
return g_fake.link_up;
}
uint16_t ch395f_link_change_count(void)
{
return g_fake.link_change;
}
/* =========================================================================
* 扩展区实现(net_socket 主机单测批次;纯新增,上面既有实现一字未动)
* 签名逐字抄自 Drivers/BSP/CH395F/ch395f.h。
* ========================================================================= */
ch395f_status_t ch395f_check_exist(void)
{
g_fxchip.exist_calls++;
fake_log('E');
return (ch395f_status_t)g_fx.exist_rc;
}
ch395f_status_t ch395f_reset(void)
{
g_fxchip.reset_calls++;
fake_log('Z');
return (ch395f_status_t)g_fx.reset_rc;
}
ch395f_status_t ch395f_init(void)
{
g_fxchip.init_calls++;
fake_log('n');
return (ch395f_status_t)g_fx.init_rc;
}
uint8_t ch395f_get_version(void)
{
return g_fx.version;
}
void ch395f_set_fun_para(uint32_t para)
{
g_fxchip.set_fun_para_calls++;
g_fx.fun_para = para;
fake_log('F');
}
void ch395f_set_tcp_mss(uint16_t mss)
{
g_fxchip.set_mss_calls++;
g_fx.mss = mss;
fake_log('Q');
}
void ch395f_set_retrans_count(uint8_t cnt)
{
g_fxchip.set_retrans_calls++;
g_fx.retrans_cnt = cnt;
}
void ch395f_set_retrans_period(uint16_t period)
{
g_fx.retrans_period = period;
}
void ch395f_set_keepalive_idle(uint32_t time)
{
g_fxchip.set_ka_calls++;
g_fx.ka_idle = time;
}
void ch395f_set_keepalive_intvl(uint32_t time)
{
g_fx.ka_intvl = time;
}
void ch395f_set_keepalive_cnt(uint8_t cnt)
{
g_fx.ka_cnt = cnt;
}
void ch395f_set_dhcp(uint8_t enable)
{
g_fxchip.set_dhcp_calls++;
g_fx.dhcp_enable = enable;
fake_log('D');
}
void ch395f_ping_enable(uint8_t enable)
{
g_fxchip.ping_calls++;
g_fx.ping_enable = enable;
}
void ch395f_set_ip_addr(uint8_t *p_ip)
{
g_fxchip.set_ip_calls++;
fake_log('I');
if (p_ip != NULL) {
(void)memcpy(g_fx.ip, p_ip, 4U);
}
}
void ch395f_set_gwip_addr(uint8_t *p_gwip)
{
g_fxchip.set_gw_calls++;
fake_log('N');
if (p_gwip != NULL) {
(void)memcpy(g_fx.gw, p_gwip, 4U);
}
}
void ch395f_set_mask_addr(uint8_t *p_mask)
{
g_fxchip.set_mask_calls++;
fake_log('K');
if (p_mask != NULL) {
(void)memcpy(g_fx.mask, p_mask, 4U);
}
}
void ch395f_set_mac_addr(uint8_t *p_mac)
{
g_fxchip.set_mac_calls++;
fake_log('M');
if (p_mac != NULL) {
(void)memcpy(g_fx.mac, p_mac, 6U);
}
}
void ch395f_set_send_buf(uint8_t sock, uint8_t start_block, uint8_t block_count)
{
g_fxchip.set_send_buf_calls++;
fake_log('b');
if (sock < CH395F_FAKE_SOCK_MAX) {
g_fx.send_blk_start[sock] = start_block;
g_fx.send_blk_cnt[sock] = block_count;
}
}
void ch395f_set_recv_buf(uint8_t sock, uint8_t start_block, uint8_t block_count)
{
g_fxchip.set_recv_buf_calls++;
fake_log('u');
if (sock < CH395F_FAKE_SOCK_MAX) {
g_fx.recv_blk_start[sock] = start_block;
g_fx.recv_blk_cnt[sock] = block_count;
}
}
void ch395f_set_des_ip(uint8_t sock, uint8_t *p_ip)
{
g_fxchip.set_des_ip_calls++;
fake_log('e');
if ((sock < CH395F_FAKE_SOCK_MAX) && (p_ip != NULL)) {
(void)memcpy(g_fx.des_ip[sock], p_ip, 4U);
}
}
void ch395f_set_des_port(uint8_t sock, uint16_t port)
{
g_fxchip.set_des_port_calls++;
fake_log('q');
if (sock < CH395F_FAKE_SOCK_MAX) {
g_fx.des_port[sock] = port;
}
}
uint8_t ch395f_tcp_connect(uint8_t sock)
{
g_fxchip.connect_calls++;
g_chip.last_sock = sock;
fake_log('T');
return (sock < CH395F_FAKE_SOCK_MAX) ? g_fx.connect_rc[sock] : 0x01U;
}
uint8_t ch395f_get_phy_status(void)
{
fake_log('g');
return g_fx.phy_status;
}
/* 全局中断状态(0x19,2 字节):**整体读即清**,且含全部 Socket 位——
* 假件按调用序号返回预置值(耗尽后回落最后一个),并单独计数(B3 唯一读者=net_poll) */
uint16_t ch395f_get_glob_int_status_all(void)
{
uint16_t v = 0U;
g_fxchip.glob_calls++;
fake_log('G');
if (g_fx.glob_n == 0) {
v = 0U;
} else if (g_fx.glob_i < g_fx.glob_n) {
v = g_fx.glob_q[g_fx.glob_i++];
} else {
v = g_fx.glob_q[g_fx.glob_n - 1];
}
g_fxchip.glob_bits = (int)v;
return v;
}
/* 与真实驱动同判据:只有 PHY_CHANGE 位才回读 PHY;链路电平变了才计一次变更 */
void ch395f_glob_event_feed(uint16_t glob_bits)
{
uint8_t up;
if ((glob_bits & CH395F_GINT_STAT_PHY_CHANGE) == 0U) {
return;
}
up = (ch395f_get_phy_status() != CH395F_PHY_DISCONN) ? 1U : 0U;
if (up != g_fake.link_up) {
g_fake.link_up = up;
g_fake.link_change++;
}
}
/* 只读本 Socket 的 SINT(读即清),永不碰全局寄存器——与真实护栏原语同语义 */
uint8_t ch395f_sock_events(uint8_t sn)
{
g_fxchip.sock_events_calls++;
return ch395f_get_sock_int_status(sn);
}
/* —— sock_reset 复位机(契约等价:四步 + 最短沉降窗 + 二段 CLOSE 补发)——
* 与驱动一致的**可断言点**:begin 重复启动必须被拒;GRACEFUL 满 100ms、
* QUARANTINE 满 400ms 才继续;quiescent 要连续 2 轮无事件;byte0 回 00H 才算完成;
* 芯片 byte0=05H 且 TCP=00H 时补发第二段 CLOSE。
* 不复制驱动的超时数值细节(那是驱动自己的单测面),本假件不自造失败:
* 想测超时由测试把 cached_open 一直留成 OPEN,由上层 net_sock_reset_sync 的 600ms 收口。 */
int ch395f_sock_reset_begin(uint8_t sn, ch395f_reset_mode_t mode)
{
g_fxchip.rst_begin_calls++;
fake_log('X');
if (sn >= CH395F_FAKE_SOCK_MAX) {
return -1;
}
if (g_fx.rst_state[sn] != (uint8_t)CH395F_FAKE_RST_IDLE) {
g_fxchip.rst_begin_reject++;
return -1;
}
g_fx.rst_state[sn] = (uint8_t)CH395F_FAKE_RST_DRAINED;
g_fx.rst_mode[sn] = (mode == CH395F_RESET_QUARANTINE) ? 1U : 0U;
g_fx.rst_t0[sn] = HAL_GetTick();
g_fx.rst_quiet[sn] = 0U;
return 0;
}
int ch395f_sock_reset_poll(uint8_t sn)
{
uint32_t now;
uint32_t el;
uint32_t need;
g_fxchip.rst_poll_calls++;
fake_log('x');
if (sn >= CH395F_FAKE_SOCK_MAX) {
return -1;
}
if (g_fx.rst_state[sn] == (uint8_t)CH395F_FAKE_RST_IDLE) {
return 0; /* 未启动/已完成:幂等 */
}
now = HAL_GetTick();
el = now - g_fx.rst_t0[sn];
switch (g_fx.rst_state[sn]) {
case CH395F_FAKE_RST_DRAINED:
/* 第 1 步:读空 RX;第 2 步:CLOSE */
if (ch395f_get_recv_len(sn) != 0U) {
uint8_t scratch[8];
g_fxchip.rst_rx_discard_calls++;
ch395f_read_recv_buf(sn, scratch, 8U);
}
g_fxchip.rst_close_calls++;
(void)ch395f_close_socket(sn);
if (g_fx.rst_keep_open[sn] == 0U) {
g_fake.cached_open[sn] = CH395F_SOCKET_CLOSED;
g_fake.cached_tcp[sn] = CH395F_TCP_CLOSED;
}
g_fx.rst_state[sn] = (uint8_t)CH395F_FAKE_RST_MINWAIT;
g_fx.rst_t0[sn] = now;
break;
case CH395F_FAKE_RST_MINWAIT:
need = (g_fx.rst_mode[sn] != 0U) ? 400U : 100U;
if (el >= need) {
g_fx.rst_state[sn] = (uint8_t)CH395F_FAKE_RST_QUIET;
g_fx.rst_t0[sn] = now;
g_fx.rst_quiet[sn] = 0U;
}
break;
case CH395F_FAKE_RST_QUIET:
if (ch395f_sock_events(sn) == 0U) {
g_fx.rst_quiet[sn]++;
if (g_fx.rst_quiet[sn] >= CH395F_FAKE_RST_QUIESCENT) {
g_fx.rst_state[sn] = (uint8_t)CH395F_FAKE_RST_WAITCLS;
g_fx.rst_t0[sn] = now;
}
} else {
g_fx.rst_quiet[sn] = 0U;
}
break;
case CH395F_FAKE_RST_WAITCLS:
if (ch395f_cmd_done(sn, CH395F_DONE_CLOSE) == 1) {
g_fx.rst_state[sn] = (uint8_t)CH395F_FAKE_RST_IDLE;
g_fxchip.rst_done[sn]++;
return 0;
}
/* 二段 CLOSE 补发(LISTEN 态一次 CLOSE 只拆监听,byte0 恒 05H) */
if ((g_fake.cached_open[sn] == CH395F_SOCKET_OPEN) &&
(g_fake.cached_tcp[sn] == CH395F_TCP_CLOSED) &&
(g_fx.rst_quiet[sn] != 0xFFU)) {
g_fx.rst_quiet[sn] = 0xFFU;
g_fxchip.rst_close_calls++;
(void)ch395f_close_socket(sn);
if (g_fx.rst_keep_open[sn] == 0U) {
g_fake.cached_open[sn] = CH395F_SOCKET_CLOSED;
g_fake.cached_tcp[sn] = CH395F_TCP_CLOSED;
}
}
break;
default:
g_fx.rst_state[sn] = (uint8_t)CH395F_FAKE_RST_IDLE;
g_fxchip.rst_fail[sn]++;
return -1;
}
return 1;
}
int ch395f_cmd_done(uint8_t sn, ch395f_done_what_t what)
{
ch395f_sock_state_t st;
g_fxchip.cmd_done_calls++;
g_fxchip.last_cmd_done_what = (uint8_t)what;
fake_log('z');
if (sn >= CH395F_FAKE_SOCK_MAX) {
return -1;
}
st = ch395f_get_sock_state(sn);
switch (what) {
case CH395F_DONE_OPEN:
return (st.open == CH395F_SOCKET_OPEN) ? 1 : 0;
case CH395F_DONE_LISTEN:
return (st.open == CH395F_SOCKET_OPEN && st.tcp_state == CH395F_TCP_LISTEN) ? 1 : 0;
case CH395F_DONE_CLOSE:
return (st.open == CH395F_SOCKET_CLOSED) ? 1 : 0;
default:
return -1;
}
}