dockapps/wmbattery/simplehal.c
Doug Torrance 0fa341ec37 wmbattery: Remove unnecessary brace.
Fixes "Invalid number of character ({) when these macros are defined"
errors given by cppcheck.
2015-05-14 11:44:03 +01:00

218 lines
5.4 KiB
C

/* Not particularly good interface to hal, for programs that used to use
* apm.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libhal.h>
#include "apm.h"
static DBusConnection *dbus_ctx;
static LibHalContext *hal_ctx;
int num_ac_adapters = 0;
int num_batteries = 0;
char **ac_adapters = NULL;
char **batteries = NULL;
int connect_hal(void)
{
DBusError error;
dbus_error_init(&error);
dbus_ctx = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
if (dbus_ctx == NULL) {
fprintf(stderr, "error: dbus_bus_get: %s: %s\n",
error.name, error.message);
LIBHAL_FREE_DBUS_ERROR(&error);
return 0;
}
hal_ctx = libhal_ctx_new();
if (hal_ctx == NULL) {
fprintf(stderr, "error: libhal_ctx_new\n");
LIBHAL_FREE_DBUS_ERROR(&error);
return 0;
}
if (!libhal_ctx_set_dbus_connection(hal_ctx, dbus_ctx)) {
fprintf(stderr, "error: libhal_ctx_set_dbus_connection: %s: %s\n",
error.name, error.message);
LIBHAL_FREE_DBUS_ERROR(&error);
return 0;
}
if (!libhal_ctx_init(hal_ctx, &error)) {
if (dbus_error_is_set(&error)) {
fprintf(stderr, "error: libhal_ctx_init: %s: %s\n", error.name, error.message);
LIBHAL_FREE_DBUS_ERROR(&error);
}
fprintf(stderr, "Could not initialise connection to hald.\n"
"Normally this means the HAL daemon (hald) is not running or not ready.\n");
return 0;
}
return 1;
}
int hal_ready(void)
{
if (hal_ctx && dbus_connection_get_is_connected(dbus_ctx)) {
return 1;
} else {
/* The messy business of reconnecting.
* dbus's design is crap when it comes to reconnecting.
* If dbus is down, can't actually close the connection to hal,
* since libhal wants to use dbus to do it. */
if (dbus_ctx) {
dbus_connection_close(dbus_ctx);
dbus_connection_unref(dbus_ctx);
}
dbus_ctx = NULL;
hal_ctx = NULL;
return connect_hal();
}
}
signed int get_hal_int(const char *udi, const char *key, int optional)
{
int ret;
DBusError error;
if (!hal_ready())
return -1;
dbus_error_init(&error);
ret = libhal_device_get_property_int (hal_ctx, udi, key, &error);
if (!dbus_error_is_set(&error)) {
return ret;
} else {
if (!optional) {
fprintf(stderr, "error: libhal_device_get_property_int: %s: %s\n",
error.name, error.message);
}
dbus_error_free(&error);
return -1;
}
}
signed int get_hal_bool(const char *udi, const char *key, int optional)
{
int ret;
DBusError error;
if (!hal_ready())
return -1;
dbus_error_init(&error);
ret = libhal_device_get_property_bool(hal_ctx, udi, key, &error);
if (!dbus_error_is_set(&error)) {
return ret;
} else {
if (!optional) {
fprintf(stderr, "error: libhal_device_get_property_bool: %s: %s\n",
error.name, error.message);
}
dbus_error_free(&error);
return -1;
}
}
void find_devices(void)
{
DBusError error;
dbus_error_init(&error);
if (ac_adapters)
libhal_free_string_array(ac_adapters);
ac_adapters = libhal_find_device_by_capability(hal_ctx, "ac_adapter",
&num_ac_adapters, &error);
if (dbus_error_is_set(&error)) {
fprintf(stderr, "error: %s: %s\n", error.name, error.message);
LIBHAL_FREE_DBUS_ERROR(&error);
}
if (batteries)
libhal_free_string_array(batteries);
batteries = libhal_find_device_by_capability(hal_ctx, "battery",
&num_batteries, &error);
if (dbus_error_is_set(&error)) {
fprintf(stderr, "error: %s: %s\n", error.name, error.message);
LIBHAL_FREE_DBUS_ERROR(&error);
}
}
int simplehal_supported(void)
{
if (!connect_hal()) {
return 0;
} else {
find_devices();
return 1;
}
}
/* Fill the passed apm_info struct. */
int simplehal_read(int battery, apm_info *info)
{
char *device;
int i;
/* Allow a battery that was not present before to appear. */
if (battery > num_batteries)
find_devices();
info->battery_flags = 0;
info->using_minutes = 0;
info->ac_line_status = 0;
for (i = 0 ; i < num_ac_adapters && !info->ac_line_status ; i++)
info->ac_line_status = (get_hal_bool(ac_adapters[i], "ac_adapter.present", 0) == 1);
if (battery > num_batteries) {
info->battery_percentage = 0;
info->battery_time = 0;
info->battery_status = BATTERY_STATUS_ABSENT;
return 0;
} else {
device = batteries[battery-1];
}
if (get_hal_bool(device, "battery.present", 0) != 1) {
info->battery_percentage = 0;
info->battery_time = 0;
info->battery_status = BATTERY_STATUS_ABSENT;
return 0;
}
/* remaining_time and charge_level.percentage are not a mandatory
* keys, so if not present, -1 will be returned */
info->battery_time = get_hal_int(device, "battery.remaining_time", 1);
info->battery_percentage = get_hal_int(device, "battery.charge_level.percentage", 1);
if (get_hal_bool(device, "battery.rechargeable.is_discharging", 0) == 1) {
info->battery_status = BATTERY_STATUS_CHARGING;
/* charge_level.warning and charge_level.low are not
* required to be available; this is good enough */
if (info->battery_percentage < 1)
info->battery_status = BATTERY_STATUS_CRITICAL;
else if (info->battery_percentage < 10)
info->battery_status = BATTERY_STATUS_LOW;
} else if (info->ac_line_status &&
get_hal_bool(device, "battery.rechargeable.is_charging", 0) == 1) {
info->battery_status = BATTERY_STATUS_CHARGING;
info->battery_flags = info->battery_flags | BATTERY_FLAGS_CHARGING;
} else if (info->ac_line_status) {
/* Must be fully charged. */
info->battery_status = BATTERY_STATUS_HIGH;
} else {
fprintf(stderr, "unknown battery state\n");
}
return 0;
}