diff options
author | Lennart Poettering <lennart@poettering.net> | 2023-06-05 11:49:35 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2023-06-05 12:18:21 +0200 |
commit | af4e8e86ec91389a04df2b1b8621c0ad5c84917b (patch) | |
tree | 14fe71addd6fa8acaeadd9ec0954922551b12ab9 /src/shared | |
parent | add support for KSM (diff) | |
download | systemd-af4e8e86ec91389a04df2b1b8621c0ad5c84917b.tar.xz systemd-af4e8e86ec91389a04df2b1b8621c0ad5c84917b.zip |
battery-util: split out code that checks AC power state into its own .c/.h pair
No code change, just some splitting out of the relevant code from
udev-util.[ch].
This makes sense on its own, but is also prepartion to move the code
that checks for low battery state into battery-util.[ch], too.
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/battery-util.c | 178 | ||||
-rw-r--r-- | src/shared/battery-util.h | 4 | ||||
-rw-r--r-- | src/shared/condition.c | 2 | ||||
-rw-r--r-- | src/shared/meson.build | 1 | ||||
-rw-r--r-- | src/shared/sleep-config.c | 4 | ||||
-rw-r--r-- | src/shared/udev-util.c | 170 | ||||
-rw-r--r-- | src/shared/udev-util.h | 2 |
7 files changed, 186 insertions, 175 deletions
diff --git a/src/shared/battery-util.c b/src/shared/battery-util.c new file mode 100644 index 0000000000..aa93b531a0 --- /dev/null +++ b/src/shared/battery-util.c @@ -0,0 +1,178 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "sd-device.h" + +#include "device-private.h" +#include "device-util.h" +#include "string-util.h" +#include "battery-util.h" + +static int device_is_power_sink(sd_device *device) { + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + bool found_source = false, found_sink = false; + sd_device *parent, *d; + int r; + + assert(device); + + /* USB-C power supply device has two power roles: source or sink. See, + * https://docs.kernel.org/admin-guide/abi-testing.html#abi-file-testing-sysfs-class-typec */ + + r = sd_device_enumerator_new(&e); + if (r < 0) + return r; + + r = sd_device_enumerator_allow_uninitialized(e); + if (r < 0) + return r; + + r = sd_device_enumerator_add_match_subsystem(e, "typec", true); + if (r < 0) + return r; + + r = sd_device_get_parent(device, &parent); + if (r < 0) + return r; + + r = sd_device_enumerator_add_match_parent(e, parent); + if (r < 0) + return r; + + FOREACH_DEVICE(e, d) { + const char *val; + + r = sd_device_get_sysattr_value(d, "power_role", &val); + if (r < 0) { + if (r != -ENOENT) + log_device_debug_errno(d, r, "Failed to read 'power_role' sysfs attribute, ignoring: %m"); + continue; + } + + if (strstr(val, "[source]")) { + found_source = true; + log_device_debug(d, "The USB type-C port is in power source mode."); + } else if (strstr(val, "[sink]")) { + found_sink = true; + log_device_debug(d, "The USB type-C port is in power sink mode."); + } + } + + if (found_sink) + log_device_debug(device, "The USB type-C device has at least one port in power sink mode."); + else if (!found_source) + log_device_debug(device, "The USB type-C device has no port in power source mode, assuming the device is in power sink mode."); + else + log_device_debug(device, "All USB type-C ports are in power source mode."); + + return found_sink || !found_source; +} + +static bool battery_is_discharging(sd_device *d) { + const char *val; + int r; + + assert(d); + + r = sd_device_get_sysattr_value(d, "scope", &val); + if (r < 0) { + if (r != -ENOENT) + log_device_debug_errno(d, r, "Failed to read 'scope' sysfs attribute, ignoring: %m"); + } else if (streq(val, "Device")) { + log_device_debug(d, "The power supply is a device battery, ignoring device."); + return false; + } + + r = device_get_sysattr_bool(d, "present"); + if (r < 0) + log_device_debug_errno(d, r, "Failed to read 'present' sysfs attribute, assuming the battery is present: %m"); + else if (r == 0) { + log_device_debug(d, "The battery is not present, ignoring the power supply."); + return false; + } + + /* Possible values: "Unknown", "Charging", "Discharging", "Not charging", "Full" */ + r = sd_device_get_sysattr_value(d, "status", &val); + if (r < 0) { + log_device_debug_errno(d, r, "Failed to read 'status' sysfs attribute, assuming the battery is discharging: %m"); + return true; + } + if (!streq(val, "Discharging")) { + log_device_debug(d, "The battery status is '%s', assuming the battery is not used as a power source of this machine.", val); + return false; + } + + return true; +} + +int on_ac_power(void) { + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + bool found_ac_online = false, found_discharging_battery = false; + sd_device *d; + int r; + + r = sd_device_enumerator_new(&e); + if (r < 0) + return r; + + r = sd_device_enumerator_allow_uninitialized(e); + if (r < 0) + return r; + + r = sd_device_enumerator_add_match_subsystem(e, "power_supply", true); + if (r < 0) + return r; + + FOREACH_DEVICE(e, d) { + /* See + * https://github.com/torvalds/linux/blob/4eef766b7d4d88f0b984781bc1bcb574a6eafdc7/include/linux/power_supply.h#L176 + * for defined power source types. Also see: + * https://docs.kernel.org/admin-guide/abi-testing.html#abi-file-testing-sysfs-class-power */ + + const char *val; + r = sd_device_get_sysattr_value(d, "type", &val); + if (r < 0) { + log_device_debug_errno(d, r, "Failed to read 'type' sysfs attribute, ignoring device: %m"); + continue; + } + + /* Ignore USB-C power supply in source mode. See issue #21988. */ + if (streq(val, "USB")) { + r = device_is_power_sink(d); + if (r <= 0) { + if (r < 0) + log_device_debug_errno(d, r, "Failed to determine the current power role, ignoring device: %m"); + else + log_device_debug(d, "USB power supply is in source mode, ignoring device."); + continue; + } + } + + if (streq(val, "Battery")) { + if (battery_is_discharging(d)) { + found_discharging_battery = true; + log_device_debug(d, "The power supply is a battery and currently discharging."); + } + continue; + } + + r = device_get_sysattr_unsigned(d, "online", NULL); + if (r < 0) { + log_device_debug_errno(d, r, "Failed to query 'online' sysfs attribute, ignoring device: %m"); + continue; + } else if (r > 0) /* At least 1 and 2 are defined as different types of 'online' */ + found_ac_online = true; + + log_device_debug(d, "The power supply is currently %s.", r > 0 ? "online" : "offline"); + } + + if (found_ac_online) { + log_debug("Found at least one online non-battery power supply, system is running on AC."); + return true; + } else if (found_discharging_battery) { + log_debug("Found at least one discharging battery and no online power sources, assuming system is running from battery."); + return false; + } else { + log_debug("No power supply reported online and no discharging battery found, assuming system is running on AC."); + return true; + } +} diff --git a/src/shared/battery-util.h b/src/shared/battery-util.h new file mode 100644 index 0000000000..4089fff0c4 --- /dev/null +++ b/src/shared/battery-util.h @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +int on_ac_power(void); diff --git a/src/shared/condition.c b/src/shared/condition.c index fce3fc2afb..9eb49d0eb5 100644 --- a/src/shared/condition.c +++ b/src/shared/condition.c @@ -18,6 +18,7 @@ #include "apparmor-util.h" #include "architecture.h" #include "audit-util.h" +#include "battery-util.h" #include "blockdev-util.h" #include "cap-list.h" #include "cgroup-util.h" @@ -56,7 +57,6 @@ #include "string-util.h" #include "tomoyo-util.h" #include "tpm2-util.h" -#include "udev-util.h" #include "uid-alloc-range.h" #include "user-util.h" #include "virt.h" diff --git a/src/shared/meson.build b/src/shared/meson.build index 31241bc08d..b34d218c1e 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -6,6 +6,7 @@ shared_sources = files( 'ask-password-api.c', 'barrier.c', 'base-filesystem.c', + 'battery-util.c', 'binfmt-util.c', 'bitmap.c', 'blockdev-util.c', diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c index d388c89192..51aebf2f0d 100644 --- a/src/shared/sleep-config.c +++ b/src/shared/sleep-config.c @@ -18,6 +18,7 @@ #include "sd-device.h" #include "alloc-util.h" +#include "battery-util.h" #include "blockdev-util.h" #include "btrfs-util.h" #include "conf-parser.h" @@ -34,15 +35,14 @@ #include "log.h" #include "macro.h" #include "path-util.h" -#include "sleep-config.h" #include "siphash24.h" +#include "sleep-config.h" #include "stat-util.h" #include "stdio-util.h" #include "string-table.h" #include "string-util.h" #include "strv.h" #include "time-util.h" -#include "udev-util.h" #define BATTERY_LOW_CAPACITY_LEVEL 5 #define DISCHARGE_RATE_FILEPATH "/var/lib/systemd/sleep/battery_discharge_percentage_rate_per_hour" diff --git a/src/shared/udev-util.c b/src/shared/udev-util.c index 646eaf9135..088eb0fe9a 100644 --- a/src/shared/udev-util.c +++ b/src/shared/udev-util.c @@ -591,176 +591,6 @@ int udev_queue_init(void) { return TAKE_FD(fd); } -static int device_is_power_sink(sd_device *device) { - _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; - bool found_source = false, found_sink = false; - sd_device *parent, *d; - int r; - - assert(device); - - /* USB-C power supply device has two power roles: source or sink. See, - * https://docs.kernel.org/admin-guide/abi-testing.html#abi-file-testing-sysfs-class-typec */ - - r = sd_device_enumerator_new(&e); - if (r < 0) - return r; - - r = sd_device_enumerator_allow_uninitialized(e); - if (r < 0) - return r; - - r = sd_device_enumerator_add_match_subsystem(e, "typec", true); - if (r < 0) - return r; - - r = sd_device_get_parent(device, &parent); - if (r < 0) - return r; - - r = sd_device_enumerator_add_match_parent(e, parent); - if (r < 0) - return r; - - FOREACH_DEVICE(e, d) { - const char *val; - - r = sd_device_get_sysattr_value(d, "power_role", &val); - if (r < 0) { - if (r != -ENOENT) - log_device_debug_errno(d, r, "Failed to read 'power_role' sysfs attribute, ignoring: %m"); - continue; - } - - if (strstr(val, "[source]")) { - found_source = true; - log_device_debug(d, "The USB type-C port is in power source mode."); - } else if (strstr(val, "[sink]")) { - found_sink = true; - log_device_debug(d, "The USB type-C port is in power sink mode."); - } - } - - if (found_sink) - log_device_debug(device, "The USB type-C device has at least one port in power sink mode."); - else if (!found_source) - log_device_debug(device, "The USB type-C device has no port in power source mode, assuming the device is in power sink mode."); - else - log_device_debug(device, "All USB type-C ports are in power source mode."); - - return found_sink || !found_source; -} - -static bool battery_is_discharging(sd_device *d) { - const char *val; - int r; - - assert(d); - - r = sd_device_get_sysattr_value(d, "scope", &val); - if (r < 0) { - if (r != -ENOENT) - log_device_debug_errno(d, r, "Failed to read 'scope' sysfs attribute, ignoring: %m"); - } else if (streq(val, "Device")) { - log_device_debug(d, "The power supply is a device battery, ignoring device."); - return false; - } - - r = device_get_sysattr_bool(d, "present"); - if (r < 0) - log_device_debug_errno(d, r, "Failed to read 'present' sysfs attribute, assuming the battery is present: %m"); - else if (r == 0) { - log_device_debug(d, "The battery is not present, ignoring the power supply."); - return false; - } - - /* Possible values: "Unknown", "Charging", "Discharging", "Not charging", "Full" */ - r = sd_device_get_sysattr_value(d, "status", &val); - if (r < 0) { - log_device_debug_errno(d, r, "Failed to read 'status' sysfs attribute, assuming the battery is discharging: %m"); - return true; - } - if (!streq(val, "Discharging")) { - log_device_debug(d, "The battery status is '%s', assuming the battery is not used as a power source of this machine.", val); - return false; - } - - return true; -} - -int on_ac_power(void) { - _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; - bool found_ac_online = false, found_discharging_battery = false; - sd_device *d; - int r; - - r = sd_device_enumerator_new(&e); - if (r < 0) - return r; - - r = sd_device_enumerator_allow_uninitialized(e); - if (r < 0) - return r; - - r = sd_device_enumerator_add_match_subsystem(e, "power_supply", true); - if (r < 0) - return r; - - FOREACH_DEVICE(e, d) { - /* See - * https://github.com/torvalds/linux/blob/4eef766b7d4d88f0b984781bc1bcb574a6eafdc7/include/linux/power_supply.h#L176 - * for defined power source types. Also see: - * https://docs.kernel.org/admin-guide/abi-testing.html#abi-file-testing-sysfs-class-power */ - - const char *val; - r = sd_device_get_sysattr_value(d, "type", &val); - if (r < 0) { - log_device_debug_errno(d, r, "Failed to read 'type' sysfs attribute, ignoring device: %m"); - continue; - } - - /* Ignore USB-C power supply in source mode. See issue #21988. */ - if (streq(val, "USB")) { - r = device_is_power_sink(d); - if (r <= 0) { - if (r < 0) - log_device_debug_errno(d, r, "Failed to determine the current power role, ignoring device: %m"); - else - log_device_debug(d, "USB power supply is in source mode, ignoring device."); - continue; - } - } - - if (streq(val, "Battery")) { - if (battery_is_discharging(d)) { - found_discharging_battery = true; - log_device_debug(d, "The power supply is a battery and currently discharging."); - } - continue; - } - - r = device_get_sysattr_unsigned(d, "online", NULL); - if (r < 0) { - log_device_debug_errno(d, r, "Failed to query 'online' sysfs attribute, ignoring device: %m"); - continue; - } else if (r > 0) /* At least 1 and 2 are defined as different types of 'online' */ - found_ac_online = true; - - log_device_debug(d, "The power supply is currently %s.", r > 0 ? "online" : "offline"); - } - - if (found_ac_online) { - log_debug("Found at least one online non-battery power supply, system is running on AC."); - return true; - } else if (found_discharging_battery) { - log_debug("Found at least one discharging battery and no online power sources, assuming system is running from battery."); - return false; - } else { - log_debug("No power supply reported online and no discharging battery found, assuming system is running on AC."); - return true; - } -} - bool udev_available(void) { static int cache = -1; diff --git a/src/shared/udev-util.h b/src/shared/udev-util.h index c3c3dbe842..175fa0b6f0 100644 --- a/src/shared/udev-util.h +++ b/src/shared/udev-util.h @@ -55,8 +55,6 @@ bool devpath_conflict(const char *a, const char *b); int udev_queue_is_empty(void); int udev_queue_init(void); -int on_ac_power(void); - bool udev_available(void); #if HAVE_SYS_SDT_H |