diff --git a/CMakeLists.txt b/CMakeLists.txt index dad7d9d..e2d1574 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,7 +78,20 @@ set( SOURCES src/config.c src/util/window.c ) if( ENABLE_BATTERY ) - set( SOURCES ${SOURCES} src/battery/battery.c src/battery/linux.c) + set( SOURCES ${SOURCES} src/battery/battery.c) + + if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + set( SOURCES ${SOURCES} src/battery/linux.c) + elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") + set( SOURCES ${SOURCES} src/battery/freebsd.c) + elseif(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD") + set( SOURCES ${SOURCES} src/battery/openbsd.c) + elseif(CMAKE_SYSTEM_NAME STREQUAL "NetBSD") + set( SOURCES ${SOURCES} src/battery/openbsd.c) + else(CMAKE_SYSTEM_NAME STREQUAL "Linux") + set( SOURCES ${SOURCES} src/battery/dummy.c) + endif(CMAKE_SYSTEM_NAME STREQUAL "Linux") + add_definitions( -DENABLE_BATTERY ) endif( ENABLE_BATTERY ) diff --git a/src/battery/battery.c b/src/battery/battery.c index babedf1..56dcf27 100644 --- a/src/battery/battery.c +++ b/src/battery/battery.c @@ -1,6 +1,6 @@ /************************************************************************** * -* Tint2 : battery +* Tint2 : Generic battery * * Copyright (C) 2009-2015 Sebastian Reichel * @@ -24,18 +24,6 @@ #include #include -#if defined(__OpenBSD__) || defined(__NetBSD__) -#include -#include -#include -#include -#endif - -#if defined(__FreeBSD__) -#include -#include -#endif - #include "window.h" #include "server.h" #include "panel.h" @@ -64,10 +52,6 @@ char *battery_uwheel_command; char *battery_dwheel_command; int battery_found; -#if defined(__OpenBSD__) || defined(__NetBSD__) -int apm_fd; -#endif - void update_battery_tick(void* arg) { if (!battery_enabled) @@ -154,9 +138,6 @@ void default_battery() battery_state.time.minutes = 0; battery_state.time.seconds = 0; battery_state.state = BATTERY_UNKNOWN; -#if defined(__OpenBSD__) || defined(__NetBSD__) - apm_fd = -1; -#endif } void cleanup_battery() @@ -181,51 +162,22 @@ void cleanup_battery() battery_timeout = NULL; battery_found = 0; -#if defined(__OpenBSD__) || defined(__NetBSD__) - if ((apm_fd != -1) && (close(apm_fd) == -1)) - warn("cannot close /dev/apm"); - apm_fd = -1; -#elif defined(__linux) - free_linux_batteries(); -#endif + battery_os_free(); } void init_battery() { if (!battery_enabled) return; - battery_found = 0; -#if defined(__OpenBSD__) || defined(__NetBSD__) - if (apm_fd > 0) - close(apm_fd); - apm_fd = open("/dev/apm", O_RDONLY); - if (apm_fd < 0) { - warn("ERROR: battery applet cannot open /dev/apm."); - battery_found = 0; - } else { - battery_found = 1; - } -#elif defined(__FreeBSD__) - int sysctl_out = 0; - size_t len = sizeof(sysctl_out); - battery_found = (sysctlbyname("hw.acpi.battery.state", &sysctl_out, &len, NULL, 0) == 0) || - (sysctlbyname("hw.acpi.battery.time", &sysctl_out, &len, NULL, 0) == 0) || - (sysctlbyname("hw.acpi.battery.life", &sysctl_out, &len, NULL, 0) == 0); -#elif defined(__linux) - battery_found = init_linux_batteries(); -#endif + battery_found = battery_os_init(); if (!battery_timeout) battery_timeout = add_timeout(10, 30000, update_battery_tick, 0, &battery_timeout); } char* battery_get_tooltip(void* obj) { -#if defined(__linux) - return linux_batteries_get_tooltip(); -#else - return g_strdup("No tooltip support for this OS!"); -#endif + return battery_os_tooltip(); } void init_battery_panel(void *p) @@ -258,100 +210,21 @@ void init_battery_panel(void *p) int update_battery() { - int seconds = 0; - int8_t new_percentage = 0; - int errors = 0; + int err; + /* reset */ battery_state.state = BATTERY_UNKNOWN; + battery_state.percentage = 0; + batstate_set_time(&battery_state, 0); -#if defined(__OpenBSD__) || defined(__NetBSD__) - struct apm_power_info info; - if (apm_fd > 0 && ioctl(apm_fd, APM_IOC_GETPOWER, &(info)) == 0) { - // best attempt at mapping to Linux battery states - switch (info.battery_state) { - case APM_BATT_CHARGING: - battery_state.state = BATTERY_CHARGING; - break; - default: - battery_state.state = BATTERY_DISCHARGING; - break; - } - - if (info.battery_life == 100) - battery_state.state = BATTERY_FULL; - - // no mapping for openbsd really - energy_full = 0; - energy_now = 0; - - if (info.minutes_left != -1) - seconds = info.minutes_left * 60; - else - seconds = -1; - - new_percentage = info.battery_life; - } else { - warn("power update: APM_IOC_GETPOWER"); - errors = 1; - } -#elif defined(__FreeBSD__) - int sysctl_out = 0; - size_t len = sizeof(sysctl_out); - - if (sysctlbyname("hw.acpi.battery.state", &sysctl_out, &len, NULL, 0) == 0) { - // attemp to map the battery state to Linux - battery_state.state = BATTERY_UNKNOWN; - switch(sysctl_out) { - case 1: - battery_state.state = BATTERY_DISCHARGING; - break; - case 2: - battery_state.state = BATTERY_CHARGING; - break; - default: - battery_state.state = BATTERY_FULL; - break; - } - } else { - fprintf(stderr, "power update: no such sysctl"); - errors = 1; - } - - // no mapping for freebsd - energy_full = 0; - energy_now = 0; - - if (sysctlbyname("hw.acpi.battery.time", &sysctl_out, &len, NULL, 0) != 0) - seconds = -1; - else - seconds = sysctl_out * 60; - - // charging or error - if (seconds < 0) - seconds = 0; - - if (sysctlbyname("hw.acpi.battery.life", &sysctl_out, &len, NULL, 0) != 0) - new_percentage = -1; - else - new_percentage = sysctl_out; -#else - update_linux_batteries(&battery_state.state, &new_percentage, &seconds); -#endif - - battery_state.time.hours = seconds / 3600; - seconds -= 3600 * battery_state.time.hours; - battery_state.time.minutes = seconds / 60; - seconds -= 60 * battery_state.time.minutes; - battery_state.time.seconds = seconds; - - battery_state.percentage = new_percentage; + err = battery_os_update(&battery_state); // clamp percentage to 100 in case battery is misreporting that its current charge is more than its max if (battery_state.percentage > 100) { battery_state.percentage = 100; } - return errors; + return err; } diff --git a/src/battery/battery.h b/src/battery/battery.h index f9441da..3148d38 100644 --- a/src/battery/battery.h +++ b/src/battery/battery.h @@ -76,6 +76,14 @@ static inline gchar* chargestate2str(enum chargestate state) { }; } +static inline void batstate_set_time(struct batstate *state, int seconds) { + state->time.hours = seconds / 3600; + seconds -= 3600 * state->time.hours; + state->time.minutes = seconds / 60; + seconds -= 60 * state->time.minutes; + state->time.seconds = seconds; +} + // default global data void default_battery(); @@ -93,11 +101,10 @@ int resize_battery(void *obj); void battery_action(int button); -#ifdef __linux -gboolean init_linux_batteries(); -void free_linux_batteries(); -void update_linux_batteries(enum chargestate *state, int8_t *percentage, int *seconds); -char* linux_batteries_get_tooltip(); -#endif +/* operating system specific functions */ +gboolean battery_os_init(); +void battery_os_free(); +int battery_os_update(struct batstate *state); +char* battery_os_tooltip(); #endif diff --git a/src/battery/dummy.c b/src/battery/dummy.c new file mode 100644 index 0000000..1639692 --- /dev/null +++ b/src/battery/dummy.c @@ -0,0 +1,40 @@ +/************************************************************************** +* +* Tint2 : Dummy battery (non-functional) +* +* Copyright (C) 2015 Sebastian Reichel +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License version 2 +* or any later version as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**************************************************************************/ + +#include +#include "common.h" +#include "battery.h" + +#warning tint2 has no battery support for this operating system! + +gboolean battery_os_init() { + return FALSE; +} + +void battery_os_free() { + return; +} + +int battery_os_update(struct batstate *state) { + return -1; +} + +char* battery_os_tooltip() { + return strdup("Operating System not supported"); +} diff --git a/src/battery/freebsd.c b/src/battery/freebsd.c new file mode 100644 index 0000000..0bdf665 --- /dev/null +++ b/src/battery/freebsd.c @@ -0,0 +1,79 @@ +/************************************************************************** +* +* Tint2 : FreeBSD battery +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License version 2 +* or any later version as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**************************************************************************/ + +#if defined(__FreeBSD__) + +#include +#include +#include + +#include "common.h" +#include "battery.h" + +gboolean battery_os_init() { + int sysctl_out = 0; + size_t len = sizeof(sysctl_out); + + return (sysctlbyname("hw.acpi.battery.state", &sysctl_out, &len, NULL, 0) == 0) || + (sysctlbyname("hw.acpi.battery.time", &sysctl_out, &len, NULL, 0) == 0) || + (sysctlbyname("hw.acpi.battery.life", &sysctl_out, &len, NULL, 0) == 0); +} + +void battery_os_free() { + return; +} + +int battery_os_update(struct batstate *state) { + int sysctl_out = 0; + size_t len = sizeof(sysctl_out); + gboolean err = 0; + + if (sysctlbyname("hw.acpi.battery.state", &sysctl_out, &len, NULL, 0) == 0) { + switch(sysctl_out) { + case 1: + state->state = BATTERY_DISCHARGING; + break; + case 2: + state->state = BATTERY_CHARGING; + break; + default: + state->state = BATTERY_FULL; + break; + } + } else { + fprintf(stderr, "power update: no such sysctl"); + err = -1; + } + + if (sysctlbyname("hw.acpi.battery.time", &sysctl_out, &len, NULL, 0) == 0) + batstate_set_time(state, sysctl_out * 60); + else + err = -1; + + if (sysctlbyname("hw.acpi.battery.life", &sysctl_out, &len, NULL, 0) == 0) + state->percentage = sysctl_out; + else + err = -1; + + return err; +} + +char* battery_os_tooltip() { + return strdup("Operating System not supported"); +} + +#endif diff --git a/src/battery/linux.c b/src/battery/linux.c index bae3d1a..7ce9deb 100644 --- a/src/battery/linux.c +++ b/src/battery/linux.c @@ -170,7 +170,7 @@ static gboolean init_linux_mains(struct psy_mains *ac) { return TRUE; } -void free_linux_batteries() { +void battery_os_free() { GList *l = batteries; while (l != NULL) { @@ -230,12 +230,12 @@ static void add_mains(const char *entryname) { } } -gboolean init_linux_batteries() { +gboolean battery_os_init() { GDir *directory = 0; GError *error = NULL; const char *entryname; - free_linux_batteries(); + battery_os_free(); directory = g_dir_open("/sys/class/power_supply", 0, &error); RETURN_ON_ERROR(error); @@ -332,12 +332,13 @@ static gboolean update_linux_mains(struct psy_mains *ac) { return TRUE; } -void update_linux_batteries(enum chargestate *state, int8_t *percentage, int *seconds) { +int battery_os_update(struct batstate *state) { GList *l; gint64 total_energy_now = 0; gint64 total_energy_full = 0; gint64 total_power_now = 0; + gint seconds = 0; gboolean charging = FALSE; gboolean discharging = FALSE; @@ -362,25 +363,26 @@ void update_linux_batteries(enum chargestate *state, int8_t *percentage, int *se } /* build global state */ - *state = BATTERY_UNKNOWN; if (charging && !discharging) - *state = BATTERY_CHARGING; + state->state = BATTERY_CHARGING; else if (!charging && discharging) - *state = BATTERY_DISCHARGING; + state->state = BATTERY_DISCHARGING; else if (!charging && !discharging && full) - *state = BATTERY_FULL; + state->state = BATTERY_FULL; /* calculate seconds */ - *seconds = 0; if (total_power_now > 0) { - if(*state == BATTERY_CHARGING) - *seconds = 3600 * (total_energy_full - total_energy_now) / total_power_now; - else if(*state == BATTERY_DISCHARGING) - *seconds = 3600 * total_energy_now / total_power_now; + if(state->state == BATTERY_CHARGING) + seconds = 3600 * (total_energy_full - total_energy_now) / total_power_now; + else if(state->state == BATTERY_DISCHARGING) + seconds = 3600 * total_energy_now / total_power_now; } + batstate_set_time(state, seconds); /* calculate percentage */ - *percentage = energy_to_percent(total_energy_now, total_energy_full); + state->percentage = energy_to_percent(total_energy_now, total_energy_full); + + return 0; } static gchar* energy_human_readable(struct psy_battery *bat) { @@ -418,7 +420,7 @@ static gchar* power_human_readable(struct psy_battery *bat) { } } -char* linux_batteries_get_tooltip() { +char* battery_os_tooltip() { GList *l; GString *tooltip = g_string_new(""); gchar *result; diff --git a/src/battery/openbsd.c b/src/battery/openbsd.c new file mode 100644 index 0000000..75d2381 --- /dev/null +++ b/src/battery/openbsd.c @@ -0,0 +1,84 @@ +/************************************************************************** +* +* Tint2 : OpenBSD & NetBSD battery +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License version 2 +* or any later version as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**************************************************************************/ + +#if defined(__OpenBSD__) || defined(__NetBSD__) + +//#include +#include +#include +#include +#include + +#include "common.h" +#include "battery.h" + +int apm_fd = -1; + +gboolean battery_os_init() { + if (apm_fd > 0) + close(apm_fd); + + apm_fd = open("/dev/apm", O_RDONLY); + + if (apm_fd < 0) { + warn("ERROR: battery applet cannot open /dev/apm."); + return FALSE; + } else { + return TRUE; + } +} + +void battery_os_free() { + if ((apm_fd != -1) && (close(apm_fd) == -1)) + warn("cannot close /dev/apm"); + apm_fd = -1; +} + +int battery_os_update(struct batstate *state) { + struct apm_power_info info; + + if (apm_fd > 0 && ioctl(apm_fd, APM_IOC_GETPOWER, &(info)) == 0) { + // best attempt at mapping to Linux battery states + switch (info.battery_state) { + case APM_BATT_CHARGING: + state->state = BATTERY_CHARGING; + break; + default: + state->state = BATTERY_DISCHARGING; + break; + } + + if (info.battery_life == 100) + state->state = BATTERY_FULL; + + if (info.minutes_left != -1) + batstate_set_time(state, info.minutes_left * 60); + + state->percentage = info.battery_life; + } else { + warn("power update: APM_IOC_GETPOWER"); + return -1; + } + + return 0; +} + +char* battery_os_tooltip() { + return strdup("Operating System not supported"); +} + +#endif