/*
 * 模块名称：CH395F SPI Ethernet Protocol Stack Driver
 * 模块功能：CH395F 以太网协议栈芯片 SPI 驱动，提供网络初始化、Socket 管理、
 *          数据收发等功能。命令码参考 CH395 手册 v2.2 Table 5-1
 * 适用平台：STM32F4 系列（SPI2 接口）
 * 作者：王建锋
 * 创建日期：2026-06-06
 * 修改记录：
 *     2026-06-06  王建锋  创建初始版本，按代码规范重构
 */

#ifndef __CH395F_H
#define __CH395F_H

/*
 * 头文件包含区 - 仅包含本模块必需的头文件
 */

#ifdef __cplusplus
extern "C" {
#endif

#include "main.h"

/*
 * 宏定义区 - SPI 命令码（来自 CH395 手册 v2.2 Table 5-1）
 */

/* 无输入数据，无输出数据 */
#define CH395F_CMD_RESET_ALL             0x05U
#define CH395F_CMD_ENTER_SLEEP           0x03U

/* 无输入数据，1 字节输出 */
#define CH395F_CMD_GET_IC_VER            0x01U
#define CH395F_CMD_GET_CMD_STATUS        0x2CU
#define CH395F_CMD_GET_GLOB_INT_STATUS   0x29U
#define CH395F_CMD_GET_GLOB_INT_STATUS_ALL 0x19U
#define CH395F_CMD_GET_UNREACH_IPPT      0x28U
#define CH395F_CMD_GET_PHY_STATUS        0x26U
#define CH395F_CMD_GET_DHCP_STATUS       0x42U

/* 无输入数据，6 字节输出 */
#define CH395F_CMD_GET_MAC_ADDR          0x40U

/* 无输入数据，20 字节输出 */
#define CH395F_CMD_GET_IP_INF            0x43U

/* 1 字节输入，无输出数据 */
#define CH395F_CMD_SET_PHY               0x20U
#define CH395F_CMD_PING_ENABLE           0x3FU
#define CH395F_CMD_DHCP_ENABLE           0x41U
#define CH395F_CMD_SET_RETRAN_COUNT      0x2AU

/* 1 字节输入，1 字节输出 */
#define CH395F_CMD_CHECK_EXIST           0x06U
#define CH395F_CMD_SET_FUN_PARA          0x55U

/* 2 字节输入，无输出数据 */
#define CH395F_CMD_SET_TTL               0x51U
#define CH395F_CMD_SET_ARP               0x44U

/* 3 字节输入，无输出数据 */
#define CH395F_CMD_SET_BAUDRATE          0x02U
#define CH395F_CMD_SET_RETRAN_PERIOD     0x2BU

/* 4 字节输入，无输出数据 */
#define CH395F_CMD_SET_IP_ADDR           0x22U
#define CH395F_CMD_SET_GWIP_ADDR         0x23U
#define CH395F_CMD_SET_MASK_ADDR         0x24U

/* 6 字节输入，无输出数据 */
#define CH395F_CMD_SET_MAC_ADDR          0x21U

/* 初始化命令（仅写入，执行时间较长） */
#define CH395F_CMD_INIT_CH395            0x27U

/* Socket 命令 */
/* 1 字节输入（socket 索引），无输出数据 */
#define CH395F_CMD_CLOSE_SOCKET_SN       0x3DU
#define CH395F_CMD_OPEN_SOCKET_SN        0x35U
#define CH395F_CMD_TCP_LISTEN_SN         0x36U
#define CH395F_CMD_TCP_CONNECT_SN        0x37U
#define CH395F_CMD_TCP_DISCONNECT_SN     0x38U
#define CH395F_CMD_CLEAR_RECV_BUF_SN     0x2EU

/* 1 字节输入，1 字节输出（socket 索引） */
#define CH395F_CMD_GET_INT_STATUS_SN     0x30U
#define CH395F_CMD_GET_SOCKET_STATUS_SN  0x2FU

/* 1 字节输入，2 字节输出 */
#define CH395F_CMD_GET_RECV_LEN_SN       0x3BU

/* 2 字节输入，无输出数据 */
#define CH395F_CMD_SET_PROTO_TYPE_SN     0x34U
#define CH395F_CMD_SET_IPRAW_PRO_SN      0x3EU

/* 3 字节输入，无输出数据 */
#define CH395F_CMD_SET_DES_PORT_SN       0x32U
#define CH395F_CMD_SET_SOUR_PORT_SN      0x33U

/* 5 字节输入，无输出数据（socket + 4 字节 IP） */
#define CH395F_CMD_SET_IP_ADDR_SN        0x31U

/* 1 字节输入，6 字节输出（socket 索引 -> 远程 IP + 端口） */
#define CH395F_CMD_GET_REMOT_IPP_SN      0x2DU

/* 3 字节输入 + 数据输出（socket + 长度） */
#define CH395F_CMD_READ_RECV_BUF_SN      0x3CU

/* 3 字节输入 + 数据输入（socket + 长度 + 数据） */
#define CH395F_CMD_WRITE_SEND_BUF_SN     0x39U

/*
 * SPI DMA 事务限制
 * CH395F_SPI_DMA_MAX_PAYLOAD: 单次 DMA 事务最大有效载荷（总缓冲 - 4 字节命令头）
 * 注意: CH395F 内部 socket 接收缓冲默认 4096B，DMA 缓冲需至少 4100 以一次性读空
 */
#define CH395F_SPI_DMA_BUF_SIZE         4100U
#define CH395F_SPI_DMA_MAX_PAYLOAD      (CH395F_SPI_DMA_BUF_SIZE - 4U)

/* 其他命令 */
#define CH395F_CMD_SET_TCP_MSS           0x50U
#define CH395F_CMD_SET_RECV_BUF          0x52U
#define CH395F_CMD_SET_SEND_BUF          0x53U
#define CH395F_CMD_SET_KEEPALIVE_IDLE    0x56U
#define CH395F_CMD_SET_KEEPALIVE_INTVL   0x57U
#define CH395F_CMD_SET_KEEPALIVE_CNT     0x58U
#define CH395F_CMD_SET_KEEPALIVE_SN      0x59U
#define CH395F_CMD_EEPROM_ERASE          0xE9U
#define CH395F_CMD_EEPROM_WRITE          0xEAU
#define CH395F_CMD_EEPROM_READ           0xEBU
#define CH395F_CMD_READ_GPIO_REG         0xECH
#define CH395F_CMD_WRITE_GPIO_REG        0xEDU

/*
 * CH395 命令执行状态码（CMD_GET_CMD_STATUS 返回值，与芯片手册一致）
 */
#define CH395F_ERR_SUCCESS               0x00U  /* 成功 */
#define CH395F_ERR_BUSY                  0x10U  /* 忙，命令正在执行 */
#define CH395F_ERR_MEM                   0x11U  /* 内存管理错误 */
#define CH395F_ERR_BUF                   0x12U  /* 缓冲区错误 */
#define CH395F_ERR_TIMEOUT               0x13U  /* 超时 */
#define CH395F_ERR_RTE                   0x14U  /* 路由错误 */
#define CH395F_ERR_ABRT                  0x15U  /* 连接中止 */
#define CH395F_ERR_RST                   0x16U  /* 连接复位 */
#define CH395F_ERR_CLSD                  0x17U  /* 连接关闭 */
#define CH395F_ERR_CONN                  0x18U  /* 无连接 */
#define CH395F_ERR_VAL                   0x19U  /* 值错误 */
#define CH395F_ERR_ARG                   0x1AH  /* 参数错误 */
#define CH395F_ERR_USE                   0x1BH  /* 已被使用 */
#define CH395F_ERR_IF                    0x1CH  /* MAC 错误 */
#define CH395F_ERR_ISCONN                0x1DH  /* 已连接 */
#define CH395F_ERR_OPEN                  0x20U  /* 已打开 */
#define CH395F_CMD_RET_ABORT             0x5FU  /* 命令中止（来自官方库） */
#define CH395F_ERR_UNKNOW                0xFAU  /* 未知错误」 */

/*
 * PHY 状态码
 */
#define CH395F_PHY_DISCONN               0x01U  /* PHY 断开连接 */
#define CH395F_PHY_10M_FULL              0x02U  /* 10M 全双工 */
#define CH395F_PHY_10M_HALF              0x04U  /* 10M 半双工 */
#define CH395F_PHY_100M_FULL             0x08U  /* 100M 全双工 */
#define CH395F_PHY_100M_HALF             0x10U  /* 100M 半双工 */
#define CH395F_PHY_AUTO_NEGOTIATE        0x20U  /* 自动协商 */

/*
 * 功能参数标志位（CMD_SET_FUN_PARA）
 */
#define CH395F_FUN_PARA_TCP_SERVER       (1UL << 1)   /* TCP Server 多连接模式 */
#define CH395F_FUN_PARA_SOCKET_CLOSE     (1UL << 3)   /* Socket 关闭控制（0=芯片自动，1=外部控制） */
#define CH395F_FUN_PARA_DISABLE_SEND_OK  (1UL << 4)   /* 禁用 SEND_OK 中断 */

/*
 * 协议类型
 */
#define CH395F_PROTO_TYPE_IP_RAW         0x00U
#define CH395F_PROTO_TYPE_MAC_RAW        0x01U
#define CH395F_PROTO_TYPE_UDP            0x02U
#define CH395F_PROTO_TYPE_TCP            0x03U

/*
 * Socket 状态
 */
#define CH395F_SOCKET_CLOSED             0x00U
#define CH395F_SOCKET_OPEN               0x05U

/*
 * TCP 状态
 */
#define CH395F_TCP_CLOSED                0x00U
#define CH395F_TCP_LISTEN                0x01U
#define CH395F_TCP_SYN_SENT              0x02U
#define CH395F_TCP_SYN_RCVD              0x03U
#define CH395F_TCP_ESTABLISHED           0x04U
#define CH395F_TCP_FIN_WAIT_1            0x05U
#define CH395F_TCP_FIN_WAIT_2            0x06U
#define CH395F_TCP_CLOSE_WAIT            0x07U
#define CH395F_TCP_CLOSING               0x08U
#define CH395F_TCP_LAST_ACK              0x09U
#define CH395F_TCP_TIME_WAIT             0x0AU

/*
 * 全局中断状态位（CMD_GET_GLOB_INT_STATUS 1字节版，仅Socket 0~3）
 */
#define CH395F_GINT_STAT_UNREACH         0x01U
#define CH395F_GINT_STAT_IP_CONFLI       0x02U
#define CH395F_GINT_STAT_PHY_CHANGE      0x04U
#define CH395F_GINT_STAT_DHCP            0x08U
#define CH395F_GINT_STAT_SOCK0           0x10U
#define CH395F_GINT_STAT_SOCK1           0x20U
#define CH395F_GINT_STAT_SOCK2           0x40U
#define CH395F_GINT_STAT_SOCK3           0x80U

/*
 * 全局中断状态位（CMD_GET_GLOB_INT_STATUS_ALL 2字节版，支持Socket 0~7）
 * 低字节高字节分别定义
 */
#define CH395F_GINT_STAT_SOCK4           0x0100U
#define CH395F_GINT_STAT_SOCK5           0x0200U
#define CH395F_GINT_STAT_SOCK6           0x0400U
#define CH395F_GINT_STAT_SOCK7           0x0800U
#define CH395F_GINT_STAT_DHCPV6          0x8000U

/*
 * Socket 中断状态位（CMD_GET_INT_STATUS_SN 返回值，来自手册表5-x）
 */
#define CH395F_SINT_STAT_SENBUF_FREE     0x01U  /* bit0: 发送缓冲区空闲 */
#define CH395F_SINT_STAT_SEND_OK         0x02U  /* bit1: 发送成功 */
#define CH395F_SINT_STAT_RECV_OK         0x04U  /* bit2: 接收缓冲区非空 */
#define CH395F_SINT_STAT_CONNECT         0x08U  /* bit3: TCP 连接成功 */
#define CH395F_SINT_STAT_DISCONNECT      0x10U  /* bit4: TCP 连接断开 */
#define CH395F_SINT_STAT_DISCARD         0x20U  /* bit5: 保留 */
#define CH395F_SINT_STAT_SOCK_TIMEOUT    0x40U  /* bit6: 超时 */

/*
 * 类型定义区 - 驱动返回码
 */
typedef enum {
    CH395F_STATUS_OK = 0,
    CH395F_STATUS_ERROR = -1,
    CH395F_STATUS_TIMEOUT = -2,
    CH395F_STATUS_NOT_DETECTED = -3
} ch395f_status_t;

/*
 * 函数声明区 - SPI 基础事务层
 */

/*
 * 函数功能：向 CH395 写入命令字节
 * 入口参数：cmd - 命令码  uint8_t  0x00 - 0xFF
 * 返回值：命令码回显值  uint8_t
 * 限定条件：需在 ch395f_spi_begin() 和 ch395f_spi_end() 之间调用
 * 函数说明：SPI 模式下命令与数据之间无需间隔
 */
uint8_t ch395f_write_cmd(uint8_t cmd);

/*
 * 函数功能：向 CH395 写入数据字节
 * 入口参数：data - 数据字节  uint8_t  0x00 - 0xFF
 * 返回值：数据回显值  uint8_t
 * 限定条件：需在 ch395f_spi_begin() 和 ch395f_spi_end() 之间调用
 */
uint8_t ch395f_write_data(uint8_t data);

/*
 * 函数功能：从 CH395 读取数据字节
 * 返回值：接收到的数据字节  uint8_t
 * 限定条件：需在 ch395f_spi_begin() 和 ch395f_spi_end() 之间调用
 */
uint8_t ch395f_read_data(void);

/*
 * 函数声明区 - 芯片检测与版本
 */

/*
 * 函数功能：检测 CH395 芯片是否存在且通信正常
 * 返回值：CH395F_STATUS_OK - 检测到芯片，CH395F_STATUS_NOT_DETECTED - 未检测到
 * 限定条件：SPI2 已正确初始化
 * 函数说明：发送 CMD_CHECK_EXIST (0x06) 及测试字节 0x57，
 *          芯片应返回按位取反值 0xA8
 */
ch395f_status_t ch395f_check_exist(void);

/*
 * 函数功能：读取 CH395 芯片版本号
 * 返回值：版本字节（bit5:0 为版本号）uint8_t
 * 限定条件：芯片已通过 ch395f_check_exist() 检测
 */
uint8_t ch395f_get_version(void);

/*
 * 函数声明区 - 初始化
 */

/*
 * 函数功能：软件复位 CH395
 * 返回值：CH395F_STATUS_OK
 * 限定条件：SPI2 已正确初始化
 * 函数说明：复位耗时约 15ms（TE0），函数内部已包含延时
 */
ch395f_status_t ch395f_reset(void);

/*
 * 函数功能：查询命令执行状态
 * 返回值：状态字节（CH395F_ERR_SUCCESS / CH395F_ERR_BUSY / ...）uint8_t
 * 限定条件：仅在长执行命令（如初始化）后调用
 */
uint8_t ch395f_get_cmd_status(void);

/*
 * 函数功能：轮询等待命令执行完成
 * 入口参数：timeout_ms - 超时时间（毫秒）  uint32_t
 * 返回值：命令执行状态码（CH395F_ERR_SUCCESS 或 CH395F_CMD_RET_ABORT）
 * 限定条件：在发送长执行命令（OPEN/TCP_LISTEN/CONNECT/DISCONNECT/CLOSE/DHCP）后调用
 * 函数说明：每 20ms 查询一次，直到命令完成或超时
 */
uint8_t ch395f_poll_cmd_status(uint32_t timeout_ms);

/*
 * 函数功能：初始化 CH395（包含 MAC、PHY、TCP/IP 协议栈）
 * 返回值：CH395F_STATUS_OK - 成功，CH395F_STATUS_TIMEOUT - 超时失败
 * 限定条件：芯片已通过 ch395f_reset() 复位
 * 函数说明：阻塞等待初始化完成或超时（典型 5ms，TE1）
 */
ch395f_status_t ch395f_init(void);

/*
 * 函数声明区 - 网络参数配置
 */

/*
 * 函数功能：设置 CH395 IP 地址（低字节在前）
 * 入口参数：p_ip - 4 字节 IP 地址指针  uint8_t*
 * 限定条件：指针非空，芯片已初始化
 */
void ch395f_set_ip_addr(uint8_t *p_ip);

/*
 * 函数功能：设置网关 IP 地址（低字节在前）
 * 入口参数：p_gwip - 4 字节网关 IP 指针  uint8_t*
 * 限定条件：指针非空，芯片已初始化
 */
void ch395f_set_gwip_addr(uint8_t *p_gwip);

/*
 * 函数功能：设置子网掩码（低字节在前）
 * 入口参数：p_mask - 4 字节子网掩码指针  uint8_t*
 * 限定条件：指针非空，芯片已初始化
 */
void ch395f_set_mask_addr(uint8_t *p_mask);

/*
 * 函数功能：设置 MAC 地址（低字节在前，存储于 EEPROM）
 * 入口参数：p_mac - 6 字节 MAC 地址指针  uint8_t*
 * 限定条件：指针非空，芯片已初始化
 * 函数说明：执行耗时约 30us（TE5）
 */
void ch395f_set_mac_addr(uint8_t *p_mac);

/*
 * 函数功能：从 CH395 读取 MAC 地址
 * 出口参数：p_mac - 6 字节 MAC 地址缓冲区指针  uint8_t*
 * 限定条件：指针非空
 */
void ch395f_get_mac_addr(uint8_t *p_mac);

/*
 * 函数功能：读取 IP 信息（IP + 掩码 + DNS，共 20 字节）
 * 出口参数：p_buf - 20 字节缓冲区指针  uint8_t*
 * 限定条件：指针非空
 */
void ch395f_get_ip_inf(uint8_t *p_buf);

/*
 * 函数声明区 - PHY 管理
 */

/*
 * 函数功能：获取 PHY 连接状态
 * 返回值：PHY 状态码（CH395F_PHY_DISCONN、CH395F_PHY_10M_FULL 等）uint8_t
 * 限定条件：芯片已初始化
 */
uint8_t ch395f_get_phy_status(void);

/*
 * 函数功能：设置 PHY 连接模式
 * 入口参数：phystat - 连接模式码  uint8_t  0x20 = 自动协商
 * 限定条件：芯片已初始化
 */
void ch395f_set_phy(uint8_t phystat);

/*
 * 函数功能：使能/关闭 CH395 响应 PING
 * 入口参数：enable - 1 使能 PING 响应，0 关闭
 * 限定条件：芯片已初始化
 * 函数说明：手册 5.37 CMD_PING_ENABLE，默认关闭
 */
void ch395f_ping_enable(uint8_t enable);

/*
 * 函数声明区 - DHCP
 */

/*
 * 函数功能：启用/禁用 DHCP
 * 入口参数：enable - 1 启用，0 禁用  uint8_t
 * 限定条件：芯片已初始化
 */
void ch395f_set_dhcp(uint8_t enable);

/*
 * 函数功能：获取 DHCP 状态
 * 返回值：0 = 成功，非零 = 错误/超时  uint8_t
 * 限定条件：芯片已初始化且 DHCP 已启用
 */
uint8_t ch395f_get_dhcp_status(void);

/*
 * 函数声明区 - Socket 管理
 */

/*
 * 函数功能：设置 Socket 协议类型
 * 入口参数：sock - Socket 索引  uint8_t  0 - 7
 *          proto - 协议类型  uint8_t  CH395F_PROTO_TYPE_xxx
 * 限定条件：Socket 未打开
 */
void ch395f_set_proto_type(uint8_t sock, uint8_t proto);

/*
 * 函数功能：设置 Socket 目标 IP 地址
 * 入口参数：sock - Socket 索引  uint8_t  0 - 7
 *          p_ip - 4 字节目标 IP 指针  uint8_t*
 * 限定条件：指针非空
 */
void ch395f_set_des_ip(uint8_t sock, uint8_t *p_ip);

/*
 * 函数功能：设置 Socket 目标端口（小端序）
 * 入口参数：sock - Socket 索引  uint8_t  0 - 7
 *          port - 目标端口  uint16_t
 * 限定条件：无
 */
void ch395f_set_des_port(uint8_t sock, uint16_t port);

/*
 * 函数功能：设置 Socket 源端口（小端序）
 * 入口参数：sock - Socket 索引  uint8_t  0 - 7
 *          port - 源端口  uint16_t
 * 限定条件：无
 */
void ch395f_set_sour_port(uint8_t sock, uint16_t port);

/*
 * 函数功能：打开 Socket
 * 入口参数：sock - Socket 索引  uint8_t  0 - 7
 * 返回值：命令执行状态码（CH395F_ERR_SUCCESS 表示成功）  uint8_t
 * 限定条件：协议类型、目标 IP、端口已设置
 */
uint8_t ch395f_open_socket(uint8_t sock);

/*
 * 函数功能：关闭 Socket
 * 入口参数：sock - Socket 索引  uint8_t  0 - 7
 * 返回值：命令执行状态码（CH395F_ERR_SUCCESS 表示成功）  uint8_t
 * 限定条件：Socket 已打开
 */
uint8_t ch395f_close_socket(uint8_t sock);

/*
 * 函数功能：启动 TCP 监听模式
 * 入口参数：sock - Socket 索引  uint8_t  0 - 7
 * 返回值：命令执行状态码（CH395F_ERR_SUCCESS 表示成功）  uint8_t
 * 限定条件：Socket 已打开且协议类型为 TCP
 */
uint8_t ch395f_tcp_listen(uint8_t sock);

/*
 * 函数功能：启动 TCP 连接
 * 入口参数：sock - Socket 索引  uint8_t  0 - 7
 * 返回值：命令执行状态码（CH395F_ERR_SUCCESS 表示成功）  uint8_t
 * 限定条件：Socket 已打开且协议类型为 TCP
 */
uint8_t ch395f_tcp_connect(uint8_t sock);

/*
 * 函数功能：断开 TCP 连接
 * 入口参数：sock - Socket 索引  uint8_t  0 - 7
 * 返回值：命令执行状态码（CH395F_ERR_SUCCESS 表示成功）  uint8_t
 * 限定条件：TCP 已建立连接
 */
uint8_t ch395f_tcp_disconnect(uint8_t sock);

/*
 * 函数声明区 - Socket 数据传输
 */

/*
 * 函数功能：向 Socket 发送缓冲区写入数据
 * 入口参数：sock - Socket 索引  uint8_t  0 - 7
 *          p_data - 数据指针  uint8_t*
 *          len - 数据长度  uint16_t
 * 限定条件：指针非空，长度大于 0，TCP 已连接或 UDP 已打开
 */
void ch395f_write_send_buf(uint8_t sock, uint8_t *p_data, uint16_t len);

/*
 * 函数功能：从 Socket 接收缓冲区读取数据
 * 入口参数：sock - Socket 索引  uint8_t  0 - 7
 *          p_data - 输出缓冲区指针  uint8_t*
 *          len - 待读取数据长度  uint16_t
 * 限定条件：指针非空，长度大于 0，接收缓冲区有数据
 */
void ch395f_read_recv_buf(uint8_t sock, uint8_t *p_data, uint16_t len);

/*
 * 函数功能：获取 Socket 接收缓冲区数据长度
 * 入口参数：sock - Socket 索引  uint8_t  0 - 7
 * 返回值：接收数据长度  uint16_t
 * 限定条件：Socket 已打开
 */
uint16_t ch395f_get_recv_len(uint8_t sock);

/*
 * 函数声明区 - 中断状态
 */

/*
 * 函数功能：获取全局中断状态（2 字节版，支持 Socket 0~7）
 * 返回值：中断状态 uint16_t（低字节=Socket 0~3 + PHY/DHCP，高字节=Socket 4~7 + DHCPv6）
 * 限定条件：芯片已初始化
 */
uint16_t ch395f_get_glob_int_status_all(void);

/*
 * 函数功能：获取 Socket 中断状态
 * 入口参数：sock - Socket 索引  uint8_t  0 - 7
 * 返回值：Socket 中断状态字节  uint8_t
 * 限定条件：芯片已初始化
 */
uint8_t ch395f_get_sock_int_status(uint8_t sock);

/*
 * 函数功能：获取 Socket 状态（2 字节输出）
 * 入口参数：sock - Socket 索引  uint8_t  0 - 7
 *          status - 2 字节输出缓冲区 [0]=Socket状态, [1]=TCP状态
 * 限定条件：芯片已初始化
 * 函数说明：Socket 状态: 00H=CLOSED, 05H=OPEN
 *           TCP 状态: 00H=CLOSED, 01H=LISTEN, 02H=SYN_SENT, 03H=SYN_RCVD, 04H=ESTABLISHED
 */
void ch395f_get_socket_status(uint8_t sock, uint8_t *status);

/*
 * 函数声明区 - Socket 远端信息
 */

/*
 * 函数功能：获取远端 IP 和端口
 * 入口参数：sock - Socket 索引  uint8_t  0 - 7
 *          p_buf - 6 字节输出缓冲区（4字节IP + 2字节端口）
 * 限定条件：TCP Server 模式下连接建立后调用
 * 函数说明：IP 低字节在前，端口低字节在前
 */
void ch395f_get_remot_ipp(uint8_t sock, uint8_t *p_buf);

/*
 * 函数声明区 - 功能参数设置
 */

/*
 * 函数功能：设置 CH395 功能参数
 * 入口参数：para - 4 字节功能参数  uint32_t
 *          bit0: 未使用，必须为 0
 *          bit1: TCP Server 多连接模式使能
 *          bit2: 低功耗模式
 *          bit3: Socket 关闭控制（0=芯片自动关闭，1=外部关闭）
 *          bit4: 禁用 SEND_OK 中断
 * 限定条件：必须在 ch395f_init() 之前调用
 */
void ch395f_set_fun_para(uint32_t para);

/*
 * 函数声明区 - TCP MSS 设置
 */

/*
 * 函数功能：设置 TCP MSS
 * 入口参数：mss - MSS 值  uint16_t  60~1460
 * 限定条件：必须在 ch395f_init() 之前调用
 */
void ch395f_set_tcp_mss(uint16_t mss);

/*
 * 函数声明区 - Socket 缓冲区设置
 */

/*
 * 函数功能：设置 Socket 接收缓冲区
 * 入口参数：sock - Socket 索引  uint8_t  0 - 7
 *          start_block - 起始块地址  uint8_t
 *          block_count - 块个数  uint8_t
 * 限定条件：必须在 OPEN_SOCKET_SN 之前调用
 */
void ch395f_set_recv_buf(uint8_t sock, uint8_t start_block, uint8_t block_count);

/*
 * 函数功能：设置 Socket 发送缓冲区
 * 入口参数：sock - Socket 索引  uint8_t  0 - 7
 *          start_block - 起始块地址  uint8_t
 *          block_count - 块个数  uint8_t
 * 限定条件：必须在 OPEN_SOCKET_SN 之前调用
 */
void ch395f_set_send_buf(uint8_t sock, uint8_t start_block, uint8_t block_count);

/*
 * 函数功能：清空 Socket 接收缓冲区
 * 入口参数：sock - Socket 索引  uint8_t  0 - 7
 * 限定条件：Socket 已打开
 */
void ch395f_clear_recv_buf(uint8_t sock);

/*
 * 函数功能：设置 TCP KeepAlive 空闲时间
 * 入口参数：time - 空闲时间（毫秒，必须为 500 的倍数）  uint32_t
 * 限定条件：必须在 ch395f_init() 之前调用
 */
void ch395f_set_keepalive_idle(uint32_t time);

/*
 * 函数功能：设置 TCP KeepAlive 探测间隔
 * 入口参数：time - 间隔时间（毫秒，必须为 500 的倍数）  uint32_t
 * 限定条件：必须在 ch395f_init() 之前调用
 */
void ch395f_set_keepalive_intvl(uint32_t time);

/*
 * 函数功能：设置 TCP KeepAlive 探测次数
 * 入口参数：cnt - 探测次数  uint8_t
 * 限定条件：必须在 ch395f_init() 之前调用
 */
void ch395f_set_keepalive_cnt(uint8_t cnt);

/*
 * 函数功能：启用/禁用指定 Socket 的 KeepAlive
 * 入口参数：sock - Socket 索引  uint8_t  0 - 7
 *          enable - 1 启用，0 禁用  uint8_t
 * 限定条件：Socket 已打开
 */
void ch395f_set_keepalive_enable(uint8_t sock, uint8_t enable);

/*
 * 函数声明区 - TCP 重传参数设置
 */

/*
 * 函数功能：设置 TCP 重传次数
 * 入口参数：cnt - 重传次数  uint8_t（0=使用默认值5）
 * 限定条件：必须在 ch395f_init() 之前调用
 */
void ch395f_set_retrans_count(uint8_t cnt);

/*
 * 函数功能：设置 TCP 重传周期
 * 入口参数：period - 重传周期（毫秒）  uint16_t
 * 限定条件：必须在 ch395f_init() 之前调用
 */
void ch395f_set_retrans_period(uint16_t period);

/*
 * 函数声明区 - ARP / TTL / 不可达信息
 */

/*
 * 函数功能：设置 ARP 重传参数
 * 入口参数：period_100ms - ARP 重传周期（单位 100ms，0=默认值=10即1秒）  uint8_t
 *          cnt - ARP 重传次数（0=默认值=3，255=无限重传）  uint8_t
 * 限定条件：应在 ch395f_init() 之后调用
 */
void ch395f_set_arp(uint8_t period_100ms, uint8_t cnt);

/*
 * 函数功能：设置 Socket TTL
 * 入口参数：sock - Socket 索引  uint8_t  0 - 7
 *          ttl - TTL 值  uint8_t  最大 128
 * 限定条件：Socket 已打开，TCP Server 模式下不生效
 */
void ch395f_set_ttl(uint8_t sock, uint8_t ttl);

/*
 * 函数功能：获取不可达信息（用于调试连接失败原因）
 * 出口参数：p_buf - 8 字节输出缓冲区（类型+协议码+端口+IP）
 * 限定条件：收到 GINT_STAT_UNREACH 中断后调用
 */
void ch395f_get_unreach_info(uint8_t *p_buf);

#ifdef __cplusplus
}
#endif

#endif /* __CH395F_H */
