nvml_wrapper/enums/
device.rs

1use std::convert::TryFrom;
2use std::fmt::Display;
3use std::os::raw::c_uint;
4
5use crate::enum_wrappers::device::{ClockLimitId, SampleValueType};
6use crate::error::NvmlError;
7use crate::ffi::bindings::*;
8#[cfg(feature = "serde")]
9use serde_derive::{Deserialize, Serialize};
10
11/// Respresents possible variants for a firmware version.
12#[derive(Debug, Clone, Eq, PartialEq, Hash)]
13#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
14pub enum FirmwareVersion {
15    /// The version is unavailable.
16    Unavailable,
17    Version(u32),
18}
19
20impl From<u32> for FirmwareVersion {
21    fn from(value: u32) -> Self {
22        match value {
23            0 => FirmwareVersion::Unavailable,
24            _ => FirmwareVersion::Version(value),
25        }
26    }
27}
28
29/// Represents possible variants for used GPU memory.
30// Checked
31#[derive(Debug, Clone, Eq, PartialEq, Hash)]
32#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
33pub enum UsedGpuMemory {
34    /// Under WDDM, `NVML_VALUE_NOT_AVAILABLE` is always reported because
35    /// Windows KMD manages all the memory, not the NVIDIA driver.
36    Unavailable,
37    /// Memory used in bytes.
38    Used(u64),
39}
40
41impl From<u64> for UsedGpuMemory {
42    fn from(value: u64) -> Self {
43        let not_available = (NVML_VALUE_NOT_AVAILABLE) as u64;
44
45        match value {
46            v if v == not_available => UsedGpuMemory::Unavailable,
47            _ => UsedGpuMemory::Used(value),
48        }
49    }
50}
51
52/// Represents different types of sample values.
53// Checked against local
54#[derive(Debug, Clone, PartialEq)]
55#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
56pub enum SampleValue {
57    F64(f64),
58    U32(u32),
59    U64(u64),
60    I64(i64),
61}
62
63impl SampleValue {
64    pub fn from_tag_and_union(tag: &SampleValueType, union: nvmlValue_t) -> Self {
65        use self::SampleValueType::*;
66
67        unsafe {
68            match *tag {
69                Double => SampleValue::F64(union.dVal),
70                UnsignedInt => SampleValue::U32(union.uiVal),
71                // Methodology: NVML supports 32-bit Linux. UL is u32 on that platform.
72                // NVML wouldn't return anything larger
73                #[allow(clippy::unnecessary_cast)]
74                UnsignedLong => SampleValue::U32(union.ulVal as u32),
75                UnsignedLongLong => SampleValue::U64(union.ullVal),
76                SignedLongLong => SampleValue::I64(union.sllVal),
77            }
78        }
79    }
80}
81
82/// Represents different types of sample values.
83#[derive(Debug, Clone, Eq, PartialEq, Hash)]
84#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
85pub enum GpuLockedClocksSetting {
86    /// Numeric setting that allows you to explicitly define minimum and
87    /// maximum clock frequencies.
88    Numeric {
89        min_clock_mhz: u32,
90        max_clock_mhz: u32,
91    },
92    /// Symbolic setting that allows you to define lower and upper bounds for
93    /// clock speed with various possibilities.
94    ///
95    /// Not all combinations of `lower_bound` and `upper_bound` are valid.
96    /// Please see the docs for `nvmlDeviceSetGpuLockedClocks` in `nvml.h` to
97    /// learn more.
98    Symbolic {
99        lower_bound: ClockLimitId,
100        upper_bound: ClockLimitId,
101    },
102}
103
104impl GpuLockedClocksSetting {
105    /// Returns `(min_clock_mhz, max_clock_mhz)`.
106    pub fn into_min_and_max_clocks(self) -> (u32, u32) {
107        match self {
108            GpuLockedClocksSetting::Numeric {
109                min_clock_mhz,
110                max_clock_mhz,
111            } => (min_clock_mhz, max_clock_mhz),
112            GpuLockedClocksSetting::Symbolic {
113                lower_bound,
114                upper_bound,
115            } => (lower_bound.as_c(), upper_bound.as_c()),
116        }
117    }
118}
119
120/// Returned by [`crate::Device::bus_type()`].
121// TODO: technically this is an "enum wrapper" but the type on the C side isn't
122// an enum
123#[derive(Debug, Clone, Eq, PartialEq, Hash)]
124#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
125pub enum BusType {
126    /// Unknown bus type.
127    Unknown,
128    /// PCI (Peripheral Component Interconnect) bus type.
129    Pci,
130    /// PCIE (Peripheral Component Interconnect Express) bus type.
131    ///
132    /// This is the most common bus type.
133    Pcie,
134    /// FPCI (Fast Peripheral Component Interconnect) bus type.
135    Fpci,
136    /// AGP (Accelerated Graphics Port) bus type.
137    ///
138    /// This is old and was dropped in favor of PCIE.
139    Agp,
140}
141
142impl BusType {
143    /// Returns the C constant equivalent for the given Rust enum variant.
144    pub fn as_c(&self) -> nvmlBusType_t {
145        match *self {
146            Self::Unknown => NVML_BUS_TYPE_UNKNOWN,
147            Self::Pci => NVML_BUS_TYPE_PCI,
148            Self::Pcie => NVML_BUS_TYPE_PCIE,
149            Self::Fpci => NVML_BUS_TYPE_FPCI,
150            Self::Agp => NVML_BUS_TYPE_AGP,
151        }
152    }
153}
154
155impl TryFrom<nvmlBusType_t> for BusType {
156    type Error = NvmlError;
157
158    fn try_from(data: nvmlBusType_t) -> Result<Self, Self::Error> {
159        match data {
160            NVML_BUS_TYPE_UNKNOWN => Ok(Self::Unknown),
161            NVML_BUS_TYPE_PCI => Ok(Self::Pci),
162            NVML_BUS_TYPE_PCIE => Ok(Self::Pcie),
163            NVML_BUS_TYPE_FPCI => Ok(Self::Fpci),
164            NVML_BUS_TYPE_AGP => Ok(Self::Agp),
165            _ => Err(NvmlError::UnexpectedVariant(data)),
166        }
167    }
168}
169
170/// Returned by [`crate::Device::power_source()`].
171// TODO: technically this is an "enum wrapper" but the type on the C side isn't
172// an enum
173#[derive(Debug, Clone, Eq, PartialEq, Hash)]
174#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
175pub enum PowerSource {
176    /// AC power (receiving power from some external source).
177    Ac,
178    /// Battery power.
179    Battery,
180}
181
182impl PowerSource {
183    /// Returns the C constant equivalent for the given Rust enum variant.
184    pub fn as_c(&self) -> nvmlPowerSource_t {
185        match *self {
186            Self::Ac => NVML_POWER_SOURCE_AC,
187            Self::Battery => NVML_POWER_SOURCE_BATTERY,
188        }
189    }
190}
191
192impl TryFrom<nvmlPowerSource_t> for PowerSource {
193    type Error = NvmlError;
194
195    fn try_from(data: nvmlPowerSource_t) -> Result<Self, Self::Error> {
196        match data {
197            NVML_POWER_SOURCE_AC => Ok(Self::Ac),
198            NVML_POWER_SOURCE_BATTERY => Ok(Self::Battery),
199            _ => Err(NvmlError::UnexpectedVariant(data)),
200        }
201    }
202}
203
204/// Returned by [`crate::Device::architecture()`].
205///
206/// This is the simplified chip architecture of the device.
207// TODO: technically this is an "enum wrapper" but the type on the C side isn't
208// an enum
209#[derive(Debug, Clone, Eq, PartialEq, Hash)]
210#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
211pub enum DeviceArchitecture {
212    /// <https://en.wikipedia.org/wiki/Kepler_(microarchitecture)>
213    Kepler,
214    /// <https://en.wikipedia.org/wiki/Maxwell_(microarchitecture)>
215    Maxwell,
216    /// <https://en.wikipedia.org/wiki/Pascal_(microarchitecture)>
217    Pascal,
218    /// <https://en.wikipedia.org/wiki/Volta_(microarchitecture)>
219    Volta,
220    /// <https://en.wikipedia.org/wiki/Turing_(microarchitecture)>
221    Turing,
222    /// <https://en.wikipedia.org/wiki/Ampere_(microarchitecture)>
223    Ampere,
224    /// <https://en.wikipedia.org/wiki/Ada_Lovelace_(microarchitecture)>
225    Ada,
226    /// <https://en.wikipedia.org/wiki/Hopper_(microarchitecture)>
227    Hopper,
228    /// https://en.wikipedia.org/wiki/Blackwell_(microarchitecture)
229    Blackwell,
230    /// Unknown device architecture (most likely something newer).
231    Unknown,
232}
233
234impl DeviceArchitecture {
235    /// Returns the C constant equivalent for the given Rust enum variant.
236    pub fn as_c(&self) -> nvmlDeviceArchitecture_t {
237        match *self {
238            Self::Kepler => NVML_DEVICE_ARCH_KEPLER,
239            Self::Maxwell => NVML_DEVICE_ARCH_MAXWELL,
240            Self::Pascal => NVML_DEVICE_ARCH_PASCAL,
241            Self::Volta => NVML_DEVICE_ARCH_VOLTA,
242            Self::Turing => NVML_DEVICE_ARCH_TURING,
243            Self::Ampere => NVML_DEVICE_ARCH_AMPERE,
244            Self::Ada => NVML_DEVICE_ARCH_ADA,
245            Self::Hopper => NVML_DEVICE_ARCH_HOPPER,
246            Self::Blackwell => NVML_DEVICE_ARCH_BLACKWELL,
247            Self::Unknown => NVML_DEVICE_ARCH_UNKNOWN,
248        }
249    }
250}
251
252impl TryFrom<nvmlDeviceArchitecture_t> for DeviceArchitecture {
253    type Error = NvmlError;
254
255    fn try_from(data: nvmlDeviceArchitecture_t) -> Result<Self, Self::Error> {
256        match data {
257            NVML_DEVICE_ARCH_KEPLER => Ok(Self::Kepler),
258            NVML_DEVICE_ARCH_MAXWELL => Ok(Self::Maxwell),
259            NVML_DEVICE_ARCH_PASCAL => Ok(Self::Pascal),
260            NVML_DEVICE_ARCH_VOLTA => Ok(Self::Volta),
261            NVML_DEVICE_ARCH_TURING => Ok(Self::Turing),
262            NVML_DEVICE_ARCH_AMPERE => Ok(Self::Ampere),
263            NVML_DEVICE_ARCH_ADA => Ok(Self::Ada),
264            NVML_DEVICE_ARCH_HOPPER => Ok(Self::Hopper),
265            NVML_DEVICE_ARCH_BLACKWELL => Ok(Self::Blackwell),
266            NVML_DEVICE_ARCH_UNKNOWN => Ok(Self::Unknown),
267            _ => Err(NvmlError::UnexpectedVariant(data)),
268        }
269    }
270}
271
272impl Display for DeviceArchitecture {
273    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
274        match self {
275            Self::Kepler => f.write_str("Kepler"),
276            Self::Maxwell => f.write_str("Maxwell"),
277            Self::Pascal => f.write_str("Pascal"),
278            Self::Volta => f.write_str("Volta"),
279            Self::Turing => f.write_str("Turing"),
280            Self::Ampere => f.write_str("Ampere"),
281            Self::Ada => f.write_str("Ada"),
282            Self::Hopper => f.write_str("Hopper"),
283            Self::Blackwell => f.write_str("Blackwell"),
284            Self::Unknown => f.write_str("Unknown"),
285        }
286    }
287}
288
289/// Returned by [`crate::Device::max_pcie_link_speed()`].
290///
291/// Note, the NVML header says these are all MBPS (Megabytes Per Second) but
292/// they don't line up with the throughput numbers on this page:
293/// <https://en.wikipedia.org/wiki/PCI_Express>
294///
295/// They _do_ line up with the "transfer rate per lane" numbers, though. This
296/// would mean they represent transfer speeds rather than throughput, in MT/s.
297///
298/// See also the discussion on [`crate::Device::pcie_link_speed()`].
299// TODO: technically this is an "enum wrapper" but the type on the C side isn't
300// an enum
301#[derive(Debug, Clone, Eq, PartialEq, Hash)]
302#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
303pub enum PcieLinkMaxSpeed {
304    Invalid,
305    MegaTransfersPerSecond2500,
306    MegaTransfersPerSecond5000,
307    MegaTransfersPerSecond8000,
308    MegaTransfersPerSecond16000,
309    MegaTransfersPerSecond32000,
310}
311
312impl PcieLinkMaxSpeed {
313    /// Returns the numerical equivalent for the given enum variant, if valid.
314    pub fn as_integer(&self) -> Option<u32> {
315        Some(match self {
316            PcieLinkMaxSpeed::Invalid => return None,
317            PcieLinkMaxSpeed::MegaTransfersPerSecond2500 => 2500,
318            PcieLinkMaxSpeed::MegaTransfersPerSecond5000 => 5000,
319            PcieLinkMaxSpeed::MegaTransfersPerSecond8000 => 8000,
320            PcieLinkMaxSpeed::MegaTransfersPerSecond16000 => 16000,
321            PcieLinkMaxSpeed::MegaTransfersPerSecond32000 => 32000,
322        })
323    }
324
325    /// Returns the C constant equivalent for the given Rust enum variant.
326    pub fn as_c(&self) -> c_uint {
327        match *self {
328            Self::Invalid => NVML_PCIE_LINK_MAX_SPEED_INVALID,
329            Self::MegaTransfersPerSecond2500 => NVML_PCIE_LINK_MAX_SPEED_2500MBPS,
330            Self::MegaTransfersPerSecond5000 => NVML_PCIE_LINK_MAX_SPEED_5000MBPS,
331            Self::MegaTransfersPerSecond8000 => NVML_PCIE_LINK_MAX_SPEED_8000MBPS,
332            Self::MegaTransfersPerSecond16000 => NVML_PCIE_LINK_MAX_SPEED_16000MBPS,
333            Self::MegaTransfersPerSecond32000 => NVML_PCIE_LINK_MAX_SPEED_32000MBPS,
334        }
335    }
336}
337
338impl TryFrom<c_uint> for PcieLinkMaxSpeed {
339    type Error = NvmlError;
340
341    fn try_from(data: c_uint) -> Result<Self, Self::Error> {
342        match data {
343            NVML_PCIE_LINK_MAX_SPEED_INVALID => Ok(Self::Invalid),
344            NVML_PCIE_LINK_MAX_SPEED_2500MBPS => Ok(Self::MegaTransfersPerSecond2500),
345            NVML_PCIE_LINK_MAX_SPEED_5000MBPS => Ok(Self::MegaTransfersPerSecond5000),
346            NVML_PCIE_LINK_MAX_SPEED_8000MBPS => Ok(Self::MegaTransfersPerSecond8000),
347            NVML_PCIE_LINK_MAX_SPEED_16000MBPS => Ok(Self::MegaTransfersPerSecond16000),
348            NVML_PCIE_LINK_MAX_SPEED_32000MBPS => Ok(Self::MegaTransfersPerSecond32000),
349            _ => Err(NvmlError::UnexpectedVariant(data)),
350        }
351    }
352}
353
354#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
355#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
356#[repr(u32)]
357pub enum FanControlPolicy {
358    TemperatureContinousSw = NVML_FAN_POLICY_TEMPERATURE_CONTINOUS_SW,
359    Manual = NVML_FAN_POLICY_MANUAL,
360}
361
362/// Returned by [`crate::Device::get_fan_control_policy()`].
363///
364/// Policy used for fan control.
365// TODO: technically this is an "enum wrapper" but the type on the C side isn't
366// an enum
367impl FanControlPolicy {
368    pub fn as_c(&self) -> nvmlFanControlPolicy_t {
369        *self as u32
370    }
371}
372
373impl TryFrom<nvmlFanControlPolicy_t> for FanControlPolicy {
374    type Error = NvmlError;
375
376    fn try_from(value: nvmlFanControlPolicy_t) -> Result<Self, Self::Error> {
377        match value {
378            NVML_FAN_POLICY_TEMPERATURE_CONTINOUS_SW => Ok(Self::TemperatureContinousSw),
379            NVML_FAN_POLICY_MANUAL => Ok(Self::Manual),
380            _ => Err(NvmlError::UnexpectedVariant(value)),
381        }
382    }
383}