udev-util: ignore USB-C ports in power source mode when detecting system is running on AC power
Fixes #21988.
This commit is contained in:
@@ -580,6 +580,66 @@ 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;
|
||||
@@ -617,6 +677,18 @@ int on_ac_power(void) {
|
||||
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");
|
||||
|
||||
Reference in New Issue
Block a user