sysfs_serde/
pci_attributes.rs1use 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}