/*
 * Copyright © Stéphane Raimbault <stephane.raimbault@gmail.com>
 *
 * SPDX-License-Identifier: LGPL-2.1-or-later
 */

#ifndef MODBUS_RTU_PRIVATE_H
#define MODBUS_RTU_PRIVATE_H

#include <stdint.h>

/*
 * 防止同时包含 <asm/termbits.h> 和 <termios.h> 时，
 * "struct termios" 的重复定义冲突。
 * 策略：先用宏 termios 屏蔽版本标识，包含 termbits.h 后再取消屏蔽，
 * 这样 termios.h 会在后续正常包含。
 */
#define termios
#include <asm/termbits.h>
#undef termios
#include <termios.h>

/*
 * Modbus RTU 协议的帧格式定义：
 *
 * RTU ADU 帧结构：
 * ┌─────────┬──────┬──────────┬─────┐
 * │ 从站地址 │ PDU  │   CRC    │     │
 * │  (1字节) │(变长)│ (2字节)  │ ... │
 * └─────────┴──────┴──────────┴─────┘
 */

/* RTU 帧头长度：只有从站地址 1 字节 */
#define _MODBUS_RTU_HEADER_LENGTH     1
/* RTU 预设请求帧长度（如报告从站ID等广播命令） */
#define _MODBUS_RTU_PRESET_REQ_LENGTH 6
/* RTU 预设响应帧长度 */
#define _MODBUS_RTU_PRESET_RSP_LENGTH 2

/* RTU CRC 校验和长度：2 字节（CRC-16） */
#define _MODBUS_RTU_CHECKSUM_LENGTH 2


/*
 * modbus_rtu_t — Modbus RTU 后端的私有数据结构体。
 * 保存 RTU 串口连接所需的所有配置参数和运行时状态。
 * 该结构体通过 modbus_t.backend_data 指针引用。
 */
typedef struct _modbus_rtu {
    /*
     * 串口设备路径。
     * Linux 下形如 "/dev/ttyS0"、"/dev/ttyUSB0"；
     * macOS 下形如 "/dev/tty.USA19*"。
     */
    char *device;
    /* 波特率：9600, 19200, 57600, 115200 等 */
    int baud;
    /* 数据位（通常为 8） */
    uint8_t data_bit;
    /* 停止位（通常为 1 或 2） */
    uint8_t stop_bit;
    /* 校验位：'N'(无校验), 'O'(奇校验), 'E'(偶校验) */
    char parity;
    /* 保存原始 termios2 设置，用于关闭时恢复 */
    struct termios2 old_tios;
#if HAVE_DECL_TIOCSRS485
    /*
     * RS-485 串口模式标志。
     * TIOCSRS485 是 Linux 内核提供的 ioctl，用于配置 RS-485 收发控制。
     */
    int serial_mode;
#endif
#if HAVE_DECL_TIOCM_RTS
    /*
     * RTS（请求发送）引脚控制相关字段。
     * 在 RS-485 半双工通信中，需要通过 RTS 信号控制收发切换。
     */
    int rts;              /* RTS 控制模式 */
    int rts_delay;        /* RTS 发送延迟（微秒） */
    int onebyte_time;     /* 单字节传输时间（用于 RTS 时序计算） */
    void (*set_rts)(modbus_t *ctx, int on); /* 设置 RTS 信号电平的回调函数 */
#endif
    /*
     * 需要忽略的确认（Confirmation）消息数量。
     * 当一条链路上存在多个从站时，广播命令会导致所有从站都产生响应，
     * 需要忽略除目标从站之外的响应消息。
     */
    int confirmation_to_ignore;
} modbus_rtu_t;

#endif /* MODBUS_RTU_PRIVATE_H */
