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