use crate::utils::ffi;
#[allow(unused_imports)]
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
#[derive(Debug, Clone)]
pub struct NetworkInfo {
pub name: String,
pub description: String,
pub mac: [u8; 6],
}
impl NetworkInfo {
pub fn mac_string(&self) -> String {
format!("{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
self.mac[0], self.mac[1], self.mac[2],
self.mac[3], self.mac[4], self.mac[5])
}
}
pub fn get_network_adapters() -> Vec<NetworkInfo> {
Vec::new()
}
#[derive(Debug, Clone)]
pub struct EnumeratedNetworkInfo {
pub name: String,
pub description: String,
pub slave_num: i16,
pub redundant_slave_num: i16,
}
pub fn enumerate_network_info(is_redundant: bool, need_slaves_num: bool) -> Vec<EnumeratedNetworkInfo> {
let count = unsafe { ffi::GetNetworkInfo(is_redundant as i32, need_slaves_num as i32) };
if count <= 0 {
return Vec::new();
}
let ptr = unsafe { ffi::GetNetworksPointer() } as *const u8;
if ptr.is_null() {
return Vec::new();
}
const STRIDE: usize = 128 + 128 + 2 + 2;
let mut result = Vec::with_capacity(count as usize);
for i in 0..count as usize {
unsafe {
let base = ptr.add(i * STRIDE);
let name_slice = std::slice::from_raw_parts(base, 128);
let desc_slice = std::slice::from_raw_parts(base.add(128), 128);
let slave_num = std::ptr::read_unaligned(base.add(256) as *const i16);
let red_num = std::ptr::read_unaligned(base.add(258) as *const i16);
let name_end = name_slice.iter().position(|&b| b == 0).unwrap_or(128);
let desc_end = desc_slice.iter().position(|&b| b == 0).unwrap_or(128);
let name = String::from_utf8_lossy(&name_slice[..name_end]).to_string();
let desc = String::from_utf8_lossy(&desc_slice[..desc_end]).to_string();
result.push(EnumeratedNetworkInfo {
name,
description: desc,
slave_num,
redundant_slave_num: red_num,
});
}
}
result
}
#[derive(Debug, Clone)]
pub struct ScannedSlaveInfo {
pub index: u16,
pub vendor_id: u32,
pub product_code: u32,
pub revision: u32,
pub serial: u32,
pub name: String,
pub config_addr: u16,
pub alias_addr: u16,
pub parent_index: u16,
pub topology: u8,
pub active_ports: u8,
pub entry_port: u8,
pub parent_port: u8,
pub physical_type: u8,
}
impl ScannedSlaveInfo {
pub fn alias_addr_hex(&self) -> String {
format!("0x{:04X}", self.alias_addr)
}
pub fn vendor_id_hex(&self) -> String {
format!("0x{:08X}", self.vendor_id)
}
pub fn is_coupler(&self) -> bool {
self.physical_type == 1
}
pub fn device_type(&self) -> u8 {
self.physical_type
}
pub fn depth(&self) -> u16 {
if self.parent_index == 0 || self.parent_index == self.index {
0
} else {
1 }
}
}
pub fn get_scanned_slaves() -> Vec<ScannedSlaveInfo> {
let count = unsafe { ffi::GetScannedSlaveCount() };
if count <= 0 {
return Vec::new();
}
let mut slaves = Vec::with_capacity(count as usize);
for i in 0..count {
let mut vendor_id: u32 = 0;
let mut product_code: u32 = 0;
let mut revision: u32 = 0;
let mut serial: u32 = 0;
let mut name_buf = vec![0u8; 256];
let mut config_addr: u16 = 0;
let mut alias_addr: u16 = 0;
let mut parent: u16 = 0;
let mut topology: u8 = 0;
let mut active_ports: u8 = 0;
let mut entry_port: u8 = 0;
let mut parent_port: u8 = 0;
let mut ptype: u8 = 0;
let ret = unsafe {
ffi::GetScannedSlaveInfo(
i,
&mut vendor_id, &mut product_code, &mut revision, &mut serial,
name_buf.as_mut_ptr() as *mut c_char, name_buf.len() as i32,
&mut config_addr, &mut alias_addr,
&mut parent, &mut topology, &mut active_ports,
&mut entry_port, &mut parent_port, &mut ptype,
)
};
if ret != 0 {
let null_pos = name_buf.iter().position(|&b| b == 0).unwrap_or(name_buf.len());
let name = String::from_utf8_lossy(&name_buf[..null_pos]).to_string();
slaves.push(ScannedSlaveInfo {
index: (i + 1) as u16,
vendor_id,
product_code,
revision,
serial,
name,
config_addr,
alias_addr,
parent_index: parent,
topology,
active_ports,
entry_port,
parent_port,
physical_type: ptype,
});
}
}
slaves
}
pub fn ring_slave_count() -> i32 {
unsafe { ffi::GetRingSlaveCount() }
}
pub fn scanned_slave_count() -> i32 {
unsafe { ffi::GetScannedSlaveCount() }
}
#[derive(Debug, Clone)]
pub struct CouplerStatus {
pub index: u16,
pub name: String,
pub child_count: usize,
}
pub fn determine_coupler_status(slaves: &[ScannedSlaveInfo]) -> Vec<CouplerStatus> {
let mut results = Vec::new();
for s in slaves {
if !s.is_coupler() {
continue;
}
let child_count = slaves.iter().filter(|c| c.parent_index == s.index).count();
results.push(CouplerStatus {
index: s.index,
name: s.name.clone(),
child_count,
});
}
results
}