Skip to content

Commit 8cb9bfa

Browse files
committed
battery: optionally use capacity_level for determining battery state
Requires upower with a patch to expose capacity_level on sysfs [0]. The functionality is enabled in the config file. It is additionally possible to configure mce to consider the battery as completely empty when capacity_level reports "Low". [0] https://gitlab.freedesktop.org/upower/upower/-/merge_requests/259
1 parent ee3d643 commit 8cb9bfa

2 files changed

Lines changed: 40 additions & 6 deletions

File tree

config/mce.ini

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,13 @@ PatternUserManual=9;1;0;1;0;0;0;0;0
312312
# Percentage at wich the battery is considerd "low" and a warning appears
313313
LowPercentage=10
314314

315+
# Enable this to use capacity_level from sysfs for shutdown policy
316+
UseCapacityLevel=false
317+
318+
# When UseCapacityLevel = true, enable this to consider battery as empty when
319+
# capacity_level is "low" instead of "critical"
320+
CapacityLevelLowCritical=false
321+
315322
[Display]
316323

317324
# Time in seconds between the display going dim and it turning off entirely

src/modules/battery-upower.c

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ G_MODULE_EXPORT module_info_struct module_info = {
6262
#define MCE_CONF_BATTERY_SECTION "Battery"
6363
#define MCE_CONF_CRIT_VOLTAGE_KEY "CriticalVoltage"
6464
#define MCE_CONF_LOW_PERCENT_KEY "LowPercentage"
65+
#define MCE_CONF_USE_CAPACITY_LEVEL "UseCapacityLevel"
66+
#define MCE_CONF_CAPACITY_LOW_CRITICAL_KEY "CapacityLevelLowCritical"
6567

6668

6769
/** Skip these devices */
@@ -83,6 +85,8 @@ static struct {
8385
time_t force_state;
8486
gdouble min_voltage;
8587
int low_percentage;
88+
gboolean use_capacity_level;
89+
gboolean level_low_critical;
8690
} private = {0};
8791

8892
/** Battery properties available via UPower */
@@ -91,6 +95,7 @@ struct {
9195
gdouble percentage;
9296
gdouble voltage;
9397
gboolean charger_online;
98+
gchar *supply_level;
9499
} upowbat = {0};
95100

96101
/** Battery properties in mce statemachine compatible form */
@@ -113,6 +118,7 @@ upowbat_init(void)
113118
{
114119
upowbat.percentage = 50;
115120
upowbat.voltage = 3.8;
121+
upowbat.supply_level = NULL;
116122
upowbat.state = UP_DEVICE_STATE_UNKNOWN;
117123
}
118124

@@ -135,6 +141,7 @@ upowbat_update(void)
135141
gdouble percentage;
136142
gdouble voltage;
137143
guint state;
144+
gchar *supply_level;
138145

139146
if (private.battery == NULL)
140147
return;
@@ -143,6 +150,7 @@ upowbat_update(void)
143150
"percentage", &percentage,
144151
"state", &state,
145152
"voltage", &voltage,
153+
"supply-level", &supply_level,
146154
NULL);
147155

148156
if (upowbat.percentage != percentage) {
@@ -164,6 +172,11 @@ upowbat_update(void)
164172
}
165173
}
166174

175+
if (g_strcmp0(upowbat.supply_level, supply_level) != 0) {
176+
mce_log(LL_DEBUG, "%s: Capacity Level: %s -> %s", MODULE_NAME, upowbat.supply_level, supply_level);
177+
upowbat.supply_level = supply_level;
178+
}
179+
167180
if (upowbat.state != state) {
168181
if (upowbat.state == UP_DEVICE_STATE_FULLY_CHARGED && state == UP_DEVICE_STATE_CHARGING) {
169182
/* Prevent 'fully charged' -> 'charging' transition */
@@ -191,13 +204,21 @@ mcebat_update_from_upowbat(void)
191204
upowbat.state == UP_DEVICE_STATE_PENDING_CHARGE;
192205
}
193206

194-
if (upowbat.state == UP_DEVICE_STATE_EMPTY ||
195-
upowbat.voltage < private.min_voltage && !mcebat.charger_connected)
196-
mcebat.status = BATTERY_STATUS_EMPTY;
197-
else if (upowbat.percentage < private.low_percentage)
198-
mcebat.status = BATTERY_STATUS_LOW;
199-
else if (upowbat.state == UP_DEVICE_STATE_FULLY_CHARGED)
207+
if (upowbat.state == UP_DEVICE_STATE_FULLY_CHARGED) {
200208
mcebat.status = BATTERY_STATUS_FULL;
209+
} else if (private.use_capacity_level) {
210+
if (g_strcmp0(upowbat.supply_level, "Critical") == 0 ||
211+
(private.level_low_critical && g_strcmp0(upowbat.supply_level, "Low") == 0))
212+
mcebat.status = BATTERY_STATUS_EMPTY;
213+
else if (g_strcmp0(upowbat.supply_level, "Low") == 0)
214+
mcebat.status = BATTERY_STATUS_LOW;
215+
} else {
216+
if (upowbat.state == UP_DEVICE_STATE_EMPTY ||
217+
(upowbat.voltage < private.min_voltage && !mcebat.charger_connected))
218+
mcebat.status = BATTERY_STATUS_EMPTY;
219+
else if (upowbat.percentage < private.low_percentage)
220+
mcebat.status = BATTERY_STATUS_LOW;
221+
}
201222
}
202223

203224
static inline const char *
@@ -476,6 +497,10 @@ xup_battery_connect_handlers(void)
476497
g_signal_connect(private.battery, "notify::voltage",
477498
G_CALLBACK(xup_battery_properties_changed_cb),
478499
NULL);
500+
501+
g_signal_connect(private.battery, "notify::supply-level",
502+
G_CALLBACK(xup_battery_properties_changed_cb),
503+
NULL);
479504
}
480505

481506
/**
@@ -639,6 +664,8 @@ const gchar *g_module_check_init(GModule *module)
639664
if(private.min_voltage > 0.1)
640665
mce_log(LL_INFO, "%s: critical voltage set set to %f", MODULE_NAME, private.min_voltage);
641666
private.low_percentage = mce_conf_get_int(MCE_CONF_BATTERY_SECTION, MCE_CONF_LOW_PERCENT_KEY, 5, NULL);
667+
private.use_capacity_level = mce_conf_get_bool(MCE_CONF_BATTERY_SECTION, MCE_CONF_USE_CAPACITY_LEVEL, false, NULL);
668+
private.level_low_critical = mce_conf_get_bool(MCE_CONF_BATTERY_SECTION, MCE_CONF_CAPACITY_LOW_CRITICAL_KEY, false, NULL);
642669

643670
/* Find battery/charger devices and add them to private */
644671
xup_find_devices();

0 commit comments

Comments
 (0)