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);
}
}