mirror of
https://gitlab.steamos.cloud/holo/steamos-manager.git
synced 2025-07-05 06:00:30 -04:00
hardware: Split out device type detection, add initial identification of Legion Go S
This commit is contained in:
parent
cd9558fd67
commit
7d8bd602a7
5 changed files with 147 additions and 64 deletions
125
src/hardware.rs
125
src/hardware.rs
|
@ -19,15 +19,24 @@ use crate::systemd::SystemdUnit;
|
|||
|
||||
const SYS_VENDOR_PATH: &str = "/sys/class/dmi/id/sys_vendor";
|
||||
const BOARD_NAME_PATH: &str = "/sys/class/dmi/id/board_name";
|
||||
const PRODUCT_NAME_PATH: &str = "/sys/class/dmi/id/product_name";
|
||||
|
||||
#[derive(PartialEq, Debug, Default, Copy, Clone)]
|
||||
pub(crate) enum HardwareVariant {
|
||||
pub(crate) enum SteamDeckVariant {
|
||||
#[default]
|
||||
Unknown,
|
||||
Jupiter,
|
||||
Galileo,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Default, Copy, Clone)]
|
||||
pub(crate) enum DeviceType {
|
||||
#[default]
|
||||
Unknown,
|
||||
SteamDeck,
|
||||
LegionGoS,
|
||||
}
|
||||
|
||||
#[derive(Display, EnumString, PartialEq, Debug, Copy, Clone, TryFromPrimitive)]
|
||||
#[strum(ascii_case_insensitive)]
|
||||
#[repr(u32)]
|
||||
|
@ -38,13 +47,13 @@ pub enum FanControlState {
|
|||
Os = 1,
|
||||
}
|
||||
|
||||
impl FromStr for HardwareVariant {
|
||||
impl FromStr for SteamDeckVariant {
|
||||
type Err = Error;
|
||||
fn from_str(input: &str) -> Result<HardwareVariant, Self::Err> {
|
||||
fn from_str(input: &str) -> Result<SteamDeckVariant, Self::Err> {
|
||||
Ok(match input {
|
||||
"Jupiter" => HardwareVariant::Jupiter,
|
||||
"Galileo" => HardwareVariant::Galileo,
|
||||
_ => HardwareVariant::Unknown,
|
||||
"Jupiter" => SteamDeckVariant::Jupiter,
|
||||
"Galileo" => SteamDeckVariant::Galileo,
|
||||
_ => SteamDeckVariant::Unknown,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -58,21 +67,27 @@ pub enum FactoryResetKind {
|
|||
All = 3,
|
||||
}
|
||||
|
||||
pub(crate) async fn variant() -> Result<HardwareVariant> {
|
||||
pub(crate) async fn steam_deck_variant() -> Result<SteamDeckVariant> {
|
||||
let sys_vendor = fs::read_to_string(path(SYS_VENDOR_PATH)).await?;
|
||||
if sys_vendor.trim_end() != "Valve" {
|
||||
return Ok(HardwareVariant::Unknown);
|
||||
return Ok(SteamDeckVariant::Unknown);
|
||||
}
|
||||
|
||||
let board_name = fs::read_to_string(path(BOARD_NAME_PATH)).await?;
|
||||
HardwareVariant::from_str(board_name.trim_end())
|
||||
SteamDeckVariant::from_str(board_name.trim_end())
|
||||
}
|
||||
|
||||
pub(crate) async fn is_deck() -> Result<bool> {
|
||||
match variant().await {
|
||||
Ok(variant) => Ok(variant != HardwareVariant::Unknown),
|
||||
Err(e) => Err(e),
|
||||
pub(crate) async fn device_type() -> Result<DeviceType> {
|
||||
if variant().await? != SteamDeckVariant::Unknown {
|
||||
return Ok(DeviceType::SteamDeck);
|
||||
}
|
||||
let board_vendor = fs::read_to_string(path(SYS_VENDOR_PATH)).await?;
|
||||
if board_vendor.trim_end() == "LENOVO" {
|
||||
let product_name = fs::read_to_string(path(PRODUCT_NAME_PATH)).await?;
|
||||
if ["83L3", "83N6", "83Q2", "83Q3"].contains(&product_name.trim_end()) {
|
||||
return Ok(DeviceType::LegionGoS);
|
||||
}
|
||||
}
|
||||
Ok(DeviceType::Unknown)
|
||||
}
|
||||
|
||||
pub(crate) struct FanControl {
|
||||
|
@ -153,15 +168,15 @@ pub mod test {
|
|||
use zbus::fdo;
|
||||
use zbus::zvariant::{ObjectPath, OwnedObjectPath};
|
||||
|
||||
pub(crate) async fn fake_model(model: HardwareVariant) -> Result<()> {
|
||||
pub(crate) async fn fake_model(model: SteamDeckVariant) -> Result<()> {
|
||||
create_dir_all(crate::path("/sys/class/dmi/id")).await?;
|
||||
match model {
|
||||
HardwareVariant::Unknown => write(crate::path(SYS_VENDOR_PATH), "LENOVO\n").await?,
|
||||
HardwareVariant::Jupiter => {
|
||||
SteamDeckVariant::Unknown => write(crate::path(SYS_VENDOR_PATH), "LENOVO\n").await?,
|
||||
SteamDeckVariant::Jupiter => {
|
||||
write(crate::path(SYS_VENDOR_PATH), "Valve\n").await?;
|
||||
write(crate::path(BOARD_NAME_PATH), "Jupiter\n").await?;
|
||||
}
|
||||
HardwareVariant::Galileo => {
|
||||
SteamDeckVariant::Galileo => {
|
||||
write(crate::path(SYS_VENDOR_PATH), "Valve\n").await?;
|
||||
write(crate::path(BOARD_NAME_PATH), "Galileo\n").await?;
|
||||
}
|
||||
|
@ -176,12 +191,58 @@ pub mod test {
|
|||
create_dir_all(crate::path("/sys/class/dmi/id"))
|
||||
.await
|
||||
.expect("create_dir_all");
|
||||
assert!(variant().await.is_err());
|
||||
assert!(steam_deck_variant().await.is_err());
|
||||
|
||||
write(crate::path(SYS_VENDOR_PATH), "LENOVO\n")
|
||||
.await
|
||||
.expect("write");
|
||||
assert_eq!(variant().await.unwrap(), HardwareVariant::Unknown);
|
||||
write(crate::path(BOARD_NAME_PATH), "INVALID\n")
|
||||
.await
|
||||
.expect("write");
|
||||
write(crate::path(PRODUCT_NAME_PATH), "INVALID\n")
|
||||
.await
|
||||
.expect("write");
|
||||
assert_eq!(
|
||||
steam_deck_variant().await.unwrap(),
|
||||
SteamDeckVariant::Unknown
|
||||
);
|
||||
assert_eq!(device_type().await.unwrap(), DeviceType::Unknown);
|
||||
|
||||
write(crate::path(PRODUCT_NAME_PATH), "83L3\n")
|
||||
.await
|
||||
.expect("write");
|
||||
assert_eq!(
|
||||
steam_deck_variant().await.unwrap(),
|
||||
SteamDeckVariant::Unknown
|
||||
);
|
||||
assert_eq!(device_type().await.unwrap(), DeviceType::LegionGoS);
|
||||
|
||||
write(crate::path(PRODUCT_NAME_PATH), "83N6\n")
|
||||
.await
|
||||
.expect("write");
|
||||
assert_eq!(
|
||||
steam_deck_variant().await.unwrap(),
|
||||
SteamDeckVariant::Unknown
|
||||
);
|
||||
assert_eq!(device_type().await.unwrap(), DeviceType::LegionGoS);
|
||||
|
||||
write(crate::path(PRODUCT_NAME_PATH), "83Q2\n")
|
||||
.await
|
||||
.expect("write");
|
||||
assert_eq!(
|
||||
steam_deck_variant().await.unwrap(),
|
||||
SteamDeckVariant::Unknown
|
||||
);
|
||||
assert_eq!(device_type().await.unwrap(), DeviceType::LegionGoS);
|
||||
|
||||
write(crate::path(PRODUCT_NAME_PATH), "83Q3\n")
|
||||
.await
|
||||
.expect("write");
|
||||
assert_eq!(
|
||||
steam_deck_variant().await.unwrap(),
|
||||
SteamDeckVariant::Unknown
|
||||
);
|
||||
assert_eq!(device_type().await.unwrap(), DeviceType::LegionGoS);
|
||||
|
||||
write(crate::path(SYS_VENDOR_PATH), "Valve\n")
|
||||
.await
|
||||
|
@ -189,17 +250,35 @@ pub mod test {
|
|||
write(crate::path(BOARD_NAME_PATH), "Jupiter\n")
|
||||
.await
|
||||
.expect("write");
|
||||
assert_eq!(variant().await.unwrap(), HardwareVariant::Jupiter);
|
||||
write(crate::path(PRODUCT_NAME_PATH), "Jupiter\n")
|
||||
.await
|
||||
.expect("write");
|
||||
assert_eq!(
|
||||
steam_deck_variant().await.unwrap(),
|
||||
SteamDeckVariant::Jupiter
|
||||
);
|
||||
assert_eq!(device_type().await.unwrap(), DeviceType::SteamDeck);
|
||||
|
||||
write(crate::path(BOARD_NAME_PATH), "Galileo\n")
|
||||
.await
|
||||
.expect("write");
|
||||
assert_eq!(variant().await.unwrap(), HardwareVariant::Galileo);
|
||||
write(crate::path(PRODUCT_NAME_PATH), "Galileo\n")
|
||||
.await
|
||||
.expect("write");
|
||||
assert_eq!(
|
||||
steam_deck_variant().await.unwrap(),
|
||||
SteamDeckVariant::Galileo
|
||||
);
|
||||
assert_eq!(device_type().await.unwrap(), DeviceType::SteamDeck);
|
||||
|
||||
write(crate::path(BOARD_NAME_PATH), "Neptune\n")
|
||||
.await
|
||||
.expect("write");
|
||||
assert_eq!(variant().await.unwrap(), HardwareVariant::Unknown);
|
||||
assert_eq!(
|
||||
steam_deck_variant().await.unwrap(),
|
||||
SteamDeckVariant::Unknown
|
||||
);
|
||||
assert_eq!(device_type().await.unwrap(), DeviceType::Unknown);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -20,7 +20,9 @@ use zbus::{fdo, interface, Connection};
|
|||
use crate::daemon::root::{Command, RootCommand};
|
||||
use crate::daemon::DaemonCommand;
|
||||
use crate::error::{to_zbus_error, to_zbus_fdo_error};
|
||||
use crate::hardware::{variant, FactoryResetKind, FanControl, FanControlState, HardwareVariant};
|
||||
use crate::hardware::{
|
||||
steam_deck_variant, FactoryResetKind, FanControl, FanControlState, SteamDeckVariant,
|
||||
};
|
||||
use crate::job::JobManager;
|
||||
use crate::platform::platform_config;
|
||||
use crate::power::{
|
||||
|
@ -78,7 +80,7 @@ impl SteamOSManager {
|
|||
Ok(SteamOSManager {
|
||||
fan_control: FanControl::new(connection.clone()),
|
||||
wifi_debug_mode: WifiDebugMode::Off,
|
||||
should_trace: variant().await? == HardwareVariant::Galileo,
|
||||
should_trace: steam_deck_variant().await? == SteamDeckVariant::Galileo,
|
||||
job_manager: JobManager::new(connection.clone()).await?,
|
||||
connection,
|
||||
channel,
|
||||
|
@ -151,9 +153,9 @@ impl SteamOSManager {
|
|||
async fn als_calibration_gain(&self) -> Vec<f64> {
|
||||
// Run script to get calibration value
|
||||
let mut gains = Vec::new();
|
||||
let indices: &[&str] = match variant().await {
|
||||
Ok(HardwareVariant::Jupiter) => &["2"],
|
||||
Ok(HardwareVariant::Galileo) => &["2", "4"],
|
||||
let indices: &[&str] = match steam_deck_variant().await {
|
||||
Ok(SteamDeckVariant::Jupiter) => &["2"],
|
||||
Ok(SteamDeckVariant::Galileo) => &["2", "4"],
|
||||
_ => return Vec::new(),
|
||||
};
|
||||
for index in indices {
|
||||
|
@ -176,10 +178,10 @@ impl SteamOSManager {
|
|||
|
||||
async fn get_als_integration_time_file_descriptor(&self, index: u32) -> fdo::Result<Fd> {
|
||||
// Get the file descriptor for the als integration time sysfs path
|
||||
let i0 = match variant().await.map_err(to_zbus_fdo_error)? {
|
||||
HardwareVariant::Jupiter => 1,
|
||||
HardwareVariant::Galileo => index,
|
||||
HardwareVariant::Unknown => {
|
||||
let i0 = match steam_deck_variant().await.map_err(to_zbus_fdo_error)? {
|
||||
SteamDeckVariant::Jupiter => 1,
|
||||
SteamDeckVariant::Galileo => index,
|
||||
SteamDeckVariant::Unknown => {
|
||||
return Err(fdo::Error::Failed(String::from("Unknown model")))
|
||||
}
|
||||
};
|
||||
|
@ -457,7 +459,7 @@ mod test {
|
|||
|
||||
async fn start() -> Result<TestHandle> {
|
||||
let mut handle = testing::start();
|
||||
fake_model(HardwareVariant::Jupiter).await?;
|
||||
fake_model(SteamDeckVariant::Jupiter).await?;
|
||||
create_dir_all(crate::path("/etc/NetworkManager/conf.d")).await?;
|
||||
write(
|
||||
crate::path("/etc/NetworkManager/conf.d/99-valve-wifi-backend.conf"),
|
||||
|
@ -608,22 +610,22 @@ mod test {
|
|||
.process_cb
|
||||
.set(|_, _| Ok((0, String::from("0.0\n"))));
|
||||
|
||||
fake_model(HardwareVariant::Jupiter)
|
||||
fake_model(SteamDeckVariant::Jupiter)
|
||||
.await
|
||||
.expect("fake_model");
|
||||
assert_eq!(proxy.als_calibration_gain().await.unwrap(), &[0.0]);
|
||||
|
||||
fake_model(HardwareVariant::Galileo)
|
||||
fake_model(SteamDeckVariant::Galileo)
|
||||
.await
|
||||
.expect("fake_model");
|
||||
assert_eq!(proxy.als_calibration_gain().await.unwrap(), &[0.0, 0.0]);
|
||||
|
||||
fake_model(HardwareVariant::Unknown)
|
||||
fake_model(SteamDeckVariant::Unknown)
|
||||
.await
|
||||
.expect("fake_model");
|
||||
assert_eq!(proxy.als_calibration_gain().await.unwrap(), &[]);
|
||||
|
||||
fake_model(HardwareVariant::Jupiter)
|
||||
fake_model(SteamDeckVariant::Jupiter)
|
||||
.await
|
||||
.expect("fake_model");
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ use crate::cec::{HdmiCecControl, HdmiCecState};
|
|||
use crate::daemon::user::Command;
|
||||
use crate::daemon::DaemonCommand;
|
||||
use crate::error::{to_zbus_error, to_zbus_fdo_error, zbus_to_zbus_fdo};
|
||||
use crate::hardware::{is_deck, variant, HardwareVariant};
|
||||
use crate::hardware::{device_type, steam_deck_variant, DeviceType, SteamDeckVariant};
|
||||
use crate::job::JobManagerCommand;
|
||||
use crate::platform::platform_config;
|
||||
use crate::power::{
|
||||
|
@ -680,10 +680,10 @@ pub(crate) async fn create_interfaces(
|
|||
|
||||
create_config_interfaces(&proxy, object_server, &job_manager).await?;
|
||||
|
||||
if is_deck().await? {
|
||||
if device_type().await.unwrap_or_default() == DeviceType::SteamDeck {
|
||||
object_server.at(MANAGER_PATH, als).await?;
|
||||
}
|
||||
if variant().await? == HardwareVariant::Galileo {
|
||||
if steam_deck_variant().await.unwrap_or_default() == SteamDeckVariant::Galileo {
|
||||
object_server.at(MANAGER_PATH, wifi_debug_dump).await?;
|
||||
}
|
||||
|
||||
|
@ -721,7 +721,7 @@ pub(crate) async fn create_interfaces(
|
|||
object_server.at(MANAGER_PATH, tdp_limit).await?;
|
||||
}
|
||||
|
||||
if variant().await.unwrap_or_default() == HardwareVariant::Galileo {
|
||||
if steam_deck_variant().await.unwrap_or_default() == SteamDeckVariant::Galileo {
|
||||
object_server.at(MANAGER_PATH, wifi_debug).await?;
|
||||
}
|
||||
|
||||
|
@ -740,7 +740,7 @@ mod test {
|
|||
use crate::daemon::channel;
|
||||
use crate::daemon::user::UserContext;
|
||||
use crate::hardware::test::fake_model;
|
||||
use crate::hardware::HardwareVariant;
|
||||
use crate::hardware::SteamDeckVariant;
|
||||
use crate::platform::{
|
||||
BatteryChargeLimitConfig, PlatformConfig, RangeConfig, ResetConfig, ScriptConfig,
|
||||
ServiceConfig, StorageConfig,
|
||||
|
@ -813,7 +813,7 @@ mod test {
|
|||
write(&exe_path, "").await?;
|
||||
set_permissions(&exe_path, PermissionsExt::from_mode(0o700)).await?;
|
||||
|
||||
fake_model(HardwareVariant::Galileo).await?;
|
||||
fake_model(SteamDeckVariant::Galileo).await?;
|
||||
handle
|
||||
.test
|
||||
.process_cb
|
||||
|
|
|
@ -18,7 +18,7 @@ use tokio::sync::OnceCell;
|
|||
use tokio::task::spawn_blocking;
|
||||
|
||||
#[cfg(not(test))]
|
||||
use crate::hardware::is_deck;
|
||||
use crate::hardware::{device_type, DeviceType};
|
||||
|
||||
#[cfg(not(test))]
|
||||
static CONFIG: OnceCell<Option<PlatformConfig>> = OnceCell::const_new();
|
||||
|
@ -137,12 +137,14 @@ impl<T: Clone> RangeConfig<T> {
|
|||
impl PlatformConfig {
|
||||
#[cfg(not(test))]
|
||||
async fn load() -> Result<Option<PlatformConfig>> {
|
||||
if !is_deck().await? {
|
||||
// Non-Steam Deck platforms are not yet supported
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let config = read_to_string("/usr/share/steamos-manager/platforms/jupiter.toml").await?;
|
||||
let platform = match device_type().await? {
|
||||
DeviceType::SteamDeck => "jupiter",
|
||||
_ => return Ok(None),
|
||||
};
|
||||
let config = read_to_string(format!(
|
||||
"/usr/share/steamos-manager/platforms/{platform}.toml"
|
||||
))
|
||||
.await?;
|
||||
Ok(Some(toml::from_str(config.as_ref())?))
|
||||
}
|
||||
|
||||
|
|
28
src/power.rs
28
src/power.rs
|
@ -16,7 +16,7 @@ use tokio::fs::{self, try_exists, File};
|
|||
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
|
||||
use tracing::{error, warn};
|
||||
|
||||
use crate::hardware::is_deck;
|
||||
use crate::hardware::{device_type, DeviceType};
|
||||
use crate::platform::platform_config;
|
||||
use crate::{path, write_synced};
|
||||
|
||||
|
@ -139,7 +139,7 @@ pub(crate) async fn get_gpu_power_profile() -> Result<GPUPowerProfile> {
|
|||
// check which profile is current and return if possible
|
||||
let contents = read_gpu_sysfs_contents(GPU_POWER_PROFILE_SUFFIX).await?;
|
||||
|
||||
// NOTE: We don't filter based on is_deck here because the sysfs
|
||||
// NOTE: We don't filter based on deck here because the sysfs
|
||||
// firmware support setting the value to no-op values.
|
||||
let lines = contents.lines();
|
||||
for line in lines {
|
||||
|
@ -162,7 +162,7 @@ pub(crate) async fn get_gpu_power_profile() -> Result<GPUPowerProfile> {
|
|||
|
||||
pub(crate) async fn get_available_gpu_power_profiles() -> Result<Vec<(u32, String)>> {
|
||||
let contents = read_gpu_sysfs_contents(GPU_POWER_PROFILE_SUFFIX).await?;
|
||||
let deck = is_deck().await?;
|
||||
let deck = device_type().await.unwrap_or_default() == DeviceType::SteamDeck;
|
||||
|
||||
let mut map = Vec::new();
|
||||
let lines = contents.lines();
|
||||
|
@ -437,7 +437,7 @@ pub(crate) async fn set_max_charge_level(limit: i32) -> Result<()> {
|
|||
pub(crate) mod test {
|
||||
use super::*;
|
||||
use crate::hardware::test::fake_model;
|
||||
use crate::hardware::HardwareVariant;
|
||||
use crate::hardware::SteamDeckVariant;
|
||||
use crate::platform::{BatteryChargeLimitConfig, PlatformConfig};
|
||||
use crate::{enum_roundtrip, testing};
|
||||
use anyhow::anyhow;
|
||||
|
@ -815,7 +815,7 @@ CCLK_RANGE in Core0:
|
|||
|
||||
write(filename.as_path(), contents).await.expect("write");
|
||||
|
||||
fake_model(HardwareVariant::Unknown)
|
||||
fake_model(SteamDeckVariant::Unknown)
|
||||
.await
|
||||
.expect("fake_model");
|
||||
|
||||
|
@ -836,7 +836,7 @@ CCLK_RANGE in Core0:
|
|||
]
|
||||
);
|
||||
|
||||
fake_model(HardwareVariant::Jupiter)
|
||||
fake_model(SteamDeckVariant::Jupiter)
|
||||
.await
|
||||
.expect("fake_model");
|
||||
|
||||
|
@ -872,7 +872,7 @@ CCLK_RANGE in Core0:
|
|||
|
||||
write(filename.as_path(), contents).await.expect("write");
|
||||
|
||||
fake_model(HardwareVariant::Unknown)
|
||||
fake_model(SteamDeckVariant::Unknown)
|
||||
.await
|
||||
.expect("fake_model");
|
||||
|
||||
|
@ -894,7 +894,7 @@ CCLK_RANGE in Core0:
|
|||
]
|
||||
);
|
||||
|
||||
fake_model(HardwareVariant::Jupiter)
|
||||
fake_model(SteamDeckVariant::Jupiter)
|
||||
.await
|
||||
.expect("fake_model");
|
||||
|
||||
|
@ -929,7 +929,7 @@ CCLK_RANGE in Core0:
|
|||
|
||||
write(filename.as_path(), contents).await.expect("write");
|
||||
|
||||
fake_model(HardwareVariant::Unknown)
|
||||
fake_model(SteamDeckVariant::Unknown)
|
||||
.await
|
||||
.expect("fake_model");
|
||||
assert_eq!(
|
||||
|
@ -937,7 +937,7 @@ CCLK_RANGE in Core0:
|
|||
GPUPowerProfile::Video
|
||||
);
|
||||
|
||||
fake_model(HardwareVariant::Jupiter)
|
||||
fake_model(SteamDeckVariant::Jupiter)
|
||||
.await
|
||||
.expect("fake_model");
|
||||
assert_eq!(
|
||||
|
@ -967,12 +967,12 @@ CCLK_RANGE in Core0:
|
|||
|
||||
write(filename.as_path(), contents).await.expect("write");
|
||||
|
||||
fake_model(HardwareVariant::Unknown)
|
||||
fake_model(SteamDeckVariant::Unknown)
|
||||
.await
|
||||
.expect("fake_model");
|
||||
assert!(get_gpu_power_profile().await.is_err());
|
||||
|
||||
fake_model(HardwareVariant::Jupiter)
|
||||
fake_model(SteamDeckVariant::Jupiter)
|
||||
.await
|
||||
.expect("fake_model");
|
||||
assert!(get_gpu_power_profile().await.is_err());
|
||||
|
@ -1000,12 +1000,12 @@ CCLK_RANGE in Core0:
|
|||
|
||||
write(filename.as_path(), contents).await.expect("write");
|
||||
|
||||
fake_model(HardwareVariant::Unknown)
|
||||
fake_model(SteamDeckVariant::Unknown)
|
||||
.await
|
||||
.expect("fake_model");
|
||||
assert!(get_gpu_power_profile().await.is_err());
|
||||
|
||||
fake_model(HardwareVariant::Jupiter)
|
||||
fake_model(SteamDeckVariant::Jupiter)
|
||||
.await
|
||||
.expect("fake_model");
|
||||
assert!(get_gpu_power_profile().await.is_err());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue