diff mbox series

[v6,matchbox-panel-2] panel: added sysfs support

Message ID 20250815142901.1742993-1-dixitparmar19@gmail.com
State New
Headers show
Series [v6,matchbox-panel-2] panel: added sysfs support | expand

Commit Message

Dixit Parmar Aug. 15, 2025, 2:29 p.m. UTC
battery applet supports reading battery and supply
information from sysfs entries, /sys/class/power_supply/.

[YOCTO #12904]
https://bugzilla.yoctoproject.org/show_bug.cgi?id=12904

Signed-off-by: Dixit Parmar <dixitparmar19@gmail.com>
---
V5: https://lists.yoctoproject.org/g/yocto-patches/message/1802
---
 applets/battery/Makefile.am     |   4 +
 applets/battery/battery-acpi.c  |   2 +
 applets/battery/battery-apm.c   |   2 +
 applets/battery/battery-sysfs.c | 144 ++++++++++++++++++++++++++++++++
 applets/battery/battery.c       |   2 +
 applets/battery/battery.h       |   3 +-
 configure.ac                    |   4 +
 7 files changed, 159 insertions(+), 2 deletions(-)
 create mode 100644 applets/battery/battery-sysfs.c

Comments

Ross Burton Sept. 2, 2025, 5:38 p.m. UTC | #1
On 15 Aug 2025, at 15:29, Dixit Parmar via lists.yoctoproject.org <dixitparmar19=gmail.com@lists.yoctoproject.org> wrote:
> + if(!ac_exist && strncmp(file_content, "Mains", strlen("Mains")) == 0) {

So the docs for g_file_get_contents() says "The string stored in contents will be null-terminated” so you can neaten this code by using g_strchomp() once you’ve read it to remove the trailing newline, and then it’s just a string you can g_strcmp(contents, “Mains”) and g_strdup() at leisure.

> + ac_dev = g_malloc0(strlen(subdir_name) + 1);
> + strncpy(ac_dev, subdir_name, strlen(subdir_name));

As above, once you’ve g_strchomp()’d the newline away this is just a simple ac_dev = g_strdup(subdir_name);

There’s also a few places where tabs are used for indentation, so please reformat consistently as it is messing up the formatting.

Thanks,
Ross
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.
Dixit Parmar Sept. 6, 2025, 8:59 a.m. UTC | #2
> There’s also a few places where tabs are used for indentation, so please reformat consistently as it is messing up the formatting.
Can you please help me which place is messed up, I can check and
correct it. Also, what is the standard way to check it so I can follow
that everytime?
Thanks,
Dixit
Ross Burton Sept. 8, 2025, 10:45 a.m. UTC | #3
Hi Dixit,

On 6 Sep 2025, at 09:59, Dixit Parmar <dixitparmar19@gmail.com> wrote:
>
>> There’s also a few places where tabs are used for indentation, so please reformat consistently as it is messing up the formatting.
> Can you please help me which place is messed up, I can check and
> correct it.

pm_cleanup() is indented with eight spaces, whereas pm_support uses tabs.

Or eg these lines:

+ strncpy(batt_dev, subdir_name, strlen(subdir_name));
+ batt_exist = TRUE;

The first uses spaces, the second uses tabs.

As tabs are of an undefined size, it looks wrong on my editor.

> Also, what is the standard way to check it so I can follow
> that everytime?

Other code uses tabs for indentation, so you can simply configure your editor to do the same and then reformat the entire battery-sysfs.c.

Cheers,
Ross
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.
Dixit Parmar Sept. 10, 2025, 5:48 a.m. UTC | #4
Thanks for the clarification Ross.
I have reformatted the file with 8 tabs and floated v7. Kindly review.
diff mbox series

Patch

diff --git a/applets/battery/Makefile.am b/applets/battery/Makefile.am
index 9b02240..1b93a0b 100644
--- a/applets/battery/Makefile.am
+++ b/applets/battery/Makefile.am
@@ -5,6 +5,10 @@  applet_LTLIBRARIES = libbattery.la
 libbattery_la_SOURCES = battery.c battery.h
 libbattery_la_CPPFLAGS = $(AM_CPPFLAGS) -DDATADIR=\"$(pkgdatadir)/battery/\"
 
+if HAVE_SYSFS
+libbattery_la_SOURCES += battery-sysfs.c
+endif
+
 if HAVE_LIBAPM
 libbattery_la_LIBADD = -lapm
 libbattery_la_SOURCES += battery-apm.c
diff --git a/applets/battery/battery-acpi.c b/applets/battery/battery-acpi.c
index d1d3de9..42ef9c8 100644
--- a/applets/battery/battery-acpi.c
+++ b/applets/battery/battery-acpi.c
@@ -14,6 +14,8 @@  global_t global;
 adapter_t *ac;
 int batt_state, ac_state;
 
+void pm_cleanup(void) { }
+
 int pm_support(void)
 {
 	if(check_acpi_support() == NOT_SUPPORTED){
diff --git a/applets/battery/battery-apm.c b/applets/battery/battery-apm.c
index edaba43..f1501a0 100644
--- a/applets/battery/battery-apm.c
+++ b/applets/battery/battery-apm.c
@@ -9,6 +9,8 @@ 
 #include "battery.h"
 #include <apm.h>
 
+void pm_cleanup(void) { }
+
 int pm_support(void)
 {
 	if (1 == apm_exists ()) {
diff --git a/applets/battery/battery-sysfs.c b/applets/battery/battery-sysfs.c
new file mode 100644
index 0000000..e9c6c80
--- /dev/null
+++ b/applets/battery/battery-sysfs.c
@@ -0,0 +1,144 @@ 
+/*
+ * (C) Dixit Parmar
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Licensed under the GPL v2 or greater.
+ */
+
+#include "battery.h"
+#include <glib.h>
+
+#define PROCFS_PS_DIR "/sys/class/power_supply"
+
+static gchar *batt_dev;
+static gchar *ac_dev;
+static gboolean batt_exist = FALSE;
+static gboolean ac_exist = FALSE;
+
+void pm_cleanup(void)
+{
+        g_free(batt_dev);
+        g_free(ac_dev);
+}
+
+int pm_support(void)
+{
+	GDir *dir = g_dir_open(PROCFS_PS_DIR, 0, NULL);
+	if (dir != NULL) {
+		const gchar *subdir_name;
+		while ((subdir_name = g_dir_read_name(dir)) != NULL) {
+			gchar *subdir_path = g_build_filename(PROCFS_PS_DIR, subdir_name, NULL);
+			// Check if it's a directory
+			if (g_file_test(subdir_path, G_FILE_TEST_IS_DIR)) {
+				gchar *type_file_path = g_build_filename(subdir_path, "type", NULL);
+				// Check if the "type" file exists
+				if (g_file_test(type_file_path, G_FILE_TEST_EXISTS)) {
+					gchar *file_content = NULL;
+					gsize length;
+
+					if (g_file_get_contents(type_file_path, &file_content, &length, NULL)) {
+						if(!batt_exist && strncmp(file_content, "Battery", strlen("Battery")) == 0) {
+							batt_dev = g_malloc0(strlen(subdir_name) + 1);
+                                                        strncpy(batt_dev, subdir_name, strlen(subdir_name));
+							batt_exist = TRUE;
+						}
+						if(!ac_exist && strncmp(file_content, "Mains", strlen("Mains")) == 0) {
+							ac_dev = g_malloc0(strlen(subdir_name) + 1);
+							strncpy(ac_dev, subdir_name, strlen(subdir_name));
+							ac_exist = TRUE;
+						}
+						g_free(file_content);
+					}
+				}
+				g_free(type_file_path);
+			}
+			g_free(subdir_path);
+			if(batt_exist && ac_exist)
+				break;
+		}
+		g_dir_close(dir);
+	}
+	return (int)batt_exist;
+}
+
+static gboolean read_val_from_file(const gchar *dev, const gchar *f, gint64 *val)
+{
+	gboolean ret = FALSE;
+
+	if(dev != NULL && f != NULL && val != NULL) {
+		gchar *file_path = g_build_filename(PROCFS_PS_DIR, dev, f, NULL);
+                gchar *file_content;
+                gsize length;
+
+                if(g_file_get_contents(file_path, &file_content, &length, NULL)) {
+                       *val = g_ascii_strtoll(file_content, NULL, 10);
+			ret = TRUE;
+                }
+
+                g_free(file_content);
+		g_free(file_path);
+	}
+	return ret;
+}
+
+const char* pm_battery_icon(void)
+{
+	const char *icon;
+	gint64 temp_val = 0;
+	gint64 ac_status = 0;
+	gint64 batt_present = 0;
+	gint64 batt_percentage = 0;
+
+	if(batt_exist == FALSE)
+		return NULL;
+
+	/* Check battery presence */
+	if(read_val_from_file(batt_dev, "present", &temp_val))
+		batt_present = temp_val;
+
+	if(batt_present == 0) {
+		/* Battery is removed */
+		icon = "ac-adapter.png";
+		return icon;
+	}
+
+	/* Check Adaptor status*/
+	if(ac_exist && read_val_from_file(ac_dev, "online", &temp_val))
+		ac_status = temp_val;
+
+	/* Check battery percentage */
+	if(read_val_from_file(batt_dev, "capacity", &temp_val))
+		batt_percentage = temp_val;
+
+	if(ac_status == 1) {
+		/* We're charging */
+		if (batt_percentage < 10)
+			icon = "battery-charging-000.png";
+		else if (batt_percentage < 30)
+			icon = "battery-charging-020.png";
+		else if (batt_percentage < 50)
+			icon = "battery-charging-040.png";
+		else if (batt_percentage < 70)
+			icon = "battery-charging-060.png";
+		else if (batt_percentage < 90)
+			icon = "battery-charging-080.png";
+		else
+			icon = "battery-charging-100.png";
+	} else {
+		if (batt_percentage < 10)
+			icon = "battery-discharging-000.png";
+		else if (batt_percentage < 30)
+			icon = "battery-discharging-020.png";
+		else if (batt_percentage < 50)
+			icon = "battery-discharging-040.png";
+		else if (batt_percentage < 70)
+			icon = "battery-discharging-060.png";
+		else if (batt_percentage < 90)
+			icon = "battery-discharging-080.png";
+		else
+			icon = "battery-discharging-100.png";
+	}
+
+	return icon;
+}
diff --git a/applets/battery/battery.c b/applets/battery/battery.c
index b11517d..755042b 100644
--- a/applets/battery/battery.c
+++ b/applets/battery/battery.c
@@ -24,6 +24,8 @@  battery_applet_free (BatteryApplet *applet)
         g_source_remove (applet->timeout_id);
 
         g_slice_free (BatteryApplet, applet);
+
+        pm_cleanup ();
 }
 
 static gboolean
diff --git a/applets/battery/battery.h b/applets/battery/battery.h
index 534988f..7c54a3a 100644
--- a/applets/battery/battery.h
+++ b/applets/battery/battery.h
@@ -9,8 +9,7 @@ 
 #ifndef MB_APPLET_BATTERY_H
 #define MB_APPLET_BATTERY_H
 
-#include <string.h>
-
+void pm_cleanup(void);
 int pm_support(void);
 const char* pm_battery_icon(void);
 
diff --git a/configure.ac b/configure.ac
index be4d591..0f607f8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -61,6 +61,9 @@  AC_ARG_WITH(
 )
 
 case "$with_battery" in
+     "sysfs") enable_linux_sysfs=yes
+     enable_battery=yes
+     ;;
      "acpi") AC_CHECK_HEADERS(libacpi.h, enable_linux_acpi=yes, AC_MSG_FAILURE([You need to install libacpi]))
      enable_battery=yes
      ;;
@@ -75,6 +78,7 @@  esac
 AM_CONDITIONAL(HAVE_BATTERY, test x$enable_battery = xyes)
 AM_CONDITIONAL(HAVE_LIBAPM, test x$enable_linux_apm = xyes)
 AM_CONDITIONAL(HAVE_LIBACPI, test x$enable_linux_acpi = xyes)
+AM_CONDITIONAL(HAVE_SYSFS, test x$enable_linux_sysfs = xyes)
 
 # glib-genmarshal
 GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0`