@@ -19,6 +19,7 @@ use tokio::{
19
19
sync:: Mutex ,
20
20
time:: sleep,
21
21
} ;
22
+ use zbus:: Interface ;
22
23
23
24
use crate :: {
24
25
charge_thresholds:: { get_charge_profiles, get_charge_thresholds, set_charge_thresholds} ,
@@ -38,6 +39,8 @@ use self::profiles::{balanced, battery, performance};
38
39
use system76_power_zbus:: ChargeProfile ;
39
40
40
41
const THRESHOLD_POLICY : & str = "com.system76.powerdaemon.set-charge-thresholds" ;
42
+ const NET_HADES_POWER_PROFILES_DBUS_NAME : & str = "net.hadess.PowerProfiles" ;
43
+ const NET_HADES_POWER_PROFILES_DBUS_PATH : & str = "/net/hadess/PowerProfiles" ;
41
44
const POWER_PROFILES_DBUS_NAME : & str = "org.freedesktop.UPower.PowerProfiles" ;
42
45
const POWER_PROFILES_DBUS_PATH : & str = "/org/freedesktop/UPower/PowerProfiles" ;
43
46
@@ -73,6 +76,7 @@ struct PowerDaemon {
73
76
held_profiles : Vec < ( u32 , & ' static str , String , String ) > ,
74
77
profile_ids : u32 ,
75
78
connection : zbus:: Connection ,
79
+ connections : Option < ( zbus:: Connection , zbus:: Connection ) > ,
76
80
}
77
81
78
82
impl PowerDaemon {
@@ -87,6 +91,7 @@ impl PowerDaemon {
87
91
held_profiles : Vec :: new ( ) ,
88
92
profile_ids : 0 ,
89
93
connection,
94
+ connections : None ,
90
95
} )
91
96
}
92
97
@@ -120,44 +125,108 @@ impl PowerDaemon {
120
125
}
121
126
}
122
127
128
+ #[ derive( Clone ) ]
123
129
struct System76Power ( Arc < Mutex < PowerDaemon > > ) ;
124
130
131
+ impl System76Power {
132
+ pub async fn emit_active_profile_changed ( & self ) {
133
+ let ( upp_connection, hadess_connection, profile) = {
134
+ let this = self . 0 . lock ( ) . await ;
135
+ let Some ( ( upp, hadess) ) = this. connections . clone ( ) else { return } ;
136
+
137
+ let profile = system76_profile_to_upp_str ( & this. power_profile ) ;
138
+ ( upp, hadess, profile)
139
+ } ;
140
+
141
+ let value = zvariant:: Value :: Str ( zvariant:: Str :: from ( profile) ) ;
142
+ let changed = HashMap :: from_iter ( std:: iter:: once ( ( "ActiveProfile" , & value) ) ) ;
143
+ let invalidated = & [ ] ;
144
+
145
+ if let Ok ( context) = zbus:: SignalContext :: new ( & upp_connection, POWER_PROFILES_DBUS_PATH ) {
146
+ let _res = dbg ! (
147
+ zbus:: fdo:: Properties :: properties_changed(
148
+ & context,
149
+ UPowerPowerProfiles :: name( ) ,
150
+ & changed,
151
+ invalidated,
152
+ )
153
+ . await
154
+ ) ;
155
+ }
156
+
157
+ if let Ok ( context) =
158
+ zbus:: SignalContext :: new ( & hadess_connection, NET_HADES_POWER_PROFILES_DBUS_PATH )
159
+ {
160
+ let _res = dbg ! (
161
+ zbus:: fdo:: Properties :: properties_changed(
162
+ & context,
163
+ NetHadessPowerProfiles :: name( ) ,
164
+ & changed,
165
+ invalidated
166
+ )
167
+ . await
168
+ ) ;
169
+ }
170
+ }
171
+ }
172
+
125
173
#[ zbus:: dbus_interface( name = "com.system76.PowerDaemon" ) ]
126
174
impl System76Power {
127
175
async fn battery (
128
176
& mut self ,
129
177
#[ zbus( signal_context) ] context : zbus:: SignalContext < ' _ > ,
130
178
) -> zbus:: fdo:: Result < ( ) > {
131
- self . 0
179
+ let result = self
180
+ . 0
132
181
. lock ( )
133
182
. await
134
183
. apply_profile ( & context, battery, "Battery" )
135
184
. await
136
- . map_err ( zbus_error_from_display)
185
+ . map_err ( zbus_error_from_display) ;
186
+
187
+ if result. is_ok ( ) {
188
+ self . emit_active_profile_changed ( ) . await
189
+ }
190
+
191
+ result
137
192
}
138
193
139
194
async fn balanced (
140
195
& mut self ,
141
196
#[ zbus( signal_context) ] context : zbus:: SignalContext < ' _ > ,
142
197
) -> zbus:: fdo:: Result < ( ) > {
143
- self . 0
198
+ let result = self
199
+ . 0
144
200
. lock ( )
145
201
. await
146
202
. apply_profile ( & context, balanced, "Balanced" )
147
203
. await
148
- . map_err ( zbus_error_from_display)
204
+ . map_err ( zbus_error_from_display) ;
205
+
206
+ if result. is_ok ( ) {
207
+ self . emit_active_profile_changed ( ) . await
208
+ }
209
+
210
+ result
149
211
}
150
212
151
213
async fn performance (
152
214
& mut self ,
153
215
#[ zbus( signal_context) ] context : zbus:: SignalContext < ' _ > ,
154
216
) -> zbus:: fdo:: Result < ( ) > {
155
- self . 0
217
+ let result = self
218
+ . 0
156
219
. lock ( )
157
220
. await
158
221
. apply_profile ( & context, performance, "Performance" )
159
222
. await
160
- . map_err ( zbus_error_from_display)
223
+ . map_err ( zbus_error_from_display) ;
224
+
225
+ if result. is_ok ( ) {
226
+ self . emit_active_profile_changed ( ) . await
227
+ }
228
+
229
+ result
161
230
}
162
231
163
232
#[ dbus_interface( out_args( "profile" ) ) ]
@@ -358,12 +427,7 @@ impl UPowerPowerProfiles {
358
427
359
428
#[ dbus_interface( property) ]
360
429
async fn active_profile ( & self ) -> & str {
361
- match self . 0 . lock ( ) . await . power_profile . as_str ( ) {
362
- "Battery" => "power-saver" ,
363
- "Balanced" => "balanced" ,
364
- "Performance" => "performance" ,
365
- _ => "unknown" ,
366
- }
430
+ system76_profile_to_upp_str ( self . 0 . lock ( ) . await . power_profile . as_str ( ) )
367
431
}
368
432
369
433
#[ dbus_interface( property) ]
@@ -455,9 +519,6 @@ pub async fn daemon() -> anyhow::Result<()> {
455
519
let connection =
456
520
zbus:: Connection :: system ( ) . await . context ( "failed to create zbus connection" ) ?;
457
521
458
- let context = zbus:: SignalContext :: new ( & connection, DBUS_PATH )
459
- . context ( "unable to create signal context" ) ?;
460
-
461
522
let daemon = PowerDaemon :: new ( connection) ?;
462
523
463
524
let nvidia_exists = !daemon. graphics . nvidia . is_empty ( ) ;
@@ -488,26 +549,9 @@ pub async fn daemon() -> anyhow::Result<()> {
488
549
}
489
550
}
490
551
491
- if let Err ( why) = system76_daemon. balanced ( context. clone ( ) ) . await {
492
- log:: warn!( "Failed to set initial profile: {}" , why) ;
493
- }
494
-
495
- system76_daemon. 0 . lock ( ) . await . initial_set = true ;
496
-
497
- // Register DBus interface for com.system76.PowerDaemon.
498
- let _connection = zbus:: ConnectionBuilder :: system ( )
499
- . context ( "failed to create zbus connection builder" ) ?
500
- . name ( DBUS_NAME )
501
- . context ( "unable to register name" ) ?
502
- . serve_at ( DBUS_PATH , system76_daemon)
503
- . context ( "unable to serve" ) ?
504
- . build ( )
505
- . await
506
- . context ( "unable to create system service for com.system76.PowerDaemon" ) ?;
507
-
508
552
// Register DBus interface for org.freedesktop.UPower.PowerProfiles.
509
553
// This is used by powerprofilesctl
510
- let _connection = zbus:: ConnectionBuilder :: system ( )
554
+ let upp_connection = zbus:: ConnectionBuilder :: system ( )
511
555
. context ( "failed to create zbus connection builder" ) ?
512
556
. name ( POWER_PROFILES_DBUS_NAME )
513
557
. context ( "unable to register name" ) ?
@@ -519,16 +563,41 @@ pub async fn daemon() -> anyhow::Result<()> {
519
563
520
564
// Register DBus interface for net.hadess.PowerProfiles.
521
565
// This is used by gnome-shell
522
- let _connection = zbus:: ConnectionBuilder :: system ( )
566
+ let hadess_connection = zbus:: ConnectionBuilder :: system ( )
523
567
. context ( "failed to create zbus connection builder" ) ?
524
- . name ( "net.hadess.PowerProfiles" )
568
+ . name ( NET_HADES_POWER_PROFILES_DBUS_NAME )
525
569
. context ( "unable to register name" ) ?
526
- . serve_at ( "/net/hadess/PowerProfiles" , NetHadessPowerProfiles ( UPowerPowerProfiles ( daemon) ) )
570
+ . serve_at (
571
+ NET_HADES_POWER_PROFILES_DBUS_PATH ,
572
+ NetHadessPowerProfiles ( UPowerPowerProfiles ( daemon) ) ,
573
+ )
527
574
. context ( "unable to serve" ) ?
528
575
. build ( )
529
576
. await
530
577
. context ( "unable to create system service for net.hadess.PowerProfiles" ) ?;
531
578
579
+ // Register DBus interface for com.system76.PowerDaemon.
580
+ let connection = zbus:: ConnectionBuilder :: system ( )
581
+ . context ( "failed to create zbus connection builder" ) ?
582
+ . name ( DBUS_NAME )
583
+ . context ( "unable to register name" ) ?
584
+ . serve_at ( DBUS_PATH , system76_daemon. clone ( ) )
585
+ . context ( "unable to serve" ) ?
586
+ . build ( )
587
+ . await
588
+ . context ( "unable to create system service for com.system76.PowerDaemon" ) ?;
589
+
590
+ system76_daemon. 0 . lock ( ) . await . connections = Some ( ( upp_connection, hadess_connection) ) ;
591
+
592
+ let context = zbus:: SignalContext :: new ( & connection, DBUS_PATH )
593
+ . context ( "unable to create signal context" ) ?;
594
+
595
+ if let Err ( why) = system76_daemon. balanced ( context. clone ( ) ) . await {
596
+ log:: warn!( "Failed to set initial profile: {}" , why) ;
597
+ }
598
+
599
+ system76_daemon. 0 . lock ( ) . await . initial_set = true ;
600
+
532
601
// Spawn hid backlight daemon
533
602
let _hid_backlight = thread:: spawn ( hid_backlight:: daemon) ;
534
603
let mut fan_daemon = FanDaemon :: new ( nvidia_exists) ;
@@ -575,6 +644,15 @@ pub async fn daemon() -> anyhow::Result<()> {
575
644
Ok ( ( ) )
576
645
}
577
646
647
+ fn system76_profile_to_upp_str ( system76_profile : & str ) -> & ' static str {
648
+ match system76_profile {
649
+ "Battery" => "power-saver" ,
650
+ "Balanced" => "balanced" ,
651
+ "Performance" => "performance" ,
652
+ _ => "unknown" ,
653
+ }
654
+ }
655
+
578
656
fn zbus_error_from_display < E : Display > ( why : E ) -> zbus:: fdo:: Error {
579
657
zbus:: fdo:: Error :: Failed ( format ! ( "{}" , why) )
580
658
}
0 commit comments