hardware 0.0.9

A no_std bare-metal hardware abstraction layer — all port I/O, memory and swap allocations are guarded at runtime. Do not consider this dependency stable before x.1.x
Documentation
use core::sync::atomic::{AtomicUsize, Ordering};

const MAX_DEVICES: usize = 64;

struct BusDevice {
    vendor_id: AtomicUsize,
    device_id: AtomicUsize,
    bus_type: AtomicUsize,
    class: AtomicUsize,
}

struct DeviceRegistry {
    devices: [BusDevice; MAX_DEVICES],
    count: AtomicUsize,
}

unsafe impl Sync for DeviceRegistry {}

static REGISTRY: DeviceRegistry = DeviceRegistry {
    devices: [const {
        BusDevice {
            vendor_id: AtomicUsize::new(0),
            device_id: AtomicUsize::new(0),
            bus_type: AtomicUsize::new(0),
            class: AtomicUsize::new(0),
        }
    }; MAX_DEVICES],
    count: AtomicUsize::new(0),
};

pub fn scan_sysfs_devices() -> usize {
    REGISTRY.count.load(Ordering::Acquire)
}

pub fn register_device(vendor: u16, device: u16, bus: u8) -> bool {
    let idx = REGISTRY.count.load(Ordering::Acquire);
    if idx >= MAX_DEVICES {
        return false;
    }
    REGISTRY.devices[idx]
        .vendor_id
        .store(vendor as usize, Ordering::Release);
    REGISTRY.devices[idx]
        .device_id
        .store(device as usize, Ordering::Release);
    REGISTRY.devices[idx]
        .bus_type
        .store(bus as usize, Ordering::Release);
    REGISTRY.count.store(idx + 1, Ordering::Release);
    true
}

pub fn device_count() -> usize {
    let c = REGISTRY.count.load(Ordering::Acquire);
    if c == 0 {
        return scan_sysfs_devices();
    }
    c
}

pub fn device_vendor(index: usize) -> Option<u16> {
    if index >= device_count() {
        return None;
    }
    Some(REGISTRY.devices[index].vendor_id.load(Ordering::Acquire) as u16)
}

pub fn device_id(index: usize) -> Option<u16> {
    if index >= device_count() {
        return None;
    }
    Some(REGISTRY.devices[index].device_id.load(Ordering::Acquire) as u16)
}

pub fn device_class(index: usize) -> Option<u16> {
    if index >= device_count() {
        return None;
    }
    Some(REGISTRY.devices[index].class.load(Ordering::Acquire) as u16)
}