From 4a1d1d798ca817ed25c2aae5e9d8d238d5c4d1a7 Mon Sep 17 00:00:00 2001 From: rolv Date: Wed, 15 Mar 2023 00:46:17 +0000 Subject: [PATCH 1/8] feat - add functionality to list connected gpu(s) --- Cargo.toml | 1 + src/lib.rs | 2 + src/linux/mod.rs | 31 +++++++++++ src/linux/pci_devices.rs | 112 +++++++++++++++++++++++++++++++++++++++ src/traits.rs | 32 +++++++++++ 5 files changed, 178 insertions(+) create mode 100644 src/linux/pci_devices.rs diff --git a/Cargo.toml b/Cargo.toml index 6256f28e..ffde5c43 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ build = "build.rs" cfg-if = "1.0.0" libc = "0.2.131" home = "0.5.3" +pciid-parser = "0.6.2" [build-dependencies.vergen] version = "7.3.2" diff --git a/src/lib.rs b/src/lib.rs index b8f60e0f..2f028245 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,6 +24,7 @@ cfg_if! { pub type ProductReadout = linux::LinuxProductReadout; pub type PackageReadout = linux::LinuxPackageReadout; pub type NetworkReadout = linux::LinuxNetworkReadout; + pub type GpuReadout = linux::LinuxGpuReadout; } else if #[cfg(target_os = "macos")] { mod extra; mod macos; @@ -94,6 +95,7 @@ pub struct Readouts { pub product: ProductReadout, pub packages: PackageReadout, pub network: PackageReadout, + pub gpu: GpuReadout, } #[cfg(feature = "version")] diff --git a/src/linux/mod.rs b/src/linux/mod.rs index 23763e08..621e767c 100644 --- a/src/linux/mod.rs +++ b/src/linux/mod.rs @@ -1,12 +1,15 @@ #![allow(clippy::unnecessary_cast)] +mod pci_devices; mod sysinfo_ffi; +use self::pci_devices::get_pci_devices; use crate::extra; use crate::extra::get_entries; use crate::extra::path_extension; use crate::shared; use crate::traits::*; use itertools::Itertools; +use pciid_parser::Database; use regex::Regex; use std::fs; use std::fs::read_dir; @@ -41,6 +44,7 @@ pub struct LinuxBatteryReadout; pub struct LinuxProductReadout; pub struct LinuxPackageReadout; pub struct LinuxNetworkReadout; +pub struct LinuxGpuReadout; impl BatteryReadout for LinuxBatteryReadout { fn new() -> Self { @@ -901,3 +905,30 @@ impl LinuxPackageReadout { None } } + +impl GpuReadout for LinuxGpuReadout { + fn new() -> Self { + LinuxGpuReadout + } + + fn list_gpus(&self) -> Result, ReadoutError> { + let db = match Database::read() { + Ok(db) => db, + _ => panic!("Could not read pci.ids file"), + }; + let devices_path = Path::new("/sys/bus/pci/devices/"); + + let devices = get_pci_devices(devices_path)?; + let mut gpus = vec![]; + + for device in devices { + if !device.is_gpu(&db) { + continue; + }; + + gpus.push(device.get_sub_device_name(&db)); + } + + Ok(gpus) + } +} diff --git a/src/linux/pci_devices.rs b/src/linux/pci_devices.rs new file mode 100644 index 00000000..462466cd --- /dev/null +++ b/src/linux/pci_devices.rs @@ -0,0 +1,112 @@ +use std::{ + fs::{read_dir, read_to_string}, + io, + path::{Path, PathBuf}, +}; + +use pciid_parser::{schema::SubDeviceId, Database}; + +use crate::extra::pop_newline; + +fn parse_device_hex(hex_str: &str) -> String { + pop_newline(hex_str).chars().skip(2).collect::() +} + +pub enum PciDeviceReadableValues { + Class, + Vendor, + Device, + SubVendor, + SubDevice, +} + +impl PciDeviceReadableValues { + fn as_str(&self) -> &'static str { + match self { + PciDeviceReadableValues::Class => "class", + PciDeviceReadableValues::Vendor => "vendor", + PciDeviceReadableValues::Device => "device", + PciDeviceReadableValues::SubVendor => "subsystem_vendor", + PciDeviceReadableValues::SubDevice => "subsystem_device", + } + } +} + +#[derive(Debug)] +pub struct PciDevice { + base_path: PathBuf, +} + +impl PciDevice { + fn new(base_path: PathBuf) -> PciDevice { + PciDevice { base_path } + } + + fn _read_value(&self, readable_value: PciDeviceReadableValues) -> String { + let value_path = self.base_path.join(readable_value.as_str()); + + match read_to_string(&value_path) { + Ok(hex_string) => parse_device_hex(&hex_string), + _ => panic!("Could not find value: {:?}", value_path), + } + } + + pub fn is_gpu(&self, db: &Database) -> bool { + let class_value = self._read_value(PciDeviceReadableValues::Class); + let first_pair = class_value.chars().take(2).collect::(); + + match db.classes.get(&first_pair) { + Some(class) => class.name == "Display controller", + _ => false, + } + } + + pub fn get_sub_device_name(&self, db: &Database) -> String { + let vendor_value = self._read_value(PciDeviceReadableValues::Vendor); + let sub_vendor_value = self._read_value(PciDeviceReadableValues::SubVendor); + let device_value = self._read_value(PciDeviceReadableValues::Device); + let sub_device_value = self._read_value(PciDeviceReadableValues::SubDevice); + + let vendor = match db.vendors.get(&vendor_value) { + Some(vendor) => vendor, + _ => panic!("Could not find vendor for value: {}", vendor_value), + }; + + let device = match vendor.devices.get(&device_value) { + Some(device) => device, + _ => panic!("Could not find device for value: {}", device_value), + }; + + let sub_device_id = SubDeviceId { + subvendor: sub_vendor_value, + subdevice: sub_device_value, + }; + + match device.subdevices.get(&sub_device_id) { + Some(sub_device) => { + let start = match sub_device.find('[') { + Some(i) => i + 1, + _ => panic!( + "Could not find opening square bracket for sub device: {}", + sub_device + ), + }; + let end = sub_device.len() - 1; + + sub_device.chars().take(end).skip(start).collect::() + } + _ => panic!("Could not find sub device for id: {:?}", sub_device_id), + } + } +} + +pub fn get_pci_devices(devices_path: &Path) -> Result, io::Error> { + let devices_dir = read_dir(devices_path)?; + + let mut devices = vec![]; + for device_entry in devices_dir.flatten() { + devices.push(PciDevice::new(device_entry.path())); + } + + Ok(devices) +} diff --git a/src/traits.rs b/src/traits.rs index 44704890..42d29ce1 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -391,6 +391,38 @@ pub trait ProductReadout { fn product(&self) -> Result; } +/** +This trait provides the interface for getting information about the _GPU(s)_ connected +to the host machine. + +# Example + +``` +use libmacchina::traits::GpuReadout; +use libmacchina::traits::ReadoutError; + +pub struct LinuxGpuReadout; + +impl GpuReadout for LinuxGpuReadout { + fn new() -> Self { + LinuxGpuReadout + } + + fn list_gpus(&self) -> Result, ReadoutError> { + // Get gpu(s) from list of connected pci devices + Ok(vec!(String::from("gpu1"), String::from("gpu2"))) // Return gpu sub-device names + } +} +``` +*/ +pub trait GpuReadout { + /// Creates a new instance of the structure which implements this trait. + fn new() -> Self; + + /// This function is used for querying the currently connected gpu devices + fn list_gpus(&self) -> Result, ReadoutError>; +} + /** This trait provides the interface for implementing functionality used for querying general information about the running operating system and current user. From af6844ae48e526d651df7965b83fe3a6d0ec77d5 Mon Sep 17 00:00:00 2001 From: rolv Date: Wed, 15 Mar 2023 10:52:09 +0000 Subject: [PATCH 2/8] fix - try to fix some lint errors pointed out by workflow --- src/linux/mod.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/linux/mod.rs b/src/linux/mod.rs index 621e767c..68af6e45 100644 --- a/src/linux/mod.rs +++ b/src/linux/mod.rs @@ -534,11 +534,7 @@ impl GeneralReadout for LinuxGeneralReadout { if family == product && family == version { return Ok(family); } else if version.is_empty() || version.len() <= 22 { - return Ok(new_product - .split_whitespace() - .into_iter() - .unique() - .join(" ")); + return Ok(new_product.split_whitespace().unique().join(" ")); } Ok(version) @@ -788,7 +784,6 @@ impl LinuxPackageReadout { entries .iter() .filter(|x| extra::path_extension(x).unwrap_or_default() == "list") - .into_iter() .count() }) } @@ -897,7 +892,6 @@ impl LinuxPackageReadout { entries .iter() .filter(|&x| path_extension(x).unwrap_or_default() == "snap") - .into_iter() .count(), ); } From e1b488b670817fa59a7e98630c440608d92853ec Mon Sep 17 00:00:00 2001 From: rolv Date: Thu, 16 Mar 2023 22:53:28 +0000 Subject: [PATCH 3/8] change - remove gpu readout trait and locally define path to pci devices --- src/lib.rs | 2 -- src/linux/mod.rs | 50 ++++++++++++++++++---------------------- src/linux/pci_devices.rs | 6 ++--- src/traits.rs | 32 ------------------------- 4 files changed, 25 insertions(+), 65 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 2f028245..b8f60e0f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,7 +24,6 @@ cfg_if! { pub type ProductReadout = linux::LinuxProductReadout; pub type PackageReadout = linux::LinuxPackageReadout; pub type NetworkReadout = linux::LinuxNetworkReadout; - pub type GpuReadout = linux::LinuxGpuReadout; } else if #[cfg(target_os = "macos")] { mod extra; mod macos; @@ -95,7 +94,6 @@ pub struct Readouts { pub product: ProductReadout, pub packages: PackageReadout, pub network: PackageReadout, - pub gpu: GpuReadout, } #[cfg(feature = "version")] diff --git a/src/linux/mod.rs b/src/linux/mod.rs index 68af6e45..bce4563c 100644 --- a/src/linux/mod.rs +++ b/src/linux/mod.rs @@ -44,7 +44,6 @@ pub struct LinuxBatteryReadout; pub struct LinuxProductReadout; pub struct LinuxPackageReadout; pub struct LinuxNetworkReadout; -pub struct LinuxGpuReadout; impl BatteryReadout for LinuxBatteryReadout { fn new() -> Self { @@ -549,6 +548,28 @@ impl GeneralReadout for LinuxGeneralReadout { } } +impl LinuxGeneralReadout { + pub fn list_gpus(&self) -> Result, ReadoutError> { + let db = match Database::read() { + Ok(db) => db, + _ => panic!("Could not read pci.ids file"), + }; + + let devices = get_pci_devices()?; + let mut gpus = vec![]; + + for device in devices { + if !device.is_gpu(&db) { + continue; + }; + + gpus.push(device.get_sub_device_name(&db)); + } + + Ok(gpus) + } +} + impl MemoryReadout for LinuxMemoryReadout { fn new() -> Self { LinuxMemoryReadout { @@ -899,30 +920,3 @@ impl LinuxPackageReadout { None } } - -impl GpuReadout for LinuxGpuReadout { - fn new() -> Self { - LinuxGpuReadout - } - - fn list_gpus(&self) -> Result, ReadoutError> { - let db = match Database::read() { - Ok(db) => db, - _ => panic!("Could not read pci.ids file"), - }; - let devices_path = Path::new("/sys/bus/pci/devices/"); - - let devices = get_pci_devices(devices_path)?; - let mut gpus = vec![]; - - for device in devices { - if !device.is_gpu(&db) { - continue; - }; - - gpus.push(device.get_sub_device_name(&db)); - } - - Ok(gpus) - } -} diff --git a/src/linux/pci_devices.rs b/src/linux/pci_devices.rs index 462466cd..a8291127 100644 --- a/src/linux/pci_devices.rs +++ b/src/linux/pci_devices.rs @@ -1,7 +1,7 @@ use std::{ fs::{read_dir, read_to_string}, io, - path::{Path, PathBuf}, + path::PathBuf, }; use pciid_parser::{schema::SubDeviceId, Database}; @@ -100,8 +100,8 @@ impl PciDevice { } } -pub fn get_pci_devices(devices_path: &Path) -> Result, io::Error> { - let devices_dir = read_dir(devices_path)?; +pub fn get_pci_devices() -> Result, io::Error> { + let devices_dir = read_dir("/sys/bus/pci/devices/")?; let mut devices = vec![]; for device_entry in devices_dir.flatten() { diff --git a/src/traits.rs b/src/traits.rs index 42d29ce1..44704890 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -391,38 +391,6 @@ pub trait ProductReadout { fn product(&self) -> Result; } -/** -This trait provides the interface for getting information about the _GPU(s)_ connected -to the host machine. - -# Example - -``` -use libmacchina::traits::GpuReadout; -use libmacchina::traits::ReadoutError; - -pub struct LinuxGpuReadout; - -impl GpuReadout for LinuxGpuReadout { - fn new() -> Self { - LinuxGpuReadout - } - - fn list_gpus(&self) -> Result, ReadoutError> { - // Get gpu(s) from list of connected pci devices - Ok(vec!(String::from("gpu1"), String::from("gpu2"))) // Return gpu sub-device names - } -} -``` -*/ -pub trait GpuReadout { - /// Creates a new instance of the structure which implements this trait. - fn new() -> Self; - - /// This function is used for querying the currently connected gpu devices - fn list_gpus(&self) -> Result, ReadoutError>; -} - /** This trait provides the interface for implementing functionality used for querying general information about the running operating system and current user. From 83cde418f36eacd6721d81a059cb49da6574d3c5 Mon Sep 17 00:00:00 2001 From: rolv Date: Fri, 17 Mar 2023 12:07:05 +0000 Subject: [PATCH 4/8] include list_gpus function in GeneralReadout trait --- src/linux/mod.rs | 4 +--- src/traits.rs | 8 ++++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/linux/mod.rs b/src/linux/mod.rs index bce4563c..ec18ee41 100644 --- a/src/linux/mod.rs +++ b/src/linux/mod.rs @@ -546,10 +546,8 @@ impl GeneralReadout for LinuxGeneralReadout { fn disk_space(&self) -> Result<(u128, u128), ReadoutError> { shared::disk_space(String::from("/")) } -} -impl LinuxGeneralReadout { - pub fn list_gpus(&self) -> Result, ReadoutError> { + fn list_gpus(&self) -> Result, ReadoutError> { let db = match Database::read() { Ok(db) => db, _ => panic!("Could not read pci.ids file"), diff --git a/src/traits.rs b/src/traits.rs index 44704890..9fd6c880 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -483,6 +483,11 @@ impl GeneralReadout for MacOSGeneralReadout { fn disk_space(&self) -> Result<(u128, u128), ReadoutError> { Ok((50000000,1000000000)) // Used / Total } + + fn list_gpus(&self) -> Result, ReadoutError> { + // Get gpu(s) from list of connected pci devices + Ok(vec!(String::from("gpu1"), String::from("gpu2"))) // Return gpu sub-device names + } } ``` @@ -581,6 +586,9 @@ pub trait GeneralReadout { /// /// _e.g._ '1.2TB / 2TB' fn disk_space(&self) -> Result<(u128, u128), ReadoutError>; + + /// This function should return the sub device names of any _GPU(s)_ connected to the host machine. + fn list_gpus(&self) -> Result, ReadoutError>; } /// Holds the possible variants for battery status. From 91e2e52ac835859630a3ac8ca42798c74ac81570 Mon Sep 17 00:00:00 2001 From: rolv Date: Fri, 17 Mar 2023 12:47:21 +0000 Subject: [PATCH 5/8] rename list_gpus to gpu --- src/linux/mod.rs | 2 +- src/traits.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/linux/mod.rs b/src/linux/mod.rs index ec18ee41..a587cdcf 100644 --- a/src/linux/mod.rs +++ b/src/linux/mod.rs @@ -547,7 +547,7 @@ impl GeneralReadout for LinuxGeneralReadout { shared::disk_space(String::from("/")) } - fn list_gpus(&self) -> Result, ReadoutError> { + fn gpu(&self) -> Result, ReadoutError> { let db = match Database::read() { Ok(db) => db, _ => panic!("Could not read pci.ids file"), diff --git a/src/traits.rs b/src/traits.rs index 9fd6c880..5405466a 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -484,7 +484,7 @@ impl GeneralReadout for MacOSGeneralReadout { Ok((50000000,1000000000)) // Used / Total } - fn list_gpus(&self) -> Result, ReadoutError> { + fn gpu(&self) -> Result, ReadoutError> { // Get gpu(s) from list of connected pci devices Ok(vec!(String::from("gpu1"), String::from("gpu2"))) // Return gpu sub-device names } @@ -588,7 +588,7 @@ pub trait GeneralReadout { fn disk_space(&self) -> Result<(u128, u128), ReadoutError>; /// This function should return the sub device names of any _GPU(s)_ connected to the host machine. - fn list_gpus(&self) -> Result, ReadoutError>; + fn gpu(&self) -> Result, ReadoutError>; } /// Holds the possible variants for battery status. From 2068884a9d12a040ed73ec74d09742a3269804fa Mon Sep 17 00:00:00 2001 From: rolv Date: Fri, 17 Mar 2023 12:47:21 +0000 Subject: [PATCH 6/8] rename list_gpus to gpu --- src/linux/mod.rs | 2 +- src/traits.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/linux/mod.rs b/src/linux/mod.rs index a587cdcf..bcda22c1 100644 --- a/src/linux/mod.rs +++ b/src/linux/mod.rs @@ -547,7 +547,7 @@ impl GeneralReadout for LinuxGeneralReadout { shared::disk_space(String::from("/")) } - fn gpu(&self) -> Result, ReadoutError> { + fn gpus(&self) -> Result, ReadoutError> { let db = match Database::read() { Ok(db) => db, _ => panic!("Could not read pci.ids file"), diff --git a/src/traits.rs b/src/traits.rs index 5405466a..a39d6382 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -484,7 +484,7 @@ impl GeneralReadout for MacOSGeneralReadout { Ok((50000000,1000000000)) // Used / Total } - fn gpu(&self) -> Result, ReadoutError> { + fn gpus(&self) -> Result, ReadoutError> { // Get gpu(s) from list of connected pci devices Ok(vec!(String::from("gpu1"), String::from("gpu2"))) // Return gpu sub-device names } @@ -588,7 +588,7 @@ pub trait GeneralReadout { fn disk_space(&self) -> Result<(u128, u128), ReadoutError>; /// This function should return the sub device names of any _GPU(s)_ connected to the host machine. - fn gpu(&self) -> Result, ReadoutError>; + fn gpus(&self) -> Result, ReadoutError>; } /// Holds the possible variants for battery status. From aac8a8df06832fcb1a85e6929b39a29ff69375d1 Mon Sep 17 00:00:00 2001 From: rolv Date: Fri, 17 Mar 2023 15:15:36 +0000 Subject: [PATCH 7/8] define gpus function for all OSes other than Linux that returns a not implemented error --- src/android/mod.rs | 4 ++++ src/freebsd/mod.rs | 4 ++++ src/macos/mod.rs | 4 ++++ src/netbsd/mod.rs | 4 ++++ src/openwrt/mod.rs | 4 ++++ src/windows/mod.rs | 4 ++++ 6 files changed, 24 insertions(+) diff --git a/src/android/mod.rs b/src/android/mod.rs index 6d90dd4a..6373008f 100644 --- a/src/android/mod.rs +++ b/src/android/mod.rs @@ -288,6 +288,10 @@ impl GeneralReadout for AndroidGeneralReadout { fn disk_space(&self) -> Result<(u128, u128), ReadoutError> { Err(ReadoutError::NotImplemented) } + + fn gpus(&self) -> Result, ReadoutError> { + Err(ReadoutError::NotImplemented) + } } impl MemoryReadout for AndroidMemoryReadout { diff --git a/src/freebsd/mod.rs b/src/freebsd/mod.rs index ee988ec0..724e2ef6 100644 --- a/src/freebsd/mod.rs +++ b/src/freebsd/mod.rs @@ -297,6 +297,10 @@ impl GeneralReadout for FreeBSDGeneralReadout { fn disk_space(&self) -> Result<(u128, u128), ReadoutError> { shared::disk_space(String::from("/")) } + + fn gpus(&self) -> Result, ReadoutError> { + Err(ReadoutError::NotImplemented) + } } impl MemoryReadout for FreeBSDMemoryReadout { diff --git a/src/macos/mod.rs b/src/macos/mod.rs index 3d5f1e3c..c9114880 100644 --- a/src/macos/mod.rs +++ b/src/macos/mod.rs @@ -403,6 +403,10 @@ impl GeneralReadout for MacOSGeneralReadout { fn disk_space(&self) -> Result<(u128, u128), ReadoutError> { shared::disk_space(String::from("/")) } + + fn gpus(&self) -> Result, ReadoutError> { + Err(ReadoutError::NotImplemented) + } } impl MacOSGeneralReadout { diff --git a/src/netbsd/mod.rs b/src/netbsd/mod.rs index aa936a60..660a7572 100644 --- a/src/netbsd/mod.rs +++ b/src/netbsd/mod.rs @@ -337,6 +337,10 @@ impl GeneralReadout for NetBSDGeneralReadout { "Error while trying to get statfs structure.", ))) } + + fn gpus(&self) -> Result, ReadoutError> { + Err(ReadoutError::NotImplemented) + } } impl MemoryReadout for NetBSDMemoryReadout { diff --git a/src/openwrt/mod.rs b/src/openwrt/mod.rs index 519c5598..c9183ee8 100644 --- a/src/openwrt/mod.rs +++ b/src/openwrt/mod.rs @@ -214,6 +214,10 @@ impl GeneralReadout for OpenWrtGeneralReadout { fn disk_space(&self) -> Result<(u128, u128), ReadoutError> { shared::disk_space(String::from("/")) } + + fn gpus(&self) -> Result, ReadoutError> { + Err(ReadoutError::NotImplemented) + } } impl MemoryReadout for OpenWrtMemoryReadout { diff --git a/src/windows/mod.rs b/src/windows/mod.rs index 8256600e..c7cbafeb 100644 --- a/src/windows/mod.rs +++ b/src/windows/mod.rs @@ -332,6 +332,10 @@ impl GeneralReadout for WindowsGeneralReadout { fn disk_space(&self) -> Result<(u128, u128), ReadoutError> { Err(ReadoutError::NotImplemented) } + + fn gpus(&self) -> Result, ReadoutError> { + Err(ReadoutError::NotImplemented) + } } pub struct WindowsProductReadout { From ece67ac465f0bcba42fa25cc24bb8fc9f21c5e93 Mon Sep 17 00:00:00 2001 From: rolv Date: Sat, 18 Mar 2023 13:04:49 +0000 Subject: [PATCH 8/8] skip devices which don't match any value in the pci.ids db and return error if gpus vec is empty after checking all pci devices --- src/linux/mod.rs | 10 ++++++++-- src/linux/pci_devices.rs | 39 ++++++++++++++++++--------------------- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/src/linux/mod.rs b/src/linux/mod.rs index bcda22c1..3a195523 100644 --- a/src/linux/mod.rs +++ b/src/linux/mod.rs @@ -561,10 +561,16 @@ impl GeneralReadout for LinuxGeneralReadout { continue; }; - gpus.push(device.get_sub_device_name(&db)); + if let Some(sub_device_name) = device.get_sub_device_name(&db) { + gpus.push(sub_device_name); + }; } - Ok(gpus) + if gpus.is_empty() { + Err(ReadoutError::MetricNotAvailable) + } else { + Ok(gpus) + } } } diff --git a/src/linux/pci_devices.rs b/src/linux/pci_devices.rs index a8291127..788ebfa4 100644 --- a/src/linux/pci_devices.rs +++ b/src/linux/pci_devices.rs @@ -61,20 +61,18 @@ impl PciDevice { } } - pub fn get_sub_device_name(&self, db: &Database) -> String { + pub fn get_sub_device_name(&self, db: &Database) -> Option { let vendor_value = self._read_value(PciDeviceReadableValues::Vendor); let sub_vendor_value = self._read_value(PciDeviceReadableValues::SubVendor); let device_value = self._read_value(PciDeviceReadableValues::Device); let sub_device_value = self._read_value(PciDeviceReadableValues::SubDevice); - let vendor = match db.vendors.get(&vendor_value) { - Some(vendor) => vendor, - _ => panic!("Could not find vendor for value: {}", vendor_value), + let Some(vendor) = db.vendors.get(&vendor_value) else { + return None; }; - let device = match vendor.devices.get(&device_value) { - Some(device) => device, - _ => panic!("Could not find device for value: {}", device_value), + let Some(device) = vendor.devices.get(&device_value) else { + return None; }; let sub_device_id = SubDeviceId { @@ -82,20 +80,19 @@ impl PciDevice { subdevice: sub_device_value, }; - match device.subdevices.get(&sub_device_id) { - Some(sub_device) => { - let start = match sub_device.find('[') { - Some(i) => i + 1, - _ => panic!( - "Could not find opening square bracket for sub device: {}", - sub_device - ), - }; - let end = sub_device.len() - 1; - - sub_device.chars().take(end).skip(start).collect::() - } - _ => panic!("Could not find sub device for id: {:?}", sub_device_id), + if let Some(sub_device) = device.subdevices.get(&sub_device_id) { + let start = match sub_device.find('[') { + Some(i) => i + 1, + _ => panic!( + "Could not find opening square bracket for sub device: {}", + sub_device + ), + }; + let end = sub_device.len() - 1; + + Some(sub_device.chars().take(end).skip(start).collect::()) + } else { + None } } }