all repos — tint2 @ 66acd8ed3890ee237d106d99a85d2a3b9c86f5d0

fork of the tint2 desktop panel for my custom setup - only minimized windows across all desktops for the taskbar

Add battery Mains/AC support for Linux

Add initial support for mains/ac adapters. This adds the
state only to the tooltip, but the code has been prepared
to update AC state together with normal battery updates,
so that it's possible to forward the state to the normal
panel area or trigger something on AC (dis)connection.
Sebastian Reichel sre@ring0.de
commit

66acd8ed3890ee237d106d99a85d2a3b9c86f5d0

parent

d1c22762c40b601f092925799b191ff54d559962

1 files changed, 121 insertions(+), 15 deletions(-)

jump to
M src/battery/linux.csrc/battery/linux.c

@@ -24,6 +24,12 @@

#include "common.h" #include "battery.h" +enum psy_type { + PSY_UNKNOWN, + PSY_BATTERY, + PSY_MAINS, +}; + struct psy_battery { /* generic properties */ gchar* name;

@@ -44,15 +50,25 @@ gint power_now;

enum chargestate status; }; +struct psy_mains { + /* generic properties */ + gchar* name; + /* sysfs files */ + gchar* path_online; + /* values */ + gboolean online; +}; + #define RETURN_ON_ERROR(err) if(error) { g_error_free(err); return FALSE; } static GList *batteries = NULL; +static GList *mains = NULL; static guint8 energy_to_percent(gint energy_now, gint energy_full) { return 0.5 + ((energy_now <= energy_full ? energy_now : energy_full) * 100.0) / energy_full; } -static gboolean power_supply_is_battery(const gchar *entryname) { +static enum psy_type power_supply_get_type(const gchar *entryname) { gchar *path_type = g_build_filename("/sys/class/power_supply", entryname, "type", NULL); GError *error = NULL; gchar *type;

@@ -60,16 +76,24 @@ gsize typelen;

g_file_get_contents(path_type, &type, &typelen, &error); g_free(path_type); - RETURN_ON_ERROR(error); + if (error) { + g_error_free(error); + return PSY_UNKNOWN; + } + + if(!g_strcmp0(type, "Battery\n")) { + g_free(type); + return PSY_BATTERY; + } - if(g_strcmp0(type, "Battery\n")) { + if(!g_strcmp0(type, "Mains\n")) { g_free(type); - return FALSE; + return PSY_MAINS; } g_free(type); - return TRUE; + return PSY_UNKNOWN; } static gboolean init_linux_battery(struct psy_battery *bat) {

@@ -134,6 +158,18 @@

return FALSE; } +static gboolean init_linux_mains(struct psy_mains *ac) { + const gchar *entryname = ac->name; + + ac->path_online = g_build_filename("/sys/class/power_supply", entryname, "online", NULL); + if (!g_file_test(ac->path_online, G_FILE_TEST_EXISTS)) { + g_free(ac->path_online); + return FALSE; + } + + return TRUE; +} + void free_linux_batteries() { GList *l = batteries;

@@ -152,7 +188,46 @@ batteries = g_list_delete_link(batteries, l);

l = next; } + l = mains; + while (l != NULL) { + GList *next = l->next; + struct psy_mains *ac = l->data; + + g_free(ac->name); + g_free(ac->path_online); + + mains = g_list_delete_link(mains, l); + l = next; + } + batteries = NULL; + mains = NULL; +} + +static void add_battery(const char *entryname) { + struct psy_battery *bat = g_malloc0(sizeof(*bat)); + bat->name = g_strdup(entryname); + + if(init_linux_battery(bat)) { + batteries = g_list_append(batteries, bat); + fprintf(stdout, "found battery \"%s\"\n", bat->name); + } else { + g_free(bat); + fprintf(stderr, RED "failed to initialize battery \"%s\"\n" RESET, entryname); + } +} + +static void add_mains(const char *entryname) { + struct psy_mains *ac = g_malloc0(sizeof(*ac)); + ac->name = g_strdup(entryname); + + if(init_linux_mains(ac)) { + mains = g_list_append(mains, ac); + fprintf(stdout, "found mains \"%s\"\n", ac->name); + } else { + g_free(ac); + fprintf(stderr, RED "failed to initialize mains \"%s\"\n" RESET, entryname); + } } gboolean init_linux_batteries() {

@@ -166,17 +241,17 @@ directory = g_dir_open("/sys/class/power_supply", 0, &error);

RETURN_ON_ERROR(error); while ((entryname = g_dir_read_name(directory))) { - if(!power_supply_is_battery(entryname)) - continue; + enum psy_type type = power_supply_get_type(entryname); - struct psy_battery *bat = g_malloc0(sizeof(*bat)); - bat->name = g_strdup(entryname); - if(init_linux_battery(bat)) { - batteries = g_list_append(batteries, bat); - fprintf(stdout, "found battery \"%s\"\n", bat->name); - } else { - g_free(bat); - fprintf(stderr, RED "failed to initialize battery \"%s\"\n" RESET, entryname); + switch(type) { + case PSY_BATTERY: + add_battery(entryname); + break; + case PSY_MAINS: + add_mains(entryname); + break; + default: + break; } }

@@ -241,6 +316,22 @@

return TRUE; } + +static gboolean update_linux_mains(struct psy_mains *ac) { + GError *error = NULL; + gchar *data; + gsize datalen; + ac->online = FALSE; + + /* online */ + g_file_get_contents(ac->path_online, &data, &datalen, &error); + RETURN_ON_ERROR(error); + ac->online = (atoi(data) == 1); + g_free(data); + + return TRUE; +} + void update_linux_batteries(enum chargestate *state, int8_t *percentage, int *seconds) { GList *l;

@@ -263,6 +354,11 @@

charging |= (bat->status == BATTERY_CHARGING); discharging |= (bat->status == BATTERY_DISCHARGING); full |= (bat->status == BATTERY_FULL); + } + + for (l = mains; l != NULL; l = l->next) { + struct psy_mains *ac = l->data; + update_linux_mains(ac); } /* build global state */

@@ -351,6 +447,16 @@ state, energy, percentage, power);

g_free(power); g_free(energy); + } + + for (l = mains; l != NULL; l = l->next) { + struct psy_mains *ac = l->data; + + if (tooltip->len) + g_string_append_c(tooltip, '\n'); + + g_string_append_printf(tooltip, "%s\n", ac->name); + g_string_append_printf(tooltip, ac->online ? "\tconnected" : "\tdisconnected"); } result = tooltip->str;