#switchtec #microsemi #pciswitch

sys switchtec-user-sys

Rust对switchtec-user C库的封装

16个版本

0.4.2 2023年8月30日
0.4.1 2022年10月14日
0.3.1 2022年10月13日
0.3.0 2022年9月13日
0.1.11 2022年8月22日

#264硬件支持

Download history 9/week @ 2024-07-20 97/week @ 2024-07-27

106 每月下载

MIT/Apache

375KB
10K SLoC

C 9K SLoC // 0.2% comments Rust 333 SLoC // 0.1% comments

包含 (自动工具混淆代码,145KB) switchtec-user/configure,(模糊autoconf代码,2KB) switchtec-user/configure.ac

switchtec-user-sys 构建 文档

switchtec-user库的Rust封装。

switchtec-user库的详细信息和用法说明可以在这里找到。这里

示例用法

以下示例使用该库引入的SwitchtecDeviceCStrExt类型,包括由该crate封装的switchtec-user C库中的函数。

获取pciswitch设备名称和温度

使用由switchtec-user库提供的switchtec_nameswitchtec_die_temp函数的示例

use std::env;

use switchtec_user_sys::{switchtec_die_temp, switchtec_name, SwitchtecDevice, CStrExt};

fn main() -> anyhow::Result<()> {
    let path = env::args()
        .skip(1)
        .next()
        .unwrap_or_else(|| "/dev/pciswitch0".to_owned());

    let device = SwitchtecDevice::open(path)?;

    // SAFETY: We know that device holds a valid/open switchtec device
    let (device_name, temperature) = unsafe {
        let temp = switchtec_die_temp(*device);
        // `CStrExt` is providing `as_string()` here for the returned C-style char* string
        let name = switchtec_name(*device).as_string()?;
        (name, temp)
    };
    println!("Temperature for {device_name}: {temperature}");

    Ok(())
}

获取pciswitch设备的每个端口的状况

使用带有switchtec_status的出值结构的更复杂示例

use std::env;
use std::io;
use std::ptr;

use switchtec_user_sys::{switchtec_status, switchtec_status_free, SwitchtecDevice};

fn main() -> anyhow::Result<()> {
    let path: std::path::PathBuf = "/dev/pciswitch1".into();
    let device = SwitchtecDevice::open(&path)?;

    // Response struct out-value, to be populated by `switchtec_status`
    // The struct is the same name as the function, so we access this by its
    // full path in order to keep from having a name conflict
    let mut status: *mut switchtec_user_sys::switchtec_status = ptr::null_mut();

    // SAFETY: We're checking that the returned status is not null, and the `port_count`
    // resp provides how many `switchtec_status` structs are present in the data
    let per_port_status = unsafe {
        // We pass in a pointer (*mut) to the status pointer (*mut)
        let port_count = switchtec_status(*device, ptr::addr_of_mut!(status));
        let resp = if status.is_null() || port_count.is_negative() {
            // Negative value represents an error
            // https://microsemi.github.io/switchtec-user/group__Device.html#ga780a757b81a704c19217aca00f42b50e

            // Don't return this immediately so this function can call switchtec_status_free first
            // - For getting the actual error, consider using `switchtec_user_sys::switchtec_strerror`
            // https://microsemi.github.io/switchtec-user/group__Device.html#ga595e1d62336ba76c59344352c334fa18
            Err(io::Error::new(io::ErrorKind::Other, format!("Unknown error")))
        } else {
            // If the call was successful, create a slice from the populated status array
            // for only as many structs were returned: `port_count`
            let statuses: Vec<_> = std::slice::from_raw_parts(status, port_count as usize)
                .iter()
                .take(port_count as usize)
                .copied()
                .collect();
            Ok(statuses)
        };

        // Must be called after switchtec_status to free allocated status structs
        // https://microsemi.github.io/switchtec-user/group__Device.html#ga742519774cbc236ba2d80a08a7dc6b5f
        switchtec_status_free(status as *mut _, port_count);

        resp
    }?;

    println!("{per_port_status:#?}");
    Ok(())
}

依赖

Bindgen & Clang

此crate使用bindgen,需要Clang进行构建:请参阅bindgen的要求

Switchtec子模块

为了构建bindgen绑定并将库链接到switchtec-user C库,需要存在switchtec-user子模块。构建脚本build.rs将自动初始化子模块,但你也可以这样做

git submodule update --init

许可证

switchtec-user-sys 同时受 MIT 和 Apache 许可证,版本 2.0 许可,如许可证-MIT 和许可证-APACHE 文件中所示。

依赖

~0.3–2.7MB
~55K SLoC