/**
 * @defgroup PCIE_DEVICE_API PCIe 设备管理接口
 * @brief 提供 PCIe Profinet 主从设备的初始化、配置和数据交互功能
 * @{
 */
#ifndef __PCIE_DEV_H__
#define __PCIE_DEV_H__

#include <stdbool.h>


/** 最大槽位数量 */
#define MAX_SLOT_NUM     (64)
/** 最大缓冲区大小（字节） */
#define MAX_BUFF_SIZE    (128)

/**
 * @brief 网络设备信息结构体
 * @details 用于存储和管理网络接口的基本配置信息
 */
typedef struct {
    char name[16];      /**< 网络接口名称，如 "eth0" */
    char mac[32];       /**< MAC 地址字符串，格式如 "00:11:22:33:44:55" */
    char ip[16];        /**< IP 地址字符串，如 "192.168.1.100" */
    char mask[16];      /**< 子网掩码字符串，如 "255.255.255.0" */
    char gw[16];        /**< 网关地址字符串，如 "192.168.1.1" */
} DEVICE_NET_T, * PDEVICE_NET_T;

/**
 * @brief Profinet 从站模块信息结构体
 * @details 描述单个 Profinet 从站模块的状态和数据缓冲区
 */
typedef struct {
    int status;                         /**< 模块状态：0-离线，1-在线 */
    char name[32];                      /**< 模块名称标识 */
    int type;                           /**< 数据类型：0-输入数据，1-输出数据 */
    int recLen;                         /**< 记录长度 */
    unsigned char record[4];            /**< 记录数据 */
    int in_size;                        /**< 输入数据缓冲区大小（字节） */
    int out_size;                       /**< 输出数据缓冲区大小（字节） */
    unsigned char in_buff[MAX_BUFF_SIZE];   /**< 输入数据缓冲区 */
    unsigned char out_buff[MAX_BUFF_SIZE];  /**< 输出数据缓冲区 */
} PNIO_SLAVE_MODULE_T, * PPNIO_SLAVE_MODULE_T;

/**
 * @brief Profinet 从站完整信息结构体
 * @details 包含从站设备的版本信息、网络配置及所有槽位模块信息
 */
typedef struct {
    char app_ver[16];                   /**< 库版本号 */
    char fw_ver[16];                    /**< 固件版本号 */
    DEVICE_NET_T net[2];                /**< 双网口配置信息（net[0] 和 net[1]） */
    int max_slot_num;                   /**< 支持的最大槽位数量 */
    int cur_slot_num;                   /**< 当前已配置的槽位数量 */
    PNIO_SLAVE_MODULE_T module[MAX_SLOT_NUM]; /**< 所有槽位的模块信息数组 */
} PNIO_SLAVE_INFO_T, * PPNIO_SLAVE_INFO_T;

//----------------------pn-master----------------------//

/**
 * @brief Profinet 主站设备列表项结构体
 * @details 描述主站管理的单个从站设备信息
 */
typedef struct {
    int online;         /**< 在线状态：0-离线，1-在线 */
    int station;        /**< 站点号 */
    int slot;           /**< 槽位号 */
    int subslot;        /**< 子槽位号 */
    int type;           /**< 设备类型 */
    int addr;           /**< 数据地址偏移 */
    int len;            /**< 数据长度 */
} PNIO_MASTER_LIST_T, *PPNIO_MASTER_LIST_T;

/**
 * @brief Profinet 主站配置信息结构体
 * @details 包含主站管理的所有从站设备列表及统计信息
 */
typedef struct {
    int station_num;                        /**< 总站点数量 */
    int online_num;                         /**< 在线站点数量 */
    int offline_num;                        /**< 离线站点数量 */
    int item_count;                         /**< 设备列表项总数 */
    PNIO_MASTER_LIST_T item[200];           /**< 从站设备列表数组，最多支持 200 个设备 */
}PNIO_MASTER_CONFIG_T, *PPNIO_MASTER_CONFIG_T;

/**
 * @brief Profinet 主站完整信息结构体
 * @details 包含主站的版本信息、网络配置及设备配置信息
 */
typedef struct {
    char app_ver[16];                   /**< 应用程序版本号 */
    char fw_ver[16];                    /**< 固件版本号 */
    DEVICE_NET_T net[2];                /**< 双网口配置信息 */
    PNIO_MASTER_CONFIG_T cfg;           /**< 主站配置信息及从站列表 */
} PNIO_MASTER_INFO_T, *PPNIO_MASTER_INFO_T;

/**
 * @brief EtherNet/IP 从站完整信息结构体
 * @details 包含主站的版本信息、网络配置及设备配置信息
 */
typedef struct {
    char app_ver[16];                   /**< 应用程序版本号 */
    char fw_ver[16];                    /**< 固件版本号 */
    DEVICE_NET_T net[2];                /**< 双网口配置信息 */
    int in_size;                        /**< 输入数据缓冲区大小（字节） */
    int out_size;                       /**< 输出数据缓冲区大小（字节） */
} EIP_SLAVE_INFO_T, *PEIP_SLAVE_INFO_T;

/**
 * @brief 初始化 PCIe 设备驱动
 * @return 失败返回小于 0
 * @note 在使用任何其他接口之前必须先调用此函数进行初始化
 */
int device_init();

/**
 * @brief 反初始化并释放 PCIe 设备资源
 * @return 成功返回 true，失败返回 false
 * @note 程序退出前应调用此函数清理资源
 */
bool device_deinit();

/**
 * @brief 打开指定的 PCIe 设备
 * @param index 设备索引号（从 0 开始）
 * @param type 设备类型：0-Profinet 从站，1-Profinet 主站
 * @return 成功返回设备句柄（非负数），失败返回负数错误码
 * @note 使用设备前必须先打开，使用完毕后应调用 device_close 关闭
 */
int device_open(int index, int type);

/**
 * @brief 关闭指定的 PCIe 设备
 * @param index 设备索引号（与 device_open 返回的句柄对应）
 * @return 成功返回 true，失败返回 false
 */
bool device_close(int index);

/**
 * @brief 获取指定设备的网络配置信息
 * @param index 设备索引号
 * @param p 指向 DEVICE_NET_T 结构体的指针，用于接收网络配置信息
 * @return 成功返回 true，失败返回 false
 * @note 对于双网口设备，需要多次调用或扩展接口以获取两个网口信息
 */
bool device_net_get(int index, PDEVICE_NET_T p);

/**
 * @brief 设置指定设备的网络配置信息
 * @param index 设备索引号
 * @param p 指向 DEVICE_NET_T 结构体的指针，包含要设置的网络配置信息
 * @return 成功返回 true，失败返回 false
 * @note 设置后立即生效
 */
bool device_net_set(int index, PDEVICE_NET_T p);

/**
 * @brief 获取 Profinet 从站的完整信息
 * @param index 设备索引号
 * @param p 指向 PNIO_SLAVE_INFO_T 结构体的指针，用于接收从站完整信息
 * @return 成功返回 true，失败返回 false
 * @details 包含版本信息、网络配置及所有槽位模块的信息
 */
bool pnio_s_info_get(int index, PPNIO_SLAVE_INFO_T p);

/**
 * @brief 获取 Profinet 从站指定槽位的模块信息
 * @param index 设备索引号
 * @param slot 槽位号（从 0 开始）
 * @param p 指向 PNIO_SLAVE_MODULE_T 结构体的指针，用于接收模块信息
 * @return 成功返回 true，失败返回 false
 */
bool pnio_s_module_info_get(int index, int slot, PPNIO_SLAVE_MODULE_T p);

/**
 * @brief 获取 Profinet 从站所有槽位的模块信息
 * @param index 设备索引号
 * @param slot 起始槽位号（通常传 0 表示从第一个槽位开始）
 * @param p 指向 PNIO_SLAVE_MODULE_T 结构体数组的指针，用于接收所有模块信息
 * @return 成功返回 true，失败返回 false
 * @note 确保 p 指向的内存空间足够大，能容纳所有槽位的信息
 */
bool pnio_s_module_info_all_get(int index, int slot, PPNIO_SLAVE_MODULE_T p);

/**
 * @brief 读取 Profinet 从站指定槽位的数据
 * @param index 设备索引号
 * @param slot 槽位号
 * @param type 数据类型：0-输入数据，1-输出数据
 * @param offset 数据偏移量（字节）
 * @param size 要读取的数据大小（字节）
 * @param buff 用于接收数据的缓冲区指针
 * @return 成功返回 true，失败返回 false
 * @note 确保 buff 指向的内存空间至少为 size 字节
 */
bool pnio_s_module_data_get(int index, int slot, int type, int offset, int size, unsigned char *buff);

/**
 * @brief 写入 Profinet 从站指定槽位的数据
 * @param index 设备索引号
 * @param slot 槽位号
 * @param type 数据类型：0-输入数据，1-输出数据
 * @param offset 数据偏移量（字节）
 * @param size 要写入的数据大小（字节）
 * @param buff 包含待写入数据的缓冲区指针
 * @return 成功返回 true，失败返回 false
 * @note 确保 buff 指向的内存空间至少包含 size 字节有效数据
 */
bool pnio_s_module_data_set(int index, int slot, int type, int offset, int size, unsigned char *buff);

/**
 * @brief 获取 Profinet 主站的完整信息
 * @param index 设备索引号
 * @param p 指向 PNIO_MASTER_INFO_T 结构体的指针，用于接收主站完整信息
 * @return 成功返回 true，失败返回 false
 * @details 包含版本信息、网络配置及所有管理的从站设备信息
 */
bool pnio_m_info_get(int index, PPNIO_MASTER_INFO_T p);

/**
 * @brief 读取 Profinet 主站管理的从站数据
 * @param index 设备索引号
 * @param slot 从站站号或槽位号
 * @param type 数据类型：0-输入数据，1-输出数据
 * @param offset 数据偏移量（字节）
 * @param size 要读取的数据大小（字节）
 * @param buff 用于接收数据的缓冲区指针
 * @return 成功返回 true，失败返回 false
 * @note 确保 buff 指向的内存空间至少为 size 字节
 */
bool pnio_m_module_data_get(int index, int slot, int type, int offset, int size, unsigned char *buff);

/**
 * @brief 写入 Profinet 主站管理的从站数据
 * @param index 设备索引号
 * @param slot 从站站号或槽位号
 * @param type 数据类型：0-输入数据，1-输出数据
 * @param offset 数据偏移量（字节）
 * @param size 要写入的数据大小（字节）
 * @param buff 包含待写入数据的缓冲区指针
 * @return 成功返回 true，失败返回 false
 * @note 确保 buff 指向的内存空间至少包含 size 字节有效数据
 */
bool pnio_m_module_data_set(int index, int slot, int type, int offset, int size, unsigned char *buff);

/**
 * @brief 获取 EtherNet/IP 从站的完整信息
 * @param index 设备索引号
 * @param p 指向 PEIP_SLAVE_INFO_T 结构体的指针，用于接收从站完整信息
 * @return 成功返回 true，失败返回 false
 * @details 包含版本信息、网络配置及所有管理的从站设备信息
 */
bool eip_s_info_get(int index, PEIP_SLAVE_INFO_T p);

/**
 * @brief 读取 EtherNet/IP 从站管理的数据
 * @param index 设备索引号
 * @param type 数据类型：0-输入数据，1-输出数据
 * @param offset 数据偏移量（字节）
 * @param size 要读取的数据大小（字节）
 * @param buff 用于接收数据的缓冲区指针
 * @return 成功返回 true，失败返回 false
 * @note 确保 buff 指向的内存空间至少为 size 字节
 */
bool eip_s_module_data_get(int index, int type, int offset, int size, unsigned char *buff);

/**
 * @brief 写入 EtherNet/IP 从站管理的数据
 * @param index 设备索引号
 * @param type 数据类型：固定值 1
 * @param offset 数据偏移量（字节）
 * @param size 要写入的数据大小（字节）
 * @param buff 包含待写入数据的缓冲区指针
 * @return 成功返回 true，失败返回 false
 * @note 确保 buff 指向的内存空间至少包含 size 字节有效数据
 */
bool eip_s_module_data_set(int index, int type, int offset, int size, unsigned char *buff);


#endif
