This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch master
in repository enlightenment.

View the commit online.

commit 48d4dbbb209bfc4cbffcf45bf5ac8377b83a1eed
Author: Carsten Haitzler <ras...@rasterman.com>
AuthorDate: Fri Apr 4 12:00:56 2025 +0100

    battery - support charge limit control for battery life improvement
    
    support newish controls for setting maximum battery charge which is
    used to improve battery life. add a slider that shows it and allow
    user to change it.
    
    @feat
---
 src/bin/system/e_system.h          |   3 +
 src/bin/system/e_system_battery.c  | 136 +++++++++++++++++++++++++++++++++++++
 src/bin/system/e_system_main.c     |   2 +
 src/bin/system/meson.build         |   1 +
 src/modules/battery/e_mod_main.c   |  69 ++++++++++++++-----
 src/modules/battery/e_mod_main.h   |   1 +
 src/modules/battery/e_mod_sysctl.c |   2 +
 src/modules/battery/e_mod_udev.c   |   9 +++
 src/modules/battery/e_mod_upower.c |   1 +
 9 files changed, 207 insertions(+), 17 deletions(-)

diff --git a/src/bin/system/e_system.h b/src/bin/system/e_system.h
index 4eb4a5c33..b78cdb06d 100644
--- a/src/bin/system/e_system.h
+++ b/src/bin/system/e_system.h
@@ -129,6 +129,9 @@ void e_system_ddc_shutdown(void);
 void e_system_acpi_init(void);
 void e_system_acpi_shutdown(void);
 
+void e_system_battery_init(void);
+void e_system_battery_shutdown(void);
+
 extern Ecore_Exe *e_system_run(const char *exe);
 
 #endif
diff --git a/src/bin/system/e_system_battery.c b/src/bin/system/e_system_battery.c
new file mode 100644
index 000000000..8ebbe7f85
--- /dev/null
+++ b/src/bin/system/e_system_battery.c
@@ -0,0 +1,136 @@
+#include "e_system.h"
+#if defined __OpenBSD__
+// no local funcs
+#elif defined __FreeBSD__
+// no local funcs
+#else
+
+typedef struct
+{
+  char *syspath;
+} Dev;
+
+static Eina_List *devices = NULL;
+static Eeze_Udev_Watch *watch = NULL;
+
+static Dev *
+dev_find(const char *syspath)
+{
+  Eina_List *l;
+  Dev *d;
+
+  EINA_LIST_FOREACH(devices, l, d)
+    {
+      if (!strcmp(syspath, d->syspath)) return d;
+    }
+  return NULL;
+}
+
+static Eina_Bool
+dev_have(const char *file)
+{
+  if (dev_find(file)) return EINA_TRUE;
+  return EINA_FALSE;
+}
+
+static void
+dev_del(Dev *d)
+{
+  if (!d) return;
+  devices = eina_list_remove(devices, d);
+  free(d->syspath);
+  free(d);
+}
+
+static Dev *
+dev_add(const char *syspath)
+{
+  Dev *d = NULL;
+
+  fprintf(stderr, "BAT: ADD BAT [%s]\n", syspath);
+  d = calloc(1, sizeof(Dev));
+  if (!d) return NULL;
+  d->syspath = strdup(syspath);
+  if (!d->syspath)
+    {
+      free(d);
+      return NULL;
+    }
+  devices = eina_list_append(devices, d);
+  return d;
+}
+
+static void
+_cb_eeze(const char *syspath, Eeze_Udev_Event ev,
+         void *data EINA_UNUSED, Eeze_Udev_Watch *w EINA_UNUSED)
+{
+  if ((ev & EEZE_UDEV_EVENT_ADD) ||
+      (ev & EEZE_UDEV_EVENT_ONLINE))
+    {
+      if (!dev_have(syspath)) dev_add(syspath);
+    }
+  else if ((ev & EEZE_UDEV_EVENT_REMOVE) ||
+           (ev & EEZE_UDEV_EVENT_OFFLINE))
+    {
+      dev_del(dev_find(syspath));
+    }
+  // else - some update but we don't care here
+
+}
+
+static void
+_cb_battery_lim_set(void *data EINA_UNUSED, const char *params EINA_UNUSED)
+{ // reply = "dev1 -|p dev2 -|p ..."
+  char dev[1024] = "", buf2[32];
+  int val = 0;
+  Dev *d;
+  int fd;
+
+  if (sscanf(params, "%1023s %i", dev, &val) != 2) return;
+  if (val < 1) val = 1;
+  else if (val > 100) val = 100;
+  d = dev_find(dev);
+  fprintf(stderr, "BAT: device = %p for [%s]\n", d, dev);
+  if (!d) return;
+  snprintf(dev, sizeof(dev), "%s/charge_control_end_threshold", d->syspath);
+  snprintf(buf2, sizeof(buf2), "%i", val);
+  fd = open(dev, O_WRONLY);
+  fprintf(stderr, "BAT: device [%s] fd = %i -> [%s]\n", dev, fd, buf2);
+  if (fd >= 0)
+    {
+      if (write(fd, buf2, strlen(buf2)) <= 0)
+        ERR("Write failed of [%s] to [%s]\n", buf2, dev);
+      close(fd);
+    }
+}
+#endif
+
+void
+e_system_battery_init(void)
+{
+#if defined __OpenBSD__
+// no local funcs
+#elif defined __FreeBSD__
+// no local funcs
+#else
+  Eina_List *devs;
+  const char *dev;
+
+  devs = eeze_udev_find_by_type(EEZE_UDEV_TYPE_POWER_BAT, NULL);
+  fprintf(stderr, "BAT: devices = %p\n", devs);
+  EINA_LIST_FREE(devs, dev)
+    {
+      if (!dev_have(dev)) dev_add(dev);
+    }
+
+  watch = eeze_udev_watch_add(EEZE_UDEV_TYPE_POWER_BAT, EEZE_UDEV_EVENT_NONE,
+                              _cb_eeze, NULL);
+#endif
+  e_system_inout_command_register("battery-lim-set", _cb_battery_lim_set, NULL);
+}
+
+void
+e_system_battery_shutdown(void)
+{
+   // only shutdown things we really have to - no need to free mem etc.
+}
diff --git a/src/bin/system/e_system_main.c b/src/bin/system/e_system_main.c
index 2c789d150..f2ac0abe4 100644
--- a/src/bin/system/e_system_main.c
+++ b/src/bin/system/e_system_main.c
@@ -174,6 +174,7 @@ main(int argc EINA_UNUSED, const char **argv EINA_UNUSED)
    CONF_INIT_CHECK("l2ping",    e_system_l2ping_init,    init_l2ping);
    CONF_INIT_CHECK("cpufreq",   e_system_cpufreq_init,   init_cpufreq);
    CONF_INIT_CHECK("acpi",      e_system_acpi_init,      init_acpi);
+   CONF_INIT_CHECK("battery",   e_system_battery_init,   init_battery);
 
    if (systems == 0)
      {
@@ -185,6 +186,7 @@ main(int argc EINA_UNUSED, const char **argv EINA_UNUSED)
 
    ecore_main_loop_begin();
 
+   CONF_SHUTDOWN(e_system_battery_shutdown,   init_battery);
    CONF_SHUTDOWN(e_system_acpi_shutdown,      init_acpi);
    CONF_SHUTDOWN(e_system_cpufreq_shutdown,   init_cpufreq);
    CONF_SHUTDOWN(e_system_l2ping_shutdown,    init_l2ping);
diff --git a/src/bin/system/meson.build b/src/bin/system/meson.build
index d4c9fe17b..d3008e659 100644
--- a/src/bin/system/meson.build
+++ b/src/bin/system/meson.build
@@ -9,6 +9,7 @@ src = [
   'e_system_l2ping.c',
   'e_system_cpufreq.c',
   'e_system_acpi.c',
+  'e_system_battery.c',
   'e_system.h',
 ]
 executable('enlightenment_system', src,
diff --git a/src/modules/battery/e_mod_main.c b/src/modules/battery/e_mod_main.c
index 88b34ec94..0bfb0cff8 100644
--- a/src/modules/battery/e_mod_main.c
+++ b/src/modules/battery/e_mod_main.c
@@ -34,6 +34,8 @@ typedef struct _Instance Instance;
 
 typedef struct __Popup_Widgets
 {
+   Battery     *bat;
+
    Evas_Object *pb_usage;
    Evas_Object *state;
    Evas_Object *remaining;
@@ -43,6 +45,7 @@ typedef struct __Popup_Widgets
    Evas_Object *drain;
    Evas_Object *full;
    Evas_Object *power;
+   Evas_Object *charge_lim;
 
    Evas_Object *gr_bat;
    Evas_Object *gr_pow;
@@ -373,6 +376,9 @@ _battery_popup_usage_content_update_cb(void *data)
         else
           elm_object_text_set(w->power, _("Unknown"));
 
+        if ((w->charge_lim) && (bat->charge_lim >= 0))
+          elm_slider_value_set(w->charge_lim, bat->charge_lim);
+
          {
            int *v_full, *v_pow, *v_crg, age;
            unsigned int vals_num;
@@ -470,6 +476,16 @@ _icon_get(void *data EINA_UNUSED, Evas_Object *obj, const char *part)
    return ic;
 }
 
+static void
+_cb_charge_lim_change(void *data, Evas_Object *obj, void *info EINA_UNUSED)
+{
+   _Popup_Widgets *w = data;
+   double v = elm_slider_value_get(obj);
+
+   w->bat->charge_lim = (int)v;
+   e_system_send("battery-lim-set", "%s %i\n", w->bat->udi, (int)v);
+}
+
 static Evas_Object *
 _content_get(void *data, Evas_Object *obj, const char *part)
 {
@@ -599,32 +615,49 @@ _content_get(void *data, Evas_Object *obj, const char *part)
    elm_table_pack(tb, o, 1, 3, 1, 1);
    evas_object_show(o);
 
+   if (w->bat->charge_lim >= 0)
+     {
+       w->charge_lim = o = elm_slider_add(obj);
+       evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
+       evas_object_size_hint_weight_set(o, 1.0,  1.0);
+       elm_object_text_set(o, _("Charge Limit"));
+       elm_slider_unit_format_set(o, "%1.0f%%");
+       elm_slider_indicator_format_set(o, "%1.0f%%");
+       elm_slider_min_max_set(o, 10, 100);
+       elm_slider_step_set(o, 5);
+       elm_slider_value_set(o, w->bat->charge_lim);
+       evas_object_smart_callback_add(o, "changed", _cb_charge_lim_change, w);
+       elm_table_pack(tb, o, 0, 4, 8, 1);
+       evas_object_show(o);
+     }
+   else w->charge_lim = NULL;
+
    w->gr_pow = o = e_graph_add(obj);
    evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
    evas_object_size_hint_weight_set(o, 1.0,  1.0);
    evas_object_size_hint_min_set(o, ELM_SCALE_SIZE(80), ELM_SCALE_SIZE(40));
-   elm_table_pack(tb, o, 0, 4, 8, 1);
-   evas_object_show(o);
-
-   o = elm_label_add(obj);
-   elm_object_text_set(o, _("Energy"));
-   evas_object_size_hint_align_set(o, 0.0, 0.0);
-   evas_object_size_hint_weight_set(o, 1.0, 0);
-   elm_table_pack(tb, o, 1, 4, 1, 1);
-   evas_object_show(o);
-
-   w->gr_crg = o = e_graph_add(obj);
-   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
-   evas_object_size_hint_weight_set(o, 1.0,  1.0);
-   evas_object_size_hint_min_set(o, ELM_SCALE_SIZE(80), ELM_SCALE_SIZE(40));
    elm_table_pack(tb, o, 0, 5, 8, 1);
    evas_object_show(o);
 
+   o = elm_label_add(obj);
+   elm_object_text_set(o, _("Energy"));
+   evas_object_size_hint_align_set(o, 0.0, 0.0);
+   evas_object_size_hint_weight_set(o, 1.0, 0);
+   elm_table_pack(tb, o, 1, 6, 1, 1);
+   evas_object_show(o);
+
+   w->gr_crg = o = e_graph_add(obj);
+   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(o, 1.0,  1.0);
+   evas_object_size_hint_min_set(o, ELM_SCALE_SIZE(80), ELM_SCALE_SIZE(40));
+   elm_table_pack(tb, o, 0, 7, 8, 1);
+   evas_object_show(o);
+
    o = elm_label_add(obj);
    elm_object_text_set(o, _("(Dis)charge"));
    evas_object_size_hint_align_set(o, 0.0, 0.0);
    evas_object_size_hint_weight_set(o, 1.0, 0);
-   elm_table_pack(tb, o, 1, 5, 1, 1);
+   elm_table_pack(tb, o, 1, 8, 1, 1);
    evas_object_show(o);
 
    return tb;
@@ -657,8 +690,8 @@ _battery_popup_usage_new(Instance *inst)
    evas_object_show(tb);
 
    rec = evas_object_rectangle_add(evas_object_evas_get(base));
-   evas_object_size_hint_min_set(rec, ELM_SCALE_SIZE(400), ELM_SCALE_SIZE(280));
-   evas_object_size_hint_max_set(rec, ELM_SCALE_SIZE(560), ELM_SCALE_SIZE(450));
+   evas_object_size_hint_min_set(rec, ELM_SCALE_SIZE(400), ELM_SCALE_SIZE(330));
+   evas_object_size_hint_max_set(rec, ELM_SCALE_SIZE(560), ELM_SCALE_SIZE(480));
    elm_table_pack(tb, rec, 0, 0, 1, 1);
 
    glist = elm_genlist_add(base);
@@ -687,6 +720,8 @@ _battery_popup_usage_new(Instance *inst)
    EINA_LIST_FOREACH(device_batteries, l, bat)
      {
         _Popup_Widgets *w = &pd->widgets[i++];
+
+        w->bat = bat;
         if ((bat->vendor) && (bat->model))
           snprintf(buf, sizeof(buf), _("Battery: %s (%s)"), bat->vendor, bat->model);
         else if (bat->vendor)
diff --git a/src/modules/battery/e_mod_main.h b/src/modules/battery/e_mod_main.h
index 716b47b71..2a9999595 100644
--- a/src/modules/battery/e_mod_main.h
+++ b/src/modules/battery/e_mod_main.h
@@ -117,6 +117,7 @@ struct _Battery
    const char   *technology;
    const char   *model;
    const char   *vendor;
+   int           charge_lim;
    int           history_power_now_max;
    Eina_Bool     got_prop E_BITFIELD;
    Eldbus_Proxy *proxy;
diff --git a/src/modules/battery/e_mod_sysctl.c b/src/modules/battery/e_mod_sysctl.c
index 7a800b11d..713329ea3 100644
--- a/src/modules/battery/e_mod_sysctl.c
+++ b/src/modules/battery/e_mod_sysctl.c
@@ -62,6 +62,7 @@ _battery_sysctl_start(void)
              bat->technology = eina_stringshare_add("Unknown");
              bat->model = eina_stringshare_add("Unknown");
              bat->vendor = eina_stringshare_add("Unknown");
+             bat->charge_lim = -1;
              bat->timer = ecore_timer_add(10.0, _battery_sysctl_battery_update_poll, NULL);
              device_batteries = eina_list_append(device_batteries, bat);
           }
@@ -105,6 +106,7 @@ _battery_sysctl_start(void)
              bat->model = eina_stringshare_add(battio.bix.model);
              bat->design_charge = battio.bix.dcap;
              bat->last_full_charge = battio.bix.lfcap;
+             bat->charge_lim = -1;
              bat->timer = ecore_timer_add(10.0, _battery_sysctl_battery_update_poll, NULL);
              bat->unit = i;
              device_batteries = eina_list_append(device_batteries, bat);
diff --git a/src/modules/battery/e_mod_udev.c b/src/modules/battery/e_mod_udev.c
index b8c907364..127f704d2 100644
--- a/src/modules/battery/e_mod_udev.c
+++ b/src/modules/battery/e_mod_udev.c
@@ -163,6 +163,10 @@ _battery_udev_battery_add(const char *syspath)
    bat->last_update = ecore_time_get();
    bat->udi = eina_stringshare_add(syspath);
    bat->timer = ecore_timer_add(10.0, _battery_udev_battery_update_poll, bat);
+
+   test = eeze_udev_syspath_get_sysattr(syspath, "charge_control_end_threshold");
+   if (!test) bat->charge_lim = -1;
+   else bat->charge_lim = atoi(test);
    device_batteries = eina_list_append(device_batteries, bat);
    _battery_udev_battery_update(syspath, bat);
 }
@@ -330,6 +334,11 @@ _battery_udev_battery_update(const char *syspath, Battery *bat)
      }
    else
      bat->charging = 0;
+
+   test = eeze_udev_syspath_get_sysattr(bat->udi, "charge_control_end_threshold");
+   if (!test) bat->charge_lim = -1;
+   else bat->charge_lim = atoi(test);
+
    test = eeze_udev_syspath_get_property(bat->udi, "POWER_SUPPLY_ENERGY_NOW");
    if (!test)
      test = eeze_udev_syspath_get_property(bat->udi, "POWER_SUPPLY_CHARGE_NOW");
diff --git a/src/modules/battery/e_mod_upower.c b/src/modules/battery/e_mod_upower.c
index 5826ed3f5..d817d2fbc 100644
--- a/src/modules/battery/e_mod_upower.c
+++ b/src/modules/battery/e_mod_upower.c
@@ -227,6 +227,7 @@ _process_battery(Eldbus_Proxy *proxy)
    bat->udi = eina_stringshare_add(eldbus_object_path_get(eldbus_proxy_object_get(proxy)));
    eldbus_proxy_property_get_all(proxy, _bat_get_all_cb, bat);
    eldbus_proxy_signal_handler_add(upower_proxy_bat, "PropertiesChanged", _bat_changed_cb, bat);
+   bat->charge_lim = -1;
    device_batteries = eina_list_append(device_batteries, bat);
    _battery_device_update();
 }

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to