11use crate :: cli:: Command as DynCommand ;
22use crate :: sys;
33
4- use anyhow:: { Context , Result } ;
4+ use anyhow:: Result ;
55
66
77pub 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