wmbattery: Add to repository.
[dockapps.git] / wmbattery / simplehal.c
blobf6379cd28eabdabf8a51d654fd0131869e02fd67
1 /* Not particularly good interface to hal, for programs that used to use
2 * apm.
3 */
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <unistd.h>
9 #include <libhal.h>
10 #include "apm.h"
12 static DBusConnection *dbus_ctx = NULL;
13 static LibHalContext *hal_ctx = NULL;
15 int num_ac_adapters = 0;
16 int num_batteries = 0;
17 char **ac_adapters = NULL;
18 char **batteries = NULL;
20 int connect_hal (void) {
21 DBusError error;
23 dbus_error_init(&error);
24 dbus_ctx = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
25 if (dbus_ctx == NULL) {
26 fprintf(stderr, "error: dbus_bus_get: %s: %s\n",
27 error.name, error.message);
28 LIBHAL_FREE_DBUS_ERROR(&error);
29 return 0;
31 if ((hal_ctx = libhal_ctx_new()) == NULL) {
32 fprintf(stderr, "error: libhal_ctx_new\n");
33 LIBHAL_FREE_DBUS_ERROR(&error);
34 return 0;
36 if (!libhal_ctx_set_dbus_connection(hal_ctx, dbus_ctx)) {
37 fprintf(stderr, "error: libhal_ctx_set_dbus_connection: %s: %s\n",
38 error.name, error.message);
39 LIBHAL_FREE_DBUS_ERROR(&error);
40 return 0;
42 if (!libhal_ctx_init(hal_ctx, &error)) {
43 if (dbus_error_is_set(&error)) {
44 fprintf(stderr, "error: libhal_ctx_init: %s: %s\n", error.name, error.message);
45 LIBHAL_FREE_DBUS_ERROR(&error);
47 fprintf(stderr, "Could not initialise connection to hald.\n"
48 "Normally this means the HAL daemon (hald) is not running or not ready.\n");
49 return 0;
52 return 1;
55 int hal_ready (void) {
56 if (hal_ctx && dbus_connection_get_is_connected(dbus_ctx)) {
57 return 1;
59 else {
60 /* The messy business of reconnecting.
61 * dbus's design is crap when it comes to reconnecting.
62 * If dbus is down, can't actually close the connection to hal,
63 * since libhal wants to use dbus to do it. */
64 if (dbus_ctx) {
65 dbus_connection_close(dbus_ctx);
66 dbus_connection_unref(dbus_ctx);
68 dbus_ctx = NULL;
69 hal_ctx = NULL;
71 return connect_hal();
75 signed int get_hal_int (const char *udi, const char *key, int optional) {
76 int ret;
77 DBusError error;
79 if (! hal_ready()) {
80 return -1;
83 dbus_error_init(&error);
85 ret = libhal_device_get_property_int (hal_ctx, udi, key, &error);
87 if (! dbus_error_is_set (&error)) {
88 return ret;
90 else {
91 if (! optional) {
92 fprintf(stderr, "error: libhal_device_get_property_int: %s: %s\n",
93 error.name, error.message);
95 dbus_error_free (&error);
96 return -1;
100 signed int get_hal_bool (const char *udi, const char *key, int optional) {
101 int ret;
102 DBusError error;
104 if (! hal_ready()) {
105 return -1;
108 dbus_error_init(&error);
110 ret = libhal_device_get_property_bool (hal_ctx, udi, key, &error);
112 if (! dbus_error_is_set (&error)) {
113 return ret;
115 else {
116 if (! optional) {
117 fprintf(stderr, "error: libhal_device_get_property_bool: %s: %s\n",
118 error.name, error.message);
120 dbus_error_free (&error);
121 return -1;
125 void find_devices (void) {
126 DBusError error;
128 dbus_error_init(&error);
130 if (ac_adapters)
131 libhal_free_string_array(ac_adapters);
132 ac_adapters = libhal_find_device_by_capability(hal_ctx, "ac_adapter",
133 &num_ac_adapters, &error);
134 if (dbus_error_is_set (&error)) {
135 fprintf (stderr, "error: %s: %s\n", error.name, error.message);
136 LIBHAL_FREE_DBUS_ERROR (&error);
139 if (batteries)
140 libhal_free_string_array(batteries);
141 batteries = libhal_find_device_by_capability(hal_ctx, "battery",
142 &num_batteries, &error);
143 if (dbus_error_is_set (&error)) {
144 fprintf (stderr, "error: %s: %s\n", error.name, error.message);
145 LIBHAL_FREE_DBUS_ERROR (&error);
149 int simplehal_supported (void) {
150 if (! connect_hal()) {
151 return 0;
153 else {
154 find_devices();
155 return 1;
159 /* Fill the passed apm_info struct. */
160 int simplehal_read (int battery, apm_info *info) {
161 char *device;
162 int i;
164 /* Allow a battery that was not present before to appear. */
165 if (battery > num_batteries) {
166 find_devices();
169 info->battery_flags = 0;
170 info->using_minutes = 0;
172 info->ac_line_status=0;
173 for (i = 0 ; i < num_ac_adapters && ! info->ac_line_status ; i++) {
174 info->ac_line_status = (get_hal_bool(ac_adapters[i], "ac_adapter.present", 0) == 1);
177 if (battery > num_batteries) {
178 info->battery_percentage = 0;
179 info->battery_time = 0;
180 info->battery_status = BATTERY_STATUS_ABSENT;
181 return 0;
183 else {
184 device=batteries[battery-1];
187 if (get_hal_bool(device, "battery.present", 0) != 1) {
188 info->battery_percentage = 0;
189 info->battery_time = 0;
190 info->battery_status = BATTERY_STATUS_ABSENT;
191 return 0;
194 /* remaining_time and charge_level.percentage are not a mandatory
195 * keys, so if not present, -1 will be returned */
196 info->battery_time = get_hal_int(device, "battery.remaining_time", 1);
197 info->battery_percentage = get_hal_int(device, "battery.charge_level.percentage", 1);
198 if (get_hal_bool(device, "battery.rechargeable.is_discharging", 0) == 1) {
199 info->battery_status = BATTERY_STATUS_CHARGING;
200 /* charge_level.warning and charge_level.low are not
201 * required to be available; this is good enough */
202 if (info->battery_percentage < 1) {
203 info->battery_status = BATTERY_STATUS_CRITICAL;
205 else if (info->battery_percentage < 10) {
206 info->battery_status = BATTERY_STATUS_LOW;
209 else if (info->ac_line_status &&
210 get_hal_bool(device, "battery.rechargeable.is_charging", 0) == 1) {
211 info->battery_status = BATTERY_STATUS_CHARGING;
212 info->battery_flags = info->battery_flags | BATTERY_FLAGS_CHARGING;
214 else if (info->ac_line_status) {
215 /* Must be fully charged. */
216 info->battery_status = BATTERY_STATUS_HIGH;
218 else {
219 fprintf(stderr, "unknown battery state\n");
222 return 0;