mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
Merge pull request #22006 from yuwata/on-ac-power
udev-util: ignore USB-C ports in power source mode
This commit is contained in:
commit
7359e3d35a
@ -3,7 +3,7 @@
|
||||
#include <getopt.h>
|
||||
|
||||
#include "main-func.h"
|
||||
#include "util.h"
|
||||
#include "udev-util.h"
|
||||
|
||||
static bool arg_verbose = false;
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "build.h"
|
||||
#include "dirent-util.h"
|
||||
#include "env-file.h"
|
||||
#include "env-util.h"
|
||||
#include "fd-util.h"
|
||||
@ -115,65 +114,6 @@ void in_initrd_force(bool value) {
|
||||
saved_in_initrd = value;
|
||||
}
|
||||
|
||||
int on_ac_power(void) {
|
||||
bool found_offline = false, found_online = false;
|
||||
_cleanup_closedir_ DIR *d = NULL;
|
||||
int r;
|
||||
|
||||
d = opendir("/sys/class/power_supply");
|
||||
if (!d)
|
||||
return errno == ENOENT ? true : -errno;
|
||||
|
||||
FOREACH_DIRENT(de, d, return -errno) {
|
||||
_cleanup_close_ int device_fd = -1;
|
||||
_cleanup_free_ char *contents = NULL;
|
||||
unsigned v;
|
||||
|
||||
device_fd = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC);
|
||||
if (device_fd < 0) {
|
||||
if (IN_SET(errno, ENOENT, ENOTDIR))
|
||||
continue;
|
||||
|
||||
return -errno;
|
||||
}
|
||||
|
||||
r = read_virtual_file_at(device_fd, "type", SIZE_MAX, &contents, NULL);
|
||||
if (r == -ENOENT)
|
||||
continue;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
delete_trailing_chars(contents, NEWLINE);
|
||||
|
||||
/* We assume every power source is AC, except for batteries. See
|
||||
* https://github.com/torvalds/linux/blob/4eef766b7d4d88f0b984781bc1bcb574a6eafdc7/include/linux/power_supply.h#L176
|
||||
* for defined power source types. Also see:
|
||||
* https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power */
|
||||
if (streq(contents, "Battery"))
|
||||
continue;
|
||||
|
||||
contents = mfree(contents);
|
||||
|
||||
r = read_virtual_file_at(device_fd, "online", SIZE_MAX, &contents, NULL);
|
||||
if (r == -ENOENT)
|
||||
continue;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
delete_trailing_chars(contents, NEWLINE);
|
||||
|
||||
r = safe_atou(contents, &v);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (v > 0) /* At least 1 and 2 are defined as different types of 'online' */
|
||||
found_online = true;
|
||||
else
|
||||
found_offline = true;
|
||||
}
|
||||
|
||||
return found_online || !found_offline;
|
||||
}
|
||||
|
||||
int container_get_leader(const char *machine, pid_t *pid) {
|
||||
_cleanup_free_ char *s = NULL, *class = NULL;
|
||||
const char *p;
|
||||
|
@ -20,8 +20,6 @@ int prot_from_flags(int flags) _const_;
|
||||
bool in_initrd(void);
|
||||
void in_initrd_force(bool value);
|
||||
|
||||
int on_ac_power(void);
|
||||
|
||||
/* Note: log2(0) == log2(1) == 0 here and below. */
|
||||
|
||||
#define CONST_LOG2ULL(x) ((x) > 1 ? (unsigned) __builtin_clzll(x) ^ 63U : 0)
|
||||
|
@ -50,9 +50,9 @@
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
#include "tomoyo-util.h"
|
||||
#include "udev-util.h"
|
||||
#include "uid-alloc-range.h"
|
||||
#include "user-util.h"
|
||||
#include "util.h"
|
||||
#include "virt.h"
|
||||
|
||||
Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate) {
|
||||
|
@ -579,3 +579,142 @@ 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://www.kernel.org/doc/Documentation/ABI/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;
|
||||
}
|
||||
|
||||
int on_ac_power(void) {
|
||||
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
|
||||
bool found_offline = false, found_online = 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) {
|
||||
const char *val;
|
||||
unsigned v;
|
||||
|
||||
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: %m");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We assume every power source is AC, except for batteries. See
|
||||
* https://github.com/torvalds/linux/blob/4eef766b7d4d88f0b984781bc1bcb574a6eafdc7/include/linux/power_supply.h#L176
|
||||
* for defined power source types. Also see:
|
||||
* https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power */
|
||||
if (streq(val, "Battery")) {
|
||||
log_device_debug(d, "The power supply is battery, ignoring.");
|
||||
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: %m");
|
||||
else
|
||||
log_device_debug(d, "USB power supply is in source mode, ignoring.");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
r = sd_device_get_sysattr_value(d, "online", &val);
|
||||
if (r < 0) {
|
||||
log_device_debug_errno(d, r, "Failed to read 'online' sysfs attribute, ignoring: %m");
|
||||
continue;
|
||||
}
|
||||
|
||||
r = safe_atou(val, &v);
|
||||
if (r < 0) {
|
||||
log_device_debug_errno(d, r, "Failed to parse 'online' attribute, ignoring: %m");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (v > 0) /* At least 1 and 2 are defined as different types of 'online' */
|
||||
found_online = true;
|
||||
else
|
||||
found_offline = true;
|
||||
|
||||
log_device_debug(d, "The power supply is currently %s.", v > 0 ? "online" : "offline");
|
||||
}
|
||||
|
||||
if (found_online)
|
||||
log_debug("Found at least one online non-battery power supply, system is running on AC power.");
|
||||
else if (!found_offline)
|
||||
log_debug("Found no offline non-battery power supply, assuming system is running on AC power.");
|
||||
else
|
||||
log_debug("All non-battery power supplies are offline, assuming system is running with battery.");
|
||||
|
||||
return found_online || !found_offline;
|
||||
}
|
||||
|
@ -53,6 +53,8 @@ int udev_resolve_subsys_kernel(const char *string, char *result, size_t maxsize,
|
||||
int udev_queue_is_empty(void);
|
||||
int udev_queue_init(void);
|
||||
|
||||
int on_ac_power(void);
|
||||
|
||||
#if HAVE_SYS_SDT_H
|
||||
|
||||
/* Each trace point can have different number of additional arguments. Note that when the macro is used only
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "strv.h"
|
||||
#include "tests.h"
|
||||
#include "tomoyo-util.h"
|
||||
#include "udev-util.h"
|
||||
#include "uid-alloc-range.h"
|
||||
#include "user-util.h"
|
||||
#include "virt.h"
|
||||
|
Loading…
Reference in New Issue
Block a user