From c30bcb634a02282c1b7d49961bc065eafaa6db76 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 12 Feb 2025 10:59:09 -0600 Subject: [PATCH] Adjust trickle charge action behavior |ppd mode | charger | |------------|----------| |power-saver | trickle | |balanced | standard | |performance | fast | Also, avoid changing if already set to adaptive as well. Co-Authored-By: Marco Trevisan --- src/ppd-action-trickle-charge.c | 107 +++++++++++++++++++++++++------- tests/integration_test.py | 15 +++-- 2 files changed, 93 insertions(+), 29 deletions(-) diff --git a/src/ppd-action-trickle-charge.c b/src/ppd-action-trickle-charge.c index 7ccba55..cf8e037 100644 --- a/src/ppd-action-trickle-charge.c +++ b/src/ppd-action-trickle-charge.c @@ -17,12 +17,21 @@ #define CHARGE_TYPE_SYSFS_NAME "charge_type" +typedef enum { + PPD_CHARGE_TYPE_UNKNOWN, + PPD_CHARGE_TYPE_STANDARD, + PPD_CHARGE_TYPE_FAST, + PPD_CHARGE_TYPE_TRICKLE, + PPD_CHARGE_TYPE_CUSTOM, + PPD_CHARGE_TYPE_ADAPTIVE, +} PpdChargeType; + struct _PpdActionTrickleCharge { PpdAction parent_instance; GUdevClient *client; - gboolean active; + PpdChargeType charge_type; }; G_DEFINE_TYPE (PpdActionTrickleCharge, ppd_action_trickle_charge, PPD_TYPE_ACTION) @@ -46,16 +55,56 @@ ppd_action_trickle_charge_constructor (GType type, return object; } +PpdChargeType +ppd_string_to_charge_type (const gchar *str) +{ + if (g_str_equal (str, "Standard")) + return PPD_CHARGE_TYPE_STANDARD; + if (g_str_equal (str, "Fast")) + return PPD_CHARGE_TYPE_FAST; + if (g_str_equal (str, "Trickle")) + return PPD_CHARGE_TYPE_TRICKLE; + if (g_str_equal (str, "Custom")) + return PPD_CHARGE_TYPE_CUSTOM; + if (g_str_equal (str, "Adaptive")) + return PPD_CHARGE_TYPE_ADAPTIVE; + + return PPD_CHARGE_TYPE_UNKNOWN; +} + +static const char * +ppd_charge_type_to_string (PpdChargeType charge_type) +{ + switch (charge_type) { + case PPD_CHARGE_TYPE_STANDARD: + return "Standard"; + case PPD_CHARGE_TYPE_FAST: + return "Fast"; + case PPD_CHARGE_TYPE_TRICKLE: + return "Trickle"; + case PPD_CHARGE_TYPE_CUSTOM: + return "Custom"; + case PPD_CHARGE_TYPE_ADAPTIVE: + return "Adaptive"; + default: + return "Unknown"; + } +} + static void set_charge_type (PpdActionTrickleCharge *action, - const char *charge_type) + PpdChargeType charge_type) { + PpdActionTrickleCharge *self = PPD_ACTION_TRICKLE_CHARGE (action); g_autolist (GUdevDevice) devices = NULL; + const char *charge_type_value; devices = g_udev_client_query_by_subsystem (action->client, "power_supply"); if (devices == NULL) return; + charge_type_value = ppd_charge_type_to_string (charge_type); + for (GList *l = devices; l != NULL; l = l->next) { GUdevDevice *dev = l->data; const char *value; @@ -67,19 +116,23 @@ set_charge_type (PpdActionTrickleCharge *action, if (!value) continue; - if (g_strcmp0 (value, "Custom") == 0) { - g_debug ("Not setting charge type for '%s' due to 'Custom'", - g_udev_device_get_sysfs_path (dev)); + if (g_str_equal (value, charge_type_value)) continue; + + switch (ppd_string_to_charge_type (value)) { + case PPD_CHARGE_TYPE_CUSTOM: + case PPD_CHARGE_TYPE_ADAPTIVE: + g_debug ("Not setting charge type for '%s' due to '%s'", + g_udev_device_get_sysfs_path (dev), value); + break; + + default: + ppd_utils_write_sysfs (dev, CHARGE_TYPE_SYSFS_NAME, charge_type_value, NULL); + break; } - - if (g_strcmp0 (charge_type, value) == 0) - continue; - - ppd_utils_write_sysfs (dev, CHARGE_TYPE_SYSFS_NAME, charge_type, NULL); - - break; } + + self->charge_type = charge_type; } static gboolean @@ -88,15 +141,26 @@ ppd_action_trickle_charge_activate_profile (PpdAction *action, GError **error) { PpdActionTrickleCharge *self = PPD_ACTION_TRICKLE_CHARGE (action); + PpdChargeType charge_type; - if (profile == PPD_PROFILE_POWER_SAVER) { - set_charge_type (self, "Trickle"); - self->active = TRUE; - } else { - set_charge_type (self, "Fast"); - self->active = FALSE; + switch (profile) { + case PPD_PROFILE_POWER_SAVER: + charge_type = PPD_CHARGE_TYPE_TRICKLE; + break; + case PPD_PROFILE_BALANCED: + charge_type = PPD_CHARGE_TYPE_STANDARD; + break; + case PPD_PROFILE_PERFORMANCE: + charge_type = PPD_CHARGE_TYPE_FAST; + break; + default: + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Unknown profile %d", profile); + return FALSE; } + set_charge_type (self, charge_type); + return TRUE; } @@ -107,7 +171,6 @@ uevent_cb (GUdevClient *client, gpointer user_data) { PpdActionTrickleCharge *self = user_data; - const char *charge_type; if (g_strcmp0 (action, "add") != 0) return; @@ -115,11 +178,7 @@ uevent_cb (GUdevClient *client, if (!g_udev_device_has_sysfs_attr (device, CHARGE_TYPE_SYSFS_NAME)) return; - charge_type = self->active ? "Trickle" : "Fast"; - g_debug ("Updating charge type for '%s' to '%s'", - g_udev_device_get_sysfs_path (device), - charge_type); - set_charge_type (self, charge_type); + set_charge_type (self, self->charge_type); } static void diff --git a/tests/integration_test.py b/tests/integration_test.py index 913ec72..e9ce9b6 100644 --- a/tests/integration_test.py +++ b/tests/integration_test.py @@ -1814,13 +1814,18 @@ class Tests(dbusmock.DBusTestCase): self.set_dbus_property("ActiveProfile", GLib.Variant.new_string("power-saver")) self.assert_sysfs_attr_eventually_is(fastcharge, "charge_type", "Trickle") self.set_dbus_property("ActiveProfile", GLib.Variant.new_string("balanced")) - self.assert_sysfs_attr_eventually_is(fastcharge, "charge_type", "Fast") + self.assert_sysfs_attr_eventually_is(fastcharge, "charge_type", "Standard") # verify it's not touched again self.write_sysfs_attr(fastcharge, "charge_type", "Custom") self.set_dbus_property("ActiveProfile", GLib.Variant.new_string("power-saver")) self.assert_sysfs_attr_eventually_is(fastcharge, "charge_type", "Custom") + # verify it's not touched again + self.write_sysfs_attr(fastcharge, "charge_type", "Adaptive") + self.set_dbus_property("ActiveProfile", GLib.Variant.new_string("balanced")) + self.assert_sysfs_attr_eventually_is(fastcharge, "charge_type", "Adaptive") + def test_trickle_charge_system(self): """Trickle power_supply charge type""" @@ -1849,7 +1854,7 @@ class Tests(dbusmock.DBusTestCase): "power_supply", "MFi Fastcharge", None, - ["charge_type", "Fast", "scope", "Device"], + ["charge_type", "Standard", "scope", "Device"], [], ) @@ -1859,7 +1864,7 @@ class Tests(dbusmock.DBusTestCase): self.assert_action_enabled("trickle_charge") # Verify that charge-type didn't get touched - self.assert_sysfs_attr_eventually_is(fastcharge, "charge_type", "Fast") + self.assert_sysfs_attr_eventually_is(fastcharge, "charge_type", "Standard") self.assertEqual(self.get_mtime(fastcharge, "charge_type"), mtime) def test_trickle_charge_mode(self): @@ -1884,8 +1889,8 @@ class Tests(dbusmock.DBusTestCase): self.assert_action_enabled("trickle_charge") - # Verify that charge-type got changed to Fast on startup - self.assert_sysfs_attr_eventually_is(fastcharge, "charge_type", "Fast") + # Verify that charge-type got changed to Standard on startup + self.assert_sysfs_attr_eventually_is(fastcharge, "charge_type", "Standard") # Verify that charge-type got changed to Trickle when power saving self.set_dbus_property("ActiveProfile", GLib.Variant.new_string("power-saver"))