Skip to content

Commit 034cab9

Browse files
committed
Rework status command
1 parent a827d90 commit 034cab9

File tree

1 file changed

+181
-51
lines changed

1 file changed

+181
-51
lines changed

src/cli/status.rs

Lines changed: 181 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::cli::Command as DynCommand;
22
use crate::sys;
33

4-
use anyhow::{Context, Result};
4+
use anyhow::Result;
55

66

77
pub struct Command;
@@ -13,63 +13,193 @@ impl DynCommand for Command {
1313

1414
fn build(&self) -> clap::App<'static, 'static> {
1515
clap::SubCommand::with_name(self.name())
16-
.about("Query the current system status")
16+
.about("Show an overview of the current system status")
1717
}
1818

1919
fn execute(&self, _: &clap::ArgMatches) -> Result<()> {
20-
let mut found = false;
21-
22-
let mode = sys::dtx::Device::open().and_then(|d| d.get_device_mode());
23-
let mode = match mode {
24-
Ok(x) => { found = true; Some(x) },
25-
Err(sys::Error::DeviceAccess { .. }) => None,
26-
Err(e) => return Err(e).context("Failed to access DTX device"),
27-
};
28-
29-
let lstat = sys::dtx::Device::open().and_then(|d| d.get_latch_status());
30-
let lstat = match lstat {
31-
Ok(x) => { found = true; Some(x) },
32-
Err(sys::Error::DeviceAccess { .. }) => None,
33-
Err(e) => return Err(e).context("Failed to access DTX device"),
34-
};
35-
36-
let base = sys::dtx::Device::open().and_then(|d| d.get_base_info());
37-
let base = match base {
38-
Ok(x) => { found = true; Some(x) },
39-
Err(sys::Error::DeviceAccess { .. }) => None,
40-
Err(e) => return Err(e).context("Failed to access DTX device"),
41-
};
42-
43-
let perf_mode = sys::perf::Device::open().and_then(|d| d.get_mode());
44-
let perf_mode = match perf_mode {
45-
Ok(x) => { found = true; Some(x) },
46-
Err(sys::Error::DeviceAccess { .. }) => None,
47-
Err(e) => return Err(e).context("Failed to access performance mode device"),
48-
};
49-
50-
// TODO: print dGPU power state
51-
52-
if found {
53-
if let Some(perf_mode) = perf_mode {
54-
println!("Performance-Mode: {} ({})", perf_mode, perf_mode.short_str());
55-
}
56-
if let Some(mode) = mode {
57-
println!("Device-Mode: {}", mode);
58-
}
59-
if let Some(lstat) = lstat {
60-
println!("Latch-Status: {}", lstat);
61-
}
62-
if let Some(base) = base {
63-
println!("Base:");
64-
println!(" State: {}", base.state);
65-
println!(" Device-Type: {}", base.device_type);
66-
println!(" ID: {:#04x}", base.id);
67-
}
20+
let stats = Stats::load();
6821

22+
if stats.available() {
23+
print!("{}", stats);
6924
Ok(())
25+
} else {
26+
anyhow::bail!("No devices found")
27+
}
28+
}
29+
}
30+
31+
32+
struct Stats {
33+
perf: PerfStats,
34+
dgpu: DgpuStats,
35+
dtx: DtxStats,
36+
}
37+
38+
struct PerfStats {
39+
mode: Option<sys::perf::Mode>,
40+
}
41+
42+
struct DgpuStats {
43+
vendor: Option<u16>,
44+
device: Option<u16>,
45+
power_state: Option<sys::pci::PowerState>,
46+
runtime_pm: Option<sys::pci::RuntimePowerManagement>,
47+
}
48+
49+
struct DtxStats {
50+
device_mode: Option<sys::dtx::DeviceMode>,
51+
base_state: Option<sys::dtx::BaseState>,
52+
base_type: Option<sys::dtx::DeviceType>,
53+
base_id: Option<u8>,
54+
latch_status: Option<sys::dtx::LatchStatus>,
55+
}
56+
57+
58+
impl Stats {
59+
fn load() -> Self {
60+
let perf = PerfStats::load();
61+
let dgpu = DgpuStats::load();
62+
let dtx = DtxStats::load();
63+
64+
Stats { perf, dgpu, dtx }
65+
}
66+
67+
fn available(&self) -> bool {
68+
self.perf.available()
69+
|| self.dgpu.available()
70+
|| self.dtx.available()
71+
}
72+
}
73+
74+
impl PerfStats {
75+
fn load() -> Self {
76+
let mode = sys::perf::Device::open().ok()
77+
.and_then(|device| device.get_mode().ok());
78+
79+
PerfStats { mode }
80+
}
81+
82+
fn available(&self) -> bool {
83+
self.mode.is_some()
84+
}
85+
}
86+
87+
impl DgpuStats {
88+
fn load() -> Self {
89+
let dev = crate::cli::dgpu::find_dgpu_device().ok().and_then(|x| x);
90+
91+
let vendor = dev.as_ref().and_then(|d| d.vendor_id().ok());
92+
let device = dev.as_ref().and_then(|d| d.device_id().ok());
93+
let power_state = dev.as_ref().and_then(|d| d.get_power_state().ok());
94+
let runtime_pm = dev.as_ref().and_then(|d| d.get_runtime_pm().ok());
95+
96+
DgpuStats { vendor, device, power_state, runtime_pm }
97+
}
98+
99+
fn available(&self) -> bool {
100+
self.vendor.is_some()
101+
|| self.device.is_some()
102+
|| self.power_state.is_some()
103+
|| self.runtime_pm.is_some()
104+
}
105+
}
106+
107+
impl DtxStats {
108+
fn load() -> Self {
109+
let dev = sys::dtx::Device::open().ok();
110+
111+
let base = dev.as_ref().and_then(|d| d.get_base_info().ok());
112+
let base_state = base.map(|b| b.state);
113+
let base_type = base.map(|b| b.device_type);
114+
let base_id = base.map(|b| b.id);
70115

116+
let device_mode = dev.as_ref().and_then(|d| d.get_device_mode().ok());
117+
let latch_status = dev.as_ref().and_then(|d| d.get_latch_status().ok());
118+
119+
DtxStats {
120+
device_mode,
121+
base_state,
122+
base_type,
123+
base_id,
124+
latch_status,
125+
}
126+
}
127+
128+
fn available(&self) -> bool {
129+
self.device_mode.is_some()
130+
|| self.base_state.is_some()
131+
|| self.base_type.is_some()
132+
|| self.base_id.is_some()
133+
|| self.latch_status.is_some()
134+
}
135+
}
136+
137+
138+
impl std::fmt::Display for Stats {
139+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
140+
write!(f, "{}{}{}", self.perf, self.dgpu, self.dtx)
141+
}
142+
}
143+
144+
impl std::fmt::Display for PerfStats {
145+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
146+
if let Some(mode) = self.mode {
147+
writeln!(f, "Performance Mode: {}\n", mode)
71148
} else {
72-
anyhow::bail!("No Surface control device found")
149+
Ok(())
73150
}
74151
}
75152
}
153+
154+
impl std::fmt::Display for DgpuStats {
155+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
156+
if !self.available() {
157+
return Ok(())
158+
}
159+
160+
writeln!(f, "Discrete GPU:")?;
161+
162+
if let Some(vendor) = self.vendor {
163+
writeln!(f, " Vendor: {:04x}", vendor)?;
164+
}
165+
if let Some(device) = self.device {
166+
writeln!(f, " Device: {:04x}", device)?;
167+
}
168+
if let Some(power_state) = self.power_state {
169+
writeln!(f, " Power State: {}", power_state)?;
170+
}
171+
if let Some(runtime_pm) = self.runtime_pm {
172+
writeln!(f, " Runtime PM: {}", runtime_pm)?;
173+
}
174+
175+
writeln!(f)
176+
}
177+
}
178+
179+
impl std::fmt::Display for DtxStats {
180+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
181+
if !self.available() {
182+
return Ok(())
183+
}
184+
185+
writeln!(f, "DTX:")?;
186+
187+
if let Some(device_mode) = self.device_mode {
188+
writeln!(f, " Device Mode: {}", device_mode)?;
189+
}
190+
if let Some(base_state) = self.base_state {
191+
writeln!(f, " Base State: {}", base_state)?;
192+
}
193+
if let Some(base_type) = self.base_type {
194+
writeln!(f, " Base Type: {}", base_type)?;
195+
}
196+
if let Some(base_id) = self.base_id {
197+
writeln!(f, " Base ID: {:#04x}", base_id)?;
198+
}
199+
if let Some(latch_status) = self.latch_status {
200+
writeln!(f, " Latch Status: {}", latch_status)?;
201+
}
202+
203+
writeln!(f)
204+
}
205+
}

0 commit comments

Comments
 (0)