sysfs_class/pci_bus/
mod.rs1use crate::{RuntimePM, RuntimePowerManagement, SysClass};
2use std::fs;
3use std::io;
4use std::path::{Path, PathBuf};
5
6#[derive(Clone)]
7pub struct PciDriver {
8 path: PathBuf,
9}
10
11impl SysClass for PciDriver {
12 fn base() -> &'static str {
13 "bus"
14 }
15
16 fn class() -> &'static str {
17 "pci/drivers"
18 }
19
20 unsafe fn from_path_unchecked(path: PathBuf) -> Self {
21 Self { path }
22 }
23
24 fn path(&self) -> &Path {
25 &self.path
26 }
27}
28
29impl PciDriver {
30 pub unsafe fn bind(&self, device: &PciDevice) -> io::Result<()> {
31 self.write_file("bind", device.id())
32 }
33
34 pub unsafe fn unbind(&self, device: &PciDevice) -> io::Result<()> {
35 self.write_file("unbind", device.id())
36 }
37}
38
39macro_rules! pci_devices {
40 ($( fn $file:tt -> $out:tt; )*) => {
41 $(
42 pub fn $file(&self) -> io::Result<$out> {
43 let v = self.read_file(stringify!($file))?;
44 $out::from_str_radix(v[2..].trim(), 16).map_err(|err| {
45 io::Error::new(
46 io::ErrorKind::InvalidData,
47 format!("{}", err)
48 )
49 })
50 }
51 )*
52 }
53}
54
55#[derive(Clone)]
56pub struct PciDevice {
57 path: PathBuf,
58}
59
60impl SysClass for PciDevice {
61 fn base() -> &'static str {
62 "bus"
63 }
64
65 fn class() -> &'static str {
66 "pci/devices"
67 }
68
69 unsafe fn from_path_unchecked(path: PathBuf) -> Self {
70 Self { path }
71 }
72
73 fn path(&self) -> &Path {
74 &self.path
75 }
76}
77
78impl PciDevice {
79 pci_devices! {
80 fn class -> u32;
81 fn device -> u16;
82 fn revision -> u8;
83 fn subsystem_device -> u16;
84 fn subsystem_vendor -> u16;
85 fn vendor -> u16;
86 }
87
88 pub fn driver(&self) -> io::Result<PciDriver> {
89 fs::canonicalize(self.path.join("driver")).map(|path| PciDriver { path })
90 }
91
92 pub unsafe fn remove(&self) -> io::Result<()> {
93 self.write_file("remove", "1")
94 }
95}
96
97impl RuntimePM for PciDevice {
98 fn set_runtime_pm(&self, state: RuntimePowerManagement) -> io::Result<()> {
99 self.write_file("power/control", <&'static str>::from(state))
100 }
101}