sysfs_serde/
pci_attributes.rs

1use crate::uevent::UEvent;
2#[cfg(feature = "serde")]
3use serde::Serialize;
4use std::collections::HashMap;
5use std::str::FromStr;
6#[cfg_attr(feature = "serde", derive(Serialize))]
7#[derive(Default)]
8pub struct PciAttributes {
9    pub class: u32,
10    pub subsystem_vendor: String,
11    pub subsystem_device: String,
12    pub dma_mask_bits: u8,
13    pub vendor: String,
14    pub device: String,
15    pub enable: u8,
16    pub revision: u16,
17    pub irq: u8,
18    pub local_cpus: u8,
19    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
20    pub uevent: Option<UEvent>,
21    pub resource: Vec<u64>,
22    pub ari_enabled: u8,
23    pub current_link_width: u8,
24    pub max_link_width: u8,
25    pub msi_bus: u8,
26    pub consistent_dma_mask_bits: u8,
27    pub secondary_bus_number: u8,
28    pub subordinate_bus_number: u8,
29    pub broken_parity_status: u8,
30    pub d3cold_allowed: u8,
31    pub numa_node: i8,
32    pub modalias: String,
33    pub current_link_speed: String,
34    pub max_link_speed: String,
35    pub driver_override: Option<String>,
36    pub local_cpulist: String,
37    pub aer_dev_fatal: String,
38    pub aer_dev_nonfatal: String,
39    pub aer_dev_correctable: String,
40    #[cfg_attr(feature = "serde", serde(skip))]
41    pub config: Vec<u8>,
42    #[cfg_attr(
43        feature = "serde",
44        serde(flatten, skip_serializing_if = "HashMap::is_empty")
45    )]
46    pub attributes: HashMap<String, String>,
47}
48
49impl PciAttributes {
50    pub(crate) fn add(&mut self, key: &str, value: Vec<u8>) -> Result<(), std::num::ParseIntError> {
51        if key == "config" {
52            self.config = value;
53            return Ok(());
54        }
55        let value = String::from_utf8_lossy(&value)
56            .to_string()
57            .trim()
58            .to_string();
59        match &key[0..] {
60            "revision" => {
61                self.revision = u16::from_str_radix(&value[2..], 16)?;
62            }
63            "uevent" => {
64                self.uevent = UEvent::from_str(&value).ok();
65            }
66            "enable" => self.enable = value.parse()?,
67            "class" => self.class = u32::from_str_radix(&value[2..], 32)?,
68            "numa_node" => self.numa_node = value.parse()?,
69            "dma_mask_bits" => self.dma_mask_bits = value.parse()?,
70            "current_link_width" => self.current_link_width = value.parse()?,
71            "max_link_width" => self.max_link_width = value.parse()?,
72            "consistent_dma_mask_bits" => self.consistent_dma_mask_bits = value.parse()?,
73            "secondary_bus_number" => self.secondary_bus_number = value.parse()?,
74            "subordinate_bus_number" => self.subordinate_bus_number = value.parse()?,
75            "d3cold_allowed" => self.d3cold_allowed = value.parse()?,
76            "driver_override" => {
77                if value != "(null)" {
78                    self.driver_override = Some(value);
79                }
80            }
81            "broken_parity_status" => self.broken_parity_status = value.parse()?,
82            "local_cpus" => {
83                self.local_cpus = u8::from_str_radix(&value, 16)?;
84            }
85            "msi_bus" => self.msi_bus = value.parse()?,
86            "ari_enabled" => self.ari_enabled = value.parse()?,
87            "irq" => self.irq = value.parse()?,
88            "resource" => {
89                let value = value.replace('\n', " ");
90                for r in value.split(' ') {
91                    self.resource.push(u64::from_str_radix(&r[2..], 16)?);
92                }
93            }
94            _ => {
95                self.attributes.insert(key.into(), value);
96            }
97        }
98        Ok(())
99    }
100}