darra-ethercat-master 2.7.0

Commercial EtherCAT master protocol stack, real-time kernel driver integration, Windows and Linux support, multi-language SDKs, complex topology and hot-plug support.
Documentation

use crate::utils::ffi;
use crate::statics::version_info::{MAJOR_VERSION, MINOR_VERSION};

#[derive(Debug, Clone, Default)]
pub struct DriverVersionInfo {

    pub major: u32,

    pub minor: u32,

    pub build: u32,

    pub build_date: String,

    pub driver_name: String,

    pub available: bool,

    pub error_message: Option<String>,
}

fn read_packed_str(buf: &[u8; 32]) -> String {
    let null_pos = buf.iter().position(|&b| b == 0).unwrap_or(buf.len());
    String::from_utf8_lossy(&buf[..null_pos]).to_string()
}

pub fn get() -> DriverVersionInfo {
    let ptr = unsafe { ffi::GetDriverVersion() };
    if ptr.is_null() {
        return DriverVersionInfo {
            error_message: Some("GetDriverVersion 返回空指针 (Core.dll 未加载或符号缺失)".into()),
            ..Default::default()
        };
    }

    let info = unsafe { std::ptr::read_unaligned(ptr) };
    let major = unsafe { std::ptr::addr_of!(info.major).read_unaligned() };
    let minor = unsafe { std::ptr::addr_of!(info.minor).read_unaligned() };
    let build = unsafe { std::ptr::addr_of!(info.build).read_unaligned() };
    let available = unsafe { std::ptr::addr_of!(info.available).read_unaligned() };
    let error_code = unsafe { std::ptr::addr_of!(info.error_code).read_unaligned() };
    let build_date_raw = unsafe { std::ptr::addr_of!(info.build_date).read_unaligned() };
    let driver_name_raw = unsafe { std::ptr::addr_of!(info.driver_name).read_unaligned() };

    DriverVersionInfo {
        major,
        minor,
        build,
        build_date: read_packed_str(&build_date_raw),
        driver_name: read_packed_str(&driver_name_raw),
        available: available != 0,
        error_message: if error_code != 0 {
            Some(format!("驱动错误码 0x{:08X}", error_code))
        } else {
            None
        },
    }
}

pub fn invalidate_cache() {
    unsafe { ffi::InvalidateDriverVersionCache() }
}

pub fn ensure_drivers_running() -> i32 {
    unsafe { ffi::EnsureDriversRunning() as i32 }
}

pub fn check_compatibility() -> (bool, String) {
    let info = get();
    if !info.available {
        let err = info.error_message.as_deref().unwrap_or("驱动不可用");
        return (false, format!("RT 驱动不可用: {}", err));
    }
    let sdk_major = MAJOR_VERSION as u32;
    let sdk_minor = MINOR_VERSION as u32;
    let drv_major = info.major;
    let drv_minor = info.minor;
    if sdk_major != drv_major {
        return (
            false,
            format!(
                "主版本不匹配: SDK={}.{} 驱动={}.{} ({})",
                sdk_major, sdk_minor, drv_major, drv_minor, info.driver_name
            ),
        );
    }
    if sdk_minor > drv_minor {
        return (
            false,
            format!(
                "SDK 次版本高于驱动: SDK={}.{} 驱动={}.{} (建议升级驱动)",
                sdk_major, sdk_minor, drv_major, drv_minor
            ),
        );
    }
    (
        true,
        format!(
            "兼容: SDK={}.{} 驱动={}.{}.{} ({}, build {})",
            sdk_major, sdk_minor, drv_major, drv_minor, info.build, info.driver_name, info.build_date
        ),
    )
}

pub fn log_compatibility() {
    use crate::logging::logging::{LogManager, LogCategory};
    let (ok, msg) = check_compatibility();
    let category = if ok { LogCategory::Message } else { LogCategory::Warning };
    let line = if ok {
        format!("[DriverVersion] {}", msg)
    } else {
        format!("[DriverVersion] 不兼容: {}", msg)
    };
    LogManager::instance().add_log(category, &line);
    if !ok {
        eprintln!("{}", line);
    }
}