summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Hughes <richard@hughsie.com>2008-08-09 14:27:32 +0100
committerRichard Hughes <richard@hughsie.com>2008-08-09 14:27:32 +0100
commit918c35586bf257d316b0dfc6c0822a9c9c142f17 (patch)
tree9bc33b487f1024c3995168baf746f84295087ac1
parent6a498f04873034cc856c02870e7ed0f18fe2094d (diff)
refactor out DkpDevice and DkpSupply so we can add another type of device without a metric ton of copy and paste
-rw-r--r--doc/Makefile.am2
-rw-r--r--doc/dbus/Makefile.am4
-rw-r--r--doc/devkit-power-docs.xml2
-rw-r--r--src/Makefile.am12
-rw-r--r--src/dkp-daemon.c75
-rw-r--r--src/dkp-daemon.h12
-rw-r--r--src/dkp-device.c576
-rw-r--r--src/dkp-device.h55
-rw-r--r--src/dkp-source.c991
-rw-r--r--src/dkp-source.h79
-rw-r--r--src/dkp-supply.c520
-rw-r--r--src/dkp-supply.h56
-rw-r--r--src/org.freedesktop.DeviceKit.Power.Device.xml (renamed from src/org.freedesktop.DeviceKit.Power.Source.xml)4
-rw-r--r--tools/.gitignore1
-rw-r--r--tools/Makefile.am8
-rw-r--r--tools/dkp-client-device.c2
16 files changed, 1242 insertions, 1157 deletions
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 9953167..5d5a83f 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -53,7 +53,7 @@ content_files = \
man/devkit-power-daemon.xml \
man/DeviceKit-power.xml \
dbus/org.freedesktop.DeviceKit.Power.ref.xml \
- dbus/org.freedesktop.DeviceKit.Power.Source.ref.xml \
+ dbus/org.freedesktop.DeviceKit.Power.Device.ref.xml \
$(NULL)
# Images to copy into HTML directory
diff --git a/doc/dbus/Makefile.am b/doc/dbus/Makefile.am
index d2685f4..c8511ac 100644
--- a/doc/dbus/Makefile.am
+++ b/doc/dbus/Makefile.am
@@ -1,11 +1,11 @@
-all : org.freedesktop.DeviceKit.Power.ref.xml org.freedesktop.DeviceKit.Power.Source.ref.xml
+all : org.freedesktop.DeviceKit.Power.ref.xml org.freedesktop.DeviceKit.Power.Device.ref.xml
org.freedesktop.DeviceKit.Power.ref.xml : $(top_srcdir)/src/org.freedesktop.DeviceKit.Power.xml $(top_srcdir)/doc/dbus/spec-to-docbook.xsl
echo "<?xml version=\"1.0\"?>""<!DOCTYPE refentry PUBLIC \"-//OASIS//DTD DocBook XML V4.1.2//EN\" \"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd\">" > $@
$(XSLTPROC) $(top_srcdir)/doc/dbus/spec-to-docbook.xsl $< | tail -n +2 >> $@
-org.freedesktop.DeviceKit.Power.Source.ref.xml : $(top_srcdir)/src/org.freedesktop.DeviceKit.Power.Source.xml $(top_srcdir)/doc/dbus/spec-to-docbook.xsl
+org.freedesktop.DeviceKit.Power.Device.ref.xml : $(top_srcdir)/src/org.freedesktop.DeviceKit.Power.Device.xml $(top_srcdir)/doc/dbus/spec-to-docbook.xsl
echo "<?xml version=\"1.0\"?>""<!DOCTYPE refentry PUBLIC \"-//OASIS//DTD DocBook XML V4.1.2//EN\" \"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd\">" > $@
$(XSLTPROC) $(top_srcdir)/doc/dbus/spec-to-docbook.xsl $< | tail -n +2 >> $@
diff --git a/doc/devkit-power-docs.xml b/doc/devkit-power-docs.xml
index 6af1211..5c6e957 100644
--- a/doc/devkit-power-docs.xml
+++ b/doc/devkit-power-docs.xml
@@ -64,7 +64,7 @@
</para>
</partintro>
<xi:include href="dbus/org.freedesktop.DeviceKit.Power.ref.xml"/>
- <xi:include href="dbus/org.freedesktop.DeviceKit.Power.Source.ref.xml"/>
+ <xi:include href="dbus/org.freedesktop.DeviceKit.Power.Device.ref.xml"/>
</reference>
<reference id="tools-fileformats">
diff --git a/src/Makefile.am b/src/Makefile.am
index 073bb12..28a9cba 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -21,7 +21,7 @@ DEVKIT_POWER_LIBS = $(top_builddir)/libdevkit-power/libdevkit-power.la
BUILT_SOURCES = \
dkp-daemon-glue.h \
- dkp-source-glue.h \
+ dkp-device-glue.h \
dkp-marshal.h dkp-marshal.c
dkp-marshal.h: dkp-marshal.list
@@ -33,19 +33,19 @@ dkp-marshal.c: dkp-marshal.list
dkp-daemon-glue.h: org.freedesktop.DeviceKit.Power.xml Makefile.am
dbus-binding-tool --prefix=dkp_daemon --mode=glib-server --output=dkp-daemon-glue.h org.freedesktop.DeviceKit.Power.xml
-dkp-source-glue.h: org.freedesktop.DeviceKit.Power.Source.xml Makefile.am
- dbus-binding-tool --prefix=dkp_source --mode=glib-server --output=dkp-source-glue.h org.freedesktop.DeviceKit.Power.Source.xml
+dkp-device-glue.h: org.freedesktop.DeviceKit.Power.Device.xml Makefile.am
+ dbus-binding-tool --prefix=dkp_device --mode=glib-server --output=dkp-device-glue.h org.freedesktop.DeviceKit.Power.Device.xml
libexec_PROGRAMS = devkit-power-daemon
dbusifdir = $(datadir)/dbus-1/interfaces
-dbusif_DATA = org.freedesktop.DeviceKit.Power.xml org.freedesktop.DeviceKit.Power.Source.xml
+dbusif_DATA = org.freedesktop.DeviceKit.Power.xml org.freedesktop.DeviceKit.Power.Device.xml
devkit_power_daemon_SOURCES = \
dkp-daemon.h dkp-daemon.c \
dkp-device.h dkp-device.c \
dkp-device-list.h dkp-device-list.c \
- dkp-source.h dkp-source.c \
+ dkp-supply.h dkp-supply.c \
dkp-history.h dkp-history.c \
sysfs-utils.h sysfs-utils.c \
main.c \
@@ -85,7 +85,7 @@ CLEANFILES = $(BUILT_SOURCES)
EXTRA_DIST = \
org.freedesktop.DeviceKit.Power.xml \
- org.freedesktop.DeviceKit.Power.Source.xml \
+ org.freedesktop.DeviceKit.Power.Device.xml \
dkp-marshal.list \
95-devkit-power.rules \
$(service_in_files) \
diff --git a/src/dkp-daemon.c b/src/dkp-daemon.c
index 1e551c8..114b3ac 100644
--- a/src/dkp-daemon.c
+++ b/src/dkp-daemon.c
@@ -34,7 +34,7 @@
#include "dkp-debug.h"
#include "dkp-daemon.h"
#include "dkp-device.h"
-#include "dkp-source.h"
+#include "dkp-supply.h"
#include "dkp-device-list.h"
#include "dkp-daemon-glue.h"
@@ -76,7 +76,7 @@ static gboolean dkp_daemon_get_low_battery_local (DkpDaemon *daemon);
G_DEFINE_TYPE (DkpDaemon, dkp_daemon, G_TYPE_OBJECT)
-#define DKP_DAEMON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DKP_SOURCE_TYPE_DAEMON, DkpDaemonPrivate))
+#define DKP_DAEMON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DKP_TYPE_DAEMON, DkpDaemonPrivate))
/**
* dkp_daemon_error_quark:
@@ -85,16 +85,12 @@ GQuark
dkp_daemon_error_quark (void)
{
static GQuark ret = 0;
-
- if (ret == 0) {
+ if (ret == 0)
ret = g_quark_from_static_string ("dkp_daemon_error");
- }
-
return ret;
}
#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
-
/**
* dkp_daemon_error_get_type:
**/
@@ -127,7 +123,7 @@ dkp_daemon_constructor (GType type, guint n_construct_properties, GObjectConstru
DkpDaemon *daemon;
DkpDaemonClass *klass;
- klass = DKP_DAEMON_CLASS (g_type_class_peek (DKP_SOURCE_TYPE_DAEMON));
+ klass = DKP_DAEMON_CLASS (g_type_class_peek (DKP_TYPE_DAEMON));
daemon = DKP_DAEMON (G_OBJECT_CLASS (dkp_daemon_parent_class)->constructor (type, n_construct_properties, construct_properties));
return G_OBJECT (daemon);
}
@@ -190,7 +186,7 @@ dkp_daemon_class_init (DkpDaemonClass *klass)
g_cclosure_marshal_VOID__BOOLEAN,
G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
- dbus_g_object_type_install_info (DKP_SOURCE_TYPE_DAEMON, &dbus_glib_dkp_daemon_object_info);
+ dbus_g_object_type_install_info (DKP_TYPE_DAEMON, &dbus_glib_dkp_daemon_object_info);
dbus_g_error_domain_register (DKP_DAEMON_ERROR, NULL, DKP_DAEMON_TYPE_ERROR);
}
@@ -308,7 +304,7 @@ gpk_daemon_dbus_filter (DBusConnection *connection, DBusMessage *message, void *
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
-static void gpk_daemon_device_add (DkpDaemon *daemon, DevkitDevice *d, gboolean emit_event);
+static gboolean gpk_daemon_device_add (DkpDaemon *daemon, DevkitDevice *d, gboolean emit_event);
static void gpk_daemon_device_remove (DkpDaemon *daemon, DevkitDevice *d);
/**
@@ -416,13 +412,45 @@ gpk_daemon_device_went_away (gpointer user_data, GObject *_device)
dkp_device_list_remove (daemon->priv->list, device);
}
+#include "dkp-supply.h"
+
+/**
+ * gpk_daemon_device_get:
+ **/
+static DkpDevice *
+gpk_daemon_device_get (DevkitDevice *d)
+{
+ const gchar *type;
+ const gchar *subsys;
+ const gchar *native_path;
+ DkpDevice *device = NULL;
+
+ subsys = devkit_device_get_subsystem (d);
+ if (strcmp (subsys, "power_supply") == 0) {
+ /* always add */
+ device = DKP_DEVICE (dkp_supply_new ());
+ } else if (strcmp (subsys, "usb") == 0) {
+ /* see if this is a CSR mouse or keyboard */
+ type = devkit_device_get_property (d, "ID_BATTERY_TYPE");
+ if (type != NULL)
+ //device = DKP_DEVICE (dkp_csr_new ());
+ dkp_warning ("should add %s !!", devkit_device_get_native_path (d));
+ } else {
+ native_path = devkit_device_get_native_path (d);
+ dkp_warning ("native path %s (%s) ignoring", native_path, subsys);
+ }
+
+ return device;
+}
+
/**
* gpk_daemon_device_add:
**/
-static void
+static gboolean
gpk_daemon_device_add (DkpDaemon *daemon, DevkitDevice *d, gboolean emit_event)
{
DkpDevice *device;
+ gboolean ret = FALSE;
/* does device exist in db? */
device = dkp_device_list_lookup (daemon->priv->list, d);
@@ -431,12 +459,21 @@ gpk_daemon_device_add (DkpDaemon *daemon, DevkitDevice *d, gboolean emit_event)
dkp_debug ("treating add event as change event on %s", dkp_device_get_object_path (device));
gpk_daemon_device_changed (daemon, d, FALSE);
} else {
- device = dkp_device_new (daemon, d);
- if (device != NULL) {
+ /* get the right sort of device */
+ device = gpk_daemon_device_get (d);
+ if (device == NULL) {
+ dkp_debug ("ignoring add event on %s", devkit_device_get_native_path (d));
+ goto out;
+ }
+
+ /* coldplug */
+ ret = dkp_device_coldplug (device, daemon, d);
+
+ /* only if coldplug succeeded */
+ if (ret) {
/* only take a weak ref; the device will stay on the bus until
- * it's unreffed. So if we ref it, it'll never go away. Stupid
- * dbus-glib, no cookie for you.
+ * it's unreffed. So if we ref it, it'll never go away.
*/
g_object_weak_ref (G_OBJECT (device), gpk_daemon_device_went_away, daemon);
dkp_device_list_insert (daemon->priv->list, d, device);
@@ -445,9 +482,12 @@ gpk_daemon_device_add (DkpDaemon *daemon, DevkitDevice *d, gboolean emit_event)
dkp_device_get_object_path (device));
}
} else {
- dkp_debug ("ignoring add event on %s", devkit_device_get_native_path (d));
+ g_object_unref (device);
+ dkp_debug ("coldplugging failed: %s", devkit_device_get_native_path (d));
}
}
+out:
+ return ret;
}
/**
@@ -599,7 +639,7 @@ dkp_daemon_new (void)
GList *devices;
GList *l;
- daemon = DKP_DAEMON (g_object_new (DKP_SOURCE_TYPE_DAEMON, NULL));
+ daemon = DKP_DAEMON (g_object_new (DKP_TYPE_DAEMON, NULL));
daemon->priv->list = dkp_device_list_new ();
if (!gpk_daemon_register_power_daemon (DKP_DAEMON (daemon))) {
@@ -844,3 +884,4 @@ out:
polkit_caller_unref (pk_caller);
return TRUE;
}
+
diff --git a/src/dkp-daemon.h b/src/dkp-daemon.h
index 36afdf9..d779086 100644
--- a/src/dkp-daemon.h
+++ b/src/dkp-daemon.h
@@ -27,12 +27,12 @@
G_BEGIN_DECLS
-#define DKP_SOURCE_TYPE_DAEMON (dkp_daemon_get_type ())
-#define DKP_DAEMON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DKP_SOURCE_TYPE_DAEMON, DkpDaemon))
-#define DKP_DAEMON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), DKP_SOURCE_TYPE_DAEMON, DkpDaemonClass))
-#define DKP_IS_DAEMON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), DKP_SOURCE_TYPE_DAEMON))
-#define DKP_IS_DAEMON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DKP_SOURCE_TYPE_DAEMON))
-#define DKP_DAEMON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DKP_SOURCE_TYPE_DAEMON, DkpDaemonClass))
+#define DKP_TYPE_DAEMON (dkp_daemon_get_type ())
+#define DKP_DAEMON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DKP_TYPE_DAEMON, DkpDaemon))
+#define DKP_DAEMON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), DKP_TYPE_DAEMON, DkpDaemonClass))
+#define DKP_IS_DAEMON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), DKP_TYPE_DAEMON))
+#define DKP_IS_DAEMON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DKP_TYPE_DAEMON))
+#define DKP_DAEMON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DKP_TYPE_DAEMON, DkpDaemonClass))
typedef struct DkpDaemonPrivate DkpDaemonPrivate;
diff --git a/src/dkp-device.c b/src/dkp-device.c
index b706e5b..a76829e 100644
--- a/src/dkp-device.c
+++ b/src/dkp-device.c
@@ -1,6 +1,7 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 David Zeuthen <david@fubar.dk>
+ * Copyright (C) 2008 Richard Hughes <richard@hughsie.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -35,30 +36,184 @@
#include "sysfs-utils.h"
#include "dkp-debug.h"
+#include "dkp-supply.h"
#include "dkp-device.h"
-#include "dkp-source.h"
+#include "dkp-device.h"
+#include "dkp-history-obj.h"
+#include "dkp-marshal.h"
+#include "dkp-device-glue.h"
+
+struct DkpDevicePrivate
+{
+ gchar *object_path;
+ DBusGConnection *system_bus_connection;
+ DBusGProxy *system_bus_proxy;
+ DkpDaemon *daemon;
+ DevkitDevice *d;
+ DkpObject *obj;
+ gboolean has_ever_refresh;
+};
+
+static void dkp_device_class_init (DkpDeviceClass *klass);
+static void dkp_device_init (DkpDevice *device);
+static gboolean dkp_device_register_device (DkpDevice *device);
+static gboolean dkp_device_refresh_internal (DkpDevice *device);
+
+enum
+{
+ PROP_0,
+ PROP_NATIVE_PATH,
+ PROP_VENDOR,
+ PROP_MODEL,
+ PROP_SERIAL,
+ PROP_UPDATE_TIME,
+ PROP_TYPE,
+ PROP_LINE_POWER_ONLINE,
+ PROP_POWER_SUPPLY,
+ PROP_BATTERY_CAPACITY,
+ PROP_BATTERY_IS_PRESENT,
+ PROP_BATTERY_IS_RECHARGEABLE,
+ PROP_BATTERY_STATE,
+ PROP_BATTERY_ENERGY,
+ PROP_BATTERY_ENERGY_EMPTY,
+ PROP_BATTERY_ENERGY_FULL,
+ PROP_BATTERY_ENERGY_FULL_DESIGN,
+ PROP_BATTERY_ENERGY_RATE,
+ PROP_BATTERY_TIME_TO_EMPTY,
+ PROP_BATTERY_TIME_TO_FULL,
+ PROP_BATTERY_PERCENTAGE,
+ PROP_BATTERY_TECHNOLOGY,
+};
+
+enum
+{
+ CHANGED_SIGNAL,
+ LAST_SIGNAL,
+};
-static void dkp_device_class_init (DkpDeviceClass *klass);
-static void dkp_device_init (DkpDevice *seat);
+static guint signals[LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE (DkpDevice, dkp_device, G_TYPE_OBJECT)
+#define DKP_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DKP_TYPE_DEVICE, DkpDevicePrivate))
+#define DKP_DBUS_STRUCT_UINT_DOUBLE_STRING (dbus_g_type_get_struct ("GValueArray", \
+ G_TYPE_UINT, G_TYPE_DOUBLE, G_TYPE_STRING, G_TYPE_INVALID))
+
+/**
+ * dkp_device_error_quark:
+ **/
+GQuark
+dkp_device_error_quark (void)
+{
+ static GQuark ret = 0;
+
+ if (ret == 0) {
+ ret = g_quark_from_static_string ("dkp_device_error");
+ }
+
+ return ret;
+}
-#define DKP_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DKP_SOURCE_TYPE_DEVICE, DkpDevicePrivate))
+#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
/**
- * dkp_device_class_init:
+ * dkp_device_error_get_type:
**/
-static void
-dkp_device_class_init (DkpDeviceClass *klass)
+GType
+dkp_device_error_get_type (void)
{
+ static GType etype = 0;
+
+ if (etype == 0)
+ {
+ static const GEnumValue values[] =
+ {
+ ENUM_ENTRY (DKP_DEVICE_ERROR_GENERAL, "GeneralError"),
+ { 0, 0, 0 }
+ };
+ g_assert (DKP_DEVICE_NUM_ERRORS == G_N_ELEMENTS (values) - 1);
+ etype = g_enum_register_static ("DkpDeviceError", values);
+ }
+ return etype;
}
/**
- * dkp_device_init:
+ * dkp_device_get_property:
**/
static void
-dkp_device_init (DkpDevice *device)
+dkp_device_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
+ DkpDevice *device = DKP_DEVICE (object);
+ DkpObject *obj = device->priv->obj;
+
+ switch (prop_id) {
+ case PROP_NATIVE_PATH:
+ g_value_set_string (value, obj->native_path);
+ break;
+ case PROP_VENDOR:
+ g_value_set_string (value, obj->vendor);
+ break;
+ case PROP_MODEL:
+ g_value_set_string (value, obj->model);
+ break;
+ case PROP_SERIAL:
+ g_value_set_string (value, obj->serial);
+ break;
+ case PROP_UPDATE_TIME:
+ g_value_set_uint64 (value, obj->update_time);
+ break;
+ case PROP_TYPE:
+ g_value_set_string (value, dkp_source_type_to_text (obj->type));
+ break;
+ case PROP_POWER_SUPPLY:
+ g_value_set_boolean (value, obj->power_supply);
+ break;
+ case PROP_LINE_POWER_ONLINE:
+ g_value_set_boolean (value, obj->line_power_online);
+ break;
+ case PROP_BATTERY_IS_PRESENT:
+ g_value_set_boolean (value, obj->battery_is_present);
+ break;
+ case PROP_BATTERY_IS_RECHARGEABLE:
+ g_value_set_boolean (value, obj->battery_is_rechargeable);
+ break;
+ case PROP_BATTERY_STATE:
+ g_value_set_string (value, dkp_source_state_to_text (obj->battery_state));
+ break;
+ case PROP_BATTERY_CAPACITY:
+ g_value_set_double (value, obj->battery_capacity);
+ break;
+ case PROP_BATTERY_ENERGY:
+ g_value_set_double (value, obj->battery_energy);
+ break;
+ case PROP_BATTERY_ENERGY_EMPTY:
+ g_value_set_double (value, obj->battery_energy_empty);
+ break;
+ case PROP_BATTERY_ENERGY_FULL:
+ g_value_set_double (value, obj->battery_energy_full);
+ break;
+ case PROP_BATTERY_ENERGY_FULL_DESIGN:
+ g_value_set_double (value, obj->battery_energy_full_design);
+ break;
+ case PROP_BATTERY_ENERGY_RATE:
+ g_value_set_double (value, obj->battery_energy_rate);
+ break;
+ case PROP_BATTERY_TIME_TO_EMPTY:
+ g_value_set_int64 (value, obj->battery_time_to_empty);
+ break;
+ case PROP_BATTERY_TIME_TO_FULL:
+ g_value_set_int64 (value, obj->battery_time_to_full);
+ break;
+ case PROP_BATTERY_PERCENTAGE:
+ g_value_set_double (value, obj->battery_percentage);
+ break;
+ case PROP_BATTERY_TECHNOLOGY:
+ g_value_set_string (value, dkp_source_technology_to_text (obj->battery_technology));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
}
/**
@@ -67,36 +222,172 @@ dkp_device_init (DkpDevice *device)
void
dkp_device_removed (DkpDevice *device)
{
+ //DkpDeviceClass *klass = DKP_DEVICE_GET_CLASS (device);
+ //klass->removed (device);
+ dkp_warning ("do something here?");
+}
+
+/**
+ * dkp_device_get_on_battery:
+ **/
+gboolean
+dkp_device_get_on_battery (DkpDevice *device, gboolean *on_battery)
+{
DkpDeviceClass *klass = DKP_DEVICE_GET_CLASS (device);
- klass->removed (device);
+ return klass->get_on_battery (device, on_battery);
}
/**
- * dkp_device_new:
+ * dkp_device_get_low_battery:
**/
-DkpDevice *
-dkp_device_new (DkpDaemon *daemon, DevkitDevice *d)
+gboolean
+dkp_device_get_low_battery (DkpDevice *device, gboolean *low_battery)
{
- const gchar *subsys;
- DkpDevice *device;
+ DkpDeviceClass *klass = DKP_DEVICE_GET_CLASS (device);
+ return klass->get_low_battery (device, low_battery);
+}
+
+/**
+ * dkp_device_coldplug:
+ **/
+gboolean
+dkp_device_coldplug (DkpDevice *device, DkpDaemon *daemon, DevkitDevice *d)
+{
+ gboolean ret;
+ const gchar *native_path;
+ DkpDeviceClass *klass = DKP_DEVICE_GET_CLASS (device);
+
+ /* save */
+ device->priv->d = g_object_ref (d);
+ device->priv->daemon = g_object_ref (daemon);
+
+ native_path = devkit_device_get_native_path (d);
+ device->priv->obj->native_path = g_strdup (native_path);
+
+ /* coldplug source */
+ dkp_debug ("coldplug %s", native_path);
+ ret = klass->coldplug (device);
+ /* only put on the bus if we succeeded */
+ if (ret)
+ dkp_device_register_device (device);
+
+ /* force a refresh */
+ dkp_device_refresh_internal (device);
+
+ return ret;
+}
+
+/**
+ * dkp_device_get_statistics:
+ **/
+gboolean
+dkp_device_get_statistics (DkpDevice *device, const gchar *type, guint timespan, DBusGMethodInvocation *context)
+{
+ DkpDeviceClass *klass = DKP_DEVICE_GET_CLASS (device);
+ GError *error;
+ GPtrArray *array;
+ GPtrArray *complex;
+ const DkpHistoryObj *obj;
+ GValue *value;
+ guint i;
- device = NULL;
+ array = klass->get_stats (device, type, timespan);
+ /* maybe the device doesn't support histories */
+ if (array == NULL) {
+ error = g_error_new (DKP_DAEMON_ERROR, DKP_DAEMON_ERROR_GENERAL, "device has no history");
+ dbus_g_method_return_error (context, error);
+ goto out;
+ }
- subsys = devkit_device_get_subsystem (d);
- if (strcmp (subsys, "power_supply") == 0) {
- device = DKP_DEVICE (dkp_source_new (daemon, d));
+ /* copy data to dbus struct */
+ complex = g_ptr_array_sized_new (array->len);
+ for (i=0; i<array->len; i++) {
+ obj = (const DkpHistoryObj *) g_ptr_array_index (array, i);
+ value = g_new0 (GValue, 1);
+ g_value_init (value, DKP_DBUS_STRUCT_UINT_DOUBLE_STRING);
+ g_value_take_boxed (value, dbus_g_type_specialized_construct (DKP_DBUS_STRUCT_UINT_DOUBLE_STRING));
+ dbus_g_type_struct_set (value, 0, obj->time, 1, obj->value, 2, dkp_source_state_to_text (obj->state), -1);
+ g_ptr_array_add (complex, g_value_get_boxed (value));
+ g_free (value);
}
- return device;
+
+ g_ptr_array_free (array, TRUE);
+ dbus_g_method_return (context, complex);
+out:
+ return TRUE;
+}
+
+/**
+ * dkp_device_refresh_internal:
+ **/
+static gboolean
+dkp_device_refresh_internal (DkpDevice *device)
+{
+ DkpObject *obj = dkp_device_get_obj (device);
+ DkpObject *obj_old;
+ gboolean ret;
+ gboolean success;
+ DkpDeviceClass *klass = DKP_DEVICE_GET_CLASS (device);
+
+ /* make a copy so we can see if anything changed */
+ obj_old = dkp_object_copy (obj);
+
+ /* do the refresh */
+ success = klass->refresh (device);
+ if (!success)
+ goto out;
+
+ /* the first time, print all properties */
+ if (!device->priv->has_ever_refresh) {
+ dkp_object_print (obj);
+ device->priv->has_ever_refresh = TRUE;
+ goto out;
+ }
+
+ /* print difference */
+ ret = !dkp_object_equal (obj, obj_old);
+ if (ret)
+ dkp_object_diff (obj_old, obj);
+out:
+ dkp_object_free (obj_old);
+ return success;
+}
+
+/**
+ * dkp_device_refresh:
+ **/
+gboolean
+dkp_device_refresh (DkpDevice *device, DBusGMethodInvocation *context)
+{
+ gboolean ret;
+ ret = dkp_device_refresh_internal (device);
+ dbus_g_method_return (context);
+ return ret;
}
+
/**
* dkp_device_changed:
**/
gboolean
dkp_device_changed (DkpDevice *device, DevkitDevice *d, gboolean synthesized)
{
- DkpDeviceClass *klass = DKP_DEVICE_GET_CLASS (device);
- return (klass->changed (device, d, synthesized));
+ gboolean keep_device;
+
+ g_object_unref (device->priv->d);
+ device->priv->d = g_object_ref (d);
+
+ keep_device = dkp_device_refresh_internal (device);
+
+ /* this 'change' event might prompt us to remove the supply */
+ if (!keep_device)
+ goto out;
+
+ /* no, it's good .. keep it */
+ dkp_device_emit_changed (device);
+
+out:
+ return keep_device;
}
/**
@@ -105,27 +396,244 @@ dkp_device_changed (DkpDevice *device, DevkitDevice *d, gboolean synthesized)
const gchar *
dkp_device_get_object_path (DkpDevice *device)
{
- DkpDeviceClass *klass = DKP_DEVICE_GET_CLASS (device);
- return klass->get_object_path (device);
+ return device->priv->object_path;
+}
+
+DkpObject *
+dkp_device_get_obj (DkpDevice *device)
+{
+ return device->priv->obj;
+}
+
+DevkitDevice *
+dkp_device_get_d (DkpDevice *device)
+{
+ return device->priv->d;
}
/**
- * dkp_device_get_on_battery:
+ * dkp_device_emit_changed:
**/
-gboolean
-dkp_device_get_on_battery (DkpDevice *device, gboolean *on_battery)
+void
+dkp_device_emit_changed (DkpDevice *device)
{
- DkpDeviceClass *klass = DKP_DEVICE_GET_CLASS (device);
- return klass->get_on_battery (device, on_battery);
+ dkp_debug ("emitting changed on %s", device->priv->obj->native_path);
+ g_signal_emit_by_name (device->priv->daemon, "device-changed",
+ device->priv->object_path, NULL);
+ g_signal_emit (device, signals[CHANGED_SIGNAL], 0);
}
/**
- * dkp_device_get_low_battery:
+ * dkp_device_compute_object_path_from_basename:
**/
-gboolean
-dkp_device_get_low_battery (DkpDevice *device, gboolean *low_battery)
+static char *
+dkp_device_compute_object_path_from_basename (const char *native_path_basename)
{
- DkpDeviceClass *klass = DKP_DEVICE_GET_CLASS (device);
- return klass->get_low_battery (device, low_battery);
+ gchar *basename;
+ gchar *object_path;
+ unsigned int n;
+
+ /* TODO: need to be more thorough with making proper object
+ * names that won't make D-Bus crash. This is just to cope
+ * with dm-0...
+ */
+ basename = g_path_get_basename (native_path_basename);
+ for (n = 0; basename[n] != '\0'; n++)
+ if (basename[n] == '-')
+ basename[n] = '_';
+ object_path = g_build_filename ("/devices/", basename, NULL);
+ g_free (basename);
+
+ return object_path;
+}
+
+/**
+ * dkp_device_compute_object_path:
+ **/
+static gchar *
+dkp_device_compute_object_path (const char *native_path)
+{
+ gchar *basename;
+ gchar *object_path;
+
+ basename = g_path_get_basename (native_path);
+ object_path = dkp_device_compute_object_path_from_basename (basename);
+ g_free (basename);
+ return object_path;
+}
+
+/**
+ * dkp_device_register_device:
+ **/
+static gboolean
+dkp_device_register_device (DkpDevice *device)
+{
+ gboolean ret = TRUE;
+
+ device->priv->object_path = dkp_device_compute_object_path (device->priv->obj->native_path);
+ dbus_g_connection_register_g_object (device->priv->system_bus_connection,
+ device->priv->object_path, G_OBJECT (device));
+ device->priv->system_bus_proxy = dbus_g_proxy_new_for_name (device->priv->system_bus_connection,
+ DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
+ if (device->priv->system_bus_proxy == NULL) {
+ dkp_warning ("proxy invalid");
+ ret = FALSE;
+ }
+ return ret;
+}
+
+/**
+ * dkp_device_init:
+ **/
+static void
+dkp_device_init (DkpDevice *device)
+{
+ GError *error = NULL;
+
+ device->priv = DKP_DEVICE_GET_PRIVATE (device);
+ device->priv->object_path = NULL;
+ device->priv->system_bus_connection = NULL;
+ device->priv->system_bus_proxy = NULL;
+ device->priv->daemon = NULL;
+ device->priv->d = NULL;
+ device->priv->has_ever_refresh = FALSE;
+ device->priv->obj = dkp_object_new ();
+
+ device->priv->system_bus_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (device->priv->system_bus_connection == NULL) {
+ dkp_error ("error getting system bus: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+/**
+ * dkp_device_finalize:
+ **/
+static void
+dkp_device_finalize (GObject *object)
+{
+ DkpDevice *device;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (DKP_IS_DEVICE (object));
+
+ device = DKP_DEVICE (object);
+ g_return_if_fail (device->priv != NULL);
+ g_object_unref (device->priv->d);
+ g_object_unref (device->priv->daemon);
+ dkp_object_free (device->priv->obj);
+
+ G_OBJECT_CLASS (dkp_device_parent_class)->finalize (object);
+}
+
+/**
+ * dkp_device_class_init:
+ **/
+static void
+dkp_device_class_init (DkpDeviceClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->get_property = dkp_device_get_property;
+ object_class->finalize = dkp_device_finalize;
+
+
+ g_type_class_add_private (klass, sizeof (DkpDevicePrivate));
+
+ signals[CHANGED_SIGNAL] =
+ g_signal_new ("changed",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ dbus_g_object_type_install_info (DKP_TYPE_DEVICE, &dbus_glib_dkp_device_object_info);
+
+ g_object_class_install_property (
+ object_class,
+ PROP_NATIVE_PATH,
+ g_param_spec_string ("native-path", NULL, NULL, NULL, G_PARAM_READABLE));
+ g_object_class_install_property (
+ object_class,
+ PROP_VENDOR,
+ g_param_spec_string ("vendor", NULL, NULL, NULL, G_PARAM_READABLE));
+ g_object_class_install_property (
+ object_class,
+ PROP_MODEL,
+ g_param_spec_string ("model", NULL, NULL, NULL, G_PARAM_READABLE));
+ g_object_class_install_property (
+ object_class,
+ PROP_SERIAL,
+ g_param_spec_string ("serial", NULL, NULL, NULL, G_PARAM_READABLE));
+ g_object_class_install_property (
+ object_class,
+ PROP_UPDATE_TIME,
+ g_param_spec_uint64 ("update-time", NULL, NULL, 0, G_MAXUINT64, 0, G_PARAM_READABLE));
+ g_object_class_install_property (
+ object_class,
+ PROP_TYPE,
+ g_param_spec_string ("type", NULL, NULL, NULL, G_PARAM_READABLE));
+ g_object_class_install_property (
+ object_class,
+ PROP_BATTERY_IS_PRESENT,
+ g_param_spec_boolean ("power-supply", NULL, NULL, FALSE, G_PARAM_READABLE));
+ g_object_class_install_property (
+ object_class,
+ PROP_LINE_POWER_ONLINE,
+ g_param_spec_boolean ("line-power-online", NULL, NULL, FALSE, G_PARAM_READABLE));
+ g_object_class_install_property (
+ object_class,
+ PROP_BATTERY_ENERGY,
+ g_param_spec_double ("battery-energy", NULL, NULL, 0, G_MAXDOUBLE, 0, G_PARAM_READABLE));
+ g_object_class_install_property (
+ object_class,
+ PROP_BATTERY_IS_PRESENT,
+ g_param_spec_boolean ("battery-is-present", NULL, NULL, FALSE, G_PARAM_READABLE));
+ g_object_class_install_property (
+ object_class,
+ PROP_BATTERY_IS_RECHARGEABLE,
+ g_param_spec_boolean ("battery-is-rechargeable", NULL, NULL, FALSE, G_PARAM_READABLE));
+ g_object_class_install_property (
+ object_class,
+ PROP_BATTERY_STATE,
+ g_param_spec_string ("battery-state", NULL, NULL, NULL, G_PARAM_READABLE));
+ g_object_class_install_property (
+ object_class,
+ PROP_BATTERY_CAPACITY,
+ g_param_spec_double ("battery-capacity", NULL, NULL, 0, G_MAXDOUBLE, 0, G_PARAM_READABLE));
+ g_object_class_install_property (
+ object_class,
+ PROP_BATTERY_ENERGY_EMPTY,
+ g_param_spec_double ("battery-energy-empty", NULL, NULL, 0, G_MAXDOUBLE, 0, G_PARAM_READABLE));
+ g_object_class_install_property (
+ object_class,
+ PROP_BATTERY_ENERGY_FULL,
+ g_param_spec_double ("battery-energy-full", NULL, NULL, 0, G_MAXDOUBLE, 0, G_PARAM_READABLE));
+ g_object_class_install_property (
+ object_class,
+ PROP_BATTERY_ENERGY_FULL_DESIGN,
+ g_param_spec_double ("battery-energy-full-design", NULL, NULL, 0, G_MAXDOUBLE, 0, G_PARAM_READABLE));
+ g_object_class_install_property (
+ object_class,
+ PROP_BATTERY_ENERGY_RATE,
+ g_param_spec_double ("battery-energy-rate", NULL, NULL, -G_MAXDOUBLE, G_MAXDOUBLE, 0, G_PARAM_READABLE));
+ g_object_class_install_property (
+ object_class,
+ PROP_BATTERY_TIME_TO_EMPTY,
+ g_param_spec_int64 ("battery-time-to-empty", NULL, NULL, -1, G_MAXINT64, -1, G_PARAM_READABLE));
+ g_object_class_install_property (
+ object_class,
+ PROP_BATTERY_TIME_TO_FULL,
+ g_param_spec_int64 ("battery-time-to-full", NULL, NULL, -1, G_MAXINT64, -1, G_PARAM_READABLE));
+ g_object_class_install_property (
+ object_class,
+ PROP_BATTERY_PERCENTAGE,
+ g_param_spec_double ("battery-percentage", NULL, NULL, -1, 100, -1, G_PARAM_READABLE));
+ g_object_class_install_property (
+ object_class,
+ PROP_BATTERY_TECHNOLOGY,
+ g_param_spec_string ("battery-technology", NULL, NULL, NULL, G_PARAM_READABLE));
+
+ dbus_g_error_domain_register (DKP_DEVICE_ERROR, NULL, DKP_DEVICE_TYPE_ERROR);
}
diff --git a/src/dkp-device.h b/src/dkp-device.h
index fc5d0e2..9724948 100644
--- a/src/dkp-device.h
+++ b/src/dkp-device.h
@@ -25,21 +25,26 @@
#include <glib-object.h>
#include <polkit-dbus/polkit-dbus.h>
#include <devkit-gobject.h>
+#include <dbus/dbus-glib.h>
+#include "dkp-object.h"
#include "dkp-daemon.h"
G_BEGIN_DECLS
-#define DKP_SOURCE_TYPE_DEVICE (dkp_device_get_type ())
-#define DKP_DEVICE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DKP_SOURCE_TYPE_DEVICE, DkpDevice))
-#define DKP_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), DKP_SOURCE_TYPE_DEVICE, DkpDeviceClass))
-#define DKP_IS_DEVICE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), DKP_SOURCE_TYPE_DEVICE))
-#define DKP_IS_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DKP_SOURCE_TYPE_DEVICE))
-#define DKP_DEVICE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DKP_SOURCE_TYPE_DEVICE, DkpDeviceClass))
+#define DKP_TYPE_DEVICE (dkp_device_get_type ())
+#define DKP_DEVICE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DKP_TYPE_DEVICE, DkpDevice))
+#define DKP_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), DKP_TYPE_DEVICE, DkpDeviceClass))
+#define DKP_IS_DEVICE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), DKP_TYPE_DEVICE))
+#define DKP_IS_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DKP_TYPE_DEVICE))
+#define DKP_DEVICE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DKP_TYPE_DEVICE, DkpDeviceClass))
+
+typedef struct DkpDevicePrivate DkpDevicePrivate;
typedef struct
{
- GObject parent;
+ GObject parent;
+ DkpDevicePrivate *priv;
} DkpDevice;
typedef struct
@@ -47,29 +52,53 @@ typedef struct
GObjectClass parent_class;
/* vtable */
- gboolean (*changed) (DkpDevice *device,
- DevkitDevice *d,
- gboolean synthesized);
- void (*removed) (DkpDevice *device);
- const gchar *(*get_object_path) (DkpDevice *device);
+ gboolean (*coldplug) (DkpDevice *device);
+ gboolean (*refresh) (DkpDevice *device);
+ const gchar *(*get_id) (DkpDevice *device);
gboolean (*get_on_battery) (DkpDevice *device,
gboolean *on_battery);
gboolean (*get_low_battery) (DkpDevice *device,
gboolean *low_battery);
+ GPtrArray *(*get_stats) (DkpDevice *device,
+ const gchar *type,
+ guint timespan);
} DkpDeviceClass;
+typedef enum
+{
+ DKP_DEVICE_ERROR_GENERAL,
+ DKP_DEVICE_NUM_ERRORS
+} DkpDeviceError;
+
+#define DKP_DEVICE_ERROR dkp_device_error_quark ()
+#define DKP_DEVICE_TYPE_ERROR (dkp_device_error_get_type ())
+
+GQuark dkp_device_error_quark (void);
+GType dkp_device_error_get_type (void);
GType dkp_device_get_type (void);
-DkpDevice *dkp_device_new (DkpDaemon *daemon,
+gboolean dkp_device_coldplug (DkpDevice *device,
+ DkpDaemon *daemon,
DevkitDevice *d);
gboolean dkp_device_changed (DkpDevice *device,
DevkitDevice *d,
gboolean synthesized);
void dkp_device_removed (DkpDevice *device);
+DkpObject *dkp_device_get_obj (DkpDevice *device);
+DevkitDevice *dkp_device_get_d (DkpDevice *device);
const gchar *dkp_device_get_object_path (DkpDevice *device);
gboolean dkp_device_get_on_battery (DkpDevice *device,
gboolean *on_battery);
gboolean dkp_device_get_low_battery (DkpDevice *device,
gboolean *low_battery);
+void dkp_device_emit_changed (DkpDevice *device);
+
+/* exported methods */
+gboolean dkp_device_refresh (DkpDevice *device,
+ DBusGMethodInvocation *context);
+gboolean dkp_device_get_statistics (DkpDevice *device,
+ const gchar *type,
+ guint timespan,
+ DBusGMethodInvocation *context);
G_END_DECLS
diff --git a/src/dkp-source.c b/src/dkp-source.c
deleted file mode 100644
index c14ded6..0000000
--- a/src/dkp-source.c
+++ /dev/null
@@ -1,991 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2008 David Zeuthen <david@fubar.dk>
- * Copyright (C) 2008 Richard Hughes <richard@hughsie.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <string.h>
-#include <math.h>
-
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <glib/gi18n-lib.h>
-#include <glib-object.h>
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
-#include <devkit-gobject.h>
-#include <polkit-dbus/polkit-dbus.h>
-
-#include "sysfs-utils.h"
-#include "dkp-debug.h"
-#include "dkp-enum.h"
-#include "dkp-object.h"
-#include "dkp-source.h"
-#include "dkp-history.h"
-#include "dkp-history-obj.h"
-#include "dkp-marshal.h"
-#include "dkp-source-glue.h"
-
-#define DK_POWER_MIN_CHARGED_PERCENTAGE 60
-
-struct DkpSourcePrivate
-{
- DBusGConnection *system_bus_connection;
- DBusGProxy *system_bus_proxy;
- DkpDaemon *daemon;
- DevkitDevice *d;
- DkpHistory *history;
- gchar *object_path;
- guint poll_timer_id;
- DkpObject *obj;
- gboolean has_coldplug_values;
- gdouble battery_energy_old;
- GTimeVal battery_energy_old_timespec;
-};
-
-static void dkp_source_class_init (DkpSourceClass *klass);
-static void dkp_source_init (DkpSource *source);
-static void dkp_source_finalize (GObject *object);
-static void dkp_source_reset_values (DkpSource *source);
-static gboolean dkp_source_update (DkpSource *source);
-
-enum
-{
- PROP_0,
- PROP_NATIVE_PATH,
- PROP_VENDOR,
- PROP_MODEL,
- PROP_SERIAL,
- PROP_UPDATE_TIME,
- PROP_TYPE,
- PROP_LINE_POWER_ONLINE,
- PROP_POWER_SUPPLY,
- PROP_BATTERY_CAPACITY,
- PROP_BATTERY_IS_PRESENT,
- PROP_BATTERY_IS_RECHARGEABLE,
- PROP_BATTERY_STATE,
- PROP_BATTERY_ENERGY,
- PROP_BATTERY_ENERGY_EMPTY,
- PROP_BATTERY_ENERGY_FULL,
- PROP_BATTERY_ENERGY_FULL_DESIGN,
- PROP_BATTERY_ENERGY_RATE,
- PROP_BATTERY_TIME_TO_EMPTY,
- PROP_BATTERY_TIME_TO_FULL,
- PROP_BATTERY_PERCENTAGE,
- PROP_BATTERY_TECHNOLOGY,
-};
-
-enum
-{
- CHANGED_SIGNAL,
- LAST_SIGNAL,
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-G_DEFINE_TYPE (DkpSource, dkp_source, DKP_SOURCE_TYPE_DEVICE)
-#define DKP_SOURCE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DKP_SOURCE_TYPE_SOURCE, DkpSourcePrivate))
-
-static const char *dkp_source_get_object_path (DkpDevice *device);
-static gboolean dkp_source_get_on_battery (DkpDevice *device, gboolean *on_battery);
-static gboolean dkp_source_get_low_battery (DkpDevice *device, gboolean *low_battery);
-static void dkp_source_removed (DkpDevice *device);
-static gboolean dkp_source_changed (DkpDevice *device, DevkitDevice *d, gboolean synthesized);
-
-/**
- * dkp_source_error_quark:
- **/
-GQuark
-dkp_source_error_quark (void)
-{
- static GQuark ret = 0;
-
- if (ret == 0) {
- ret = g_quark_from_static_string ("dkp_source_error");
- }
-
- return ret;
-}
-
-#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
-
-/**
- * dkp_source_error_get_type:
- **/
-GType
-dkp_source_error_get_type (void)
-{
- static GType etype = 0;
-
- if (etype == 0)
- {
- static const GEnumValue values[] =
- {
- ENUM_ENTRY (DKP_SOURCE_ERROR_GENERAL, "GeneralError"),
- { 0, 0, 0 }
- };
- g_assert (DKP_SOURCE_NUM_ERRORS == G_N_ELEMENTS (values) - 1);
- etype = g_enum_register_static ("DkpSourceError", values);
- }
- return etype;
-}
-
-/**
- * dkp_source_get_property:
- **/
-static void
-dkp_source_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
-{
- DkpSource *source = DKP_SOURCE (object);
- DkpObject *obj = source->priv->obj;
-
- switch (prop_id) {
- case PROP_NATIVE_PATH:
- g_value_set_string (value, obj->native_path);
- break;
- case PROP_VENDOR:
- g_value_set_string (value, obj->vendor);
- break;
- case PROP_MODEL:
- g_value_set_string (value, obj->model);
- break;
- case PROP_SERIAL:
- g_value_set_string (value, obj->serial);
- break;
- case PROP_UPDATE_TIME:
- g_value_set_uint64 (value, obj->update_time);
- break;
- case PROP_TYPE:
- g_value_set_string (value, dkp_source_type_to_text (obj->type));
- break;
- case PROP_POWER_SUPPLY:
- g_value_set_boolean (value, obj->power_supply);
- break;
- case PROP_LINE_POWER_ONLINE:
- g_value_set_boolean (value, obj->line_power_online);
- break;
- case PROP_BATTERY_IS_PRESENT:
- g_value_set_boolean (value, obj->battery_is_present);
- break;
- case PROP_BATTERY_IS_RECHARGEABLE:
- g_value_set_boolean (value, obj->battery_is_rechargeable);
- break;
- case PROP_BATTERY_STATE:
- g_value_set_string (value, dkp_source_state_to_text (obj->battery_state));
- break;
- case PROP_BATTERY_CAPACITY:
- g_value_set_double (value, obj->battery_capacity);
- break;
- case PROP_BATTERY_ENERGY:
- g_value_set_double (value, obj->battery_energy);
- break;
- case PROP_BATTERY_ENERGY_EMPTY:
- g_value_set_double (value, obj->battery_energy_empty);
- break;
- case PROP_BATTERY_ENERGY_FULL:
- g_value_set_double (value, obj->battery_energy_full);
- break;
- case PROP_BATTERY_ENERGY_FULL_DESIGN:
- g_value_set_double (value, obj->battery_energy_full_design);
- break;
- case PROP_BATTERY_ENERGY_RATE:
- g_value_set_double (value, obj->battery_energy_rate);
- break;
- case PROP_BATTERY_TIME_TO_EMPTY:
- g_value_set_int64 (value, obj->battery_time_to_empty);
- break;
- case PROP_BATTERY_TIME_TO_FULL:
- g_value_set_int64 (value, obj->battery_time_to_full);
- break;
- case PROP_BATTERY_PERCENTAGE:
- g_value_set_double (value, obj->battery_percentage);
- break;
- case PROP_BATTERY_TECHNOLOGY:
- g_value_set_string (value, dkp_source_technology_to_text (obj->battery_technology));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-/**
- * dkp_source_class_init:
- **/
-static void
-dkp_source_class_init (DkpSourceClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- DkpDeviceClass *device_class = DKP_DEVICE_CLASS (klass);
-
- object_class->finalize = dkp_source_finalize;
- object_class->get_property = dkp_source_get_property;
- device_class->changed = dkp_source_changed;
- device_class->removed = dkp_source_removed;
- device_class->get_object_path = dkp_source_get_object_path;
- device_class->get_on_battery = dkp_source_get_on_battery;
- device_class->get_low_battery = dkp_source_get_low_battery;
-
- g_type_class_add_private (klass, sizeof (DkpSourcePrivate));
-
- signals[CHANGED_SIGNAL] =
- g_signal_new ("changed",
- G_OBJECT_CLASS_TYPE (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0, NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- dbus_g_object_type_install_info (DKP_SOURCE_TYPE_SOURCE, &dbus_glib_dkp_source_object_info);
-
- g_object_class_install_property (
- object_class,
- PROP_NATIVE_PATH,
- g_param_spec_string ("native-path", NULL, NULL, NULL, G_PARAM_READABLE));
- g_object_class_install_property (
- object_class,
- PROP_VENDOR,
- g_param_spec_string ("vendor", NULL, NULL, NULL, G_PARAM_READABLE));
- g_object_class_install_property (
- object_class,
- PROP_MODEL,
- g_param_spec_string ("model", NULL, NULL, NULL, G_PARAM_READABLE));
- g_object_class_install_property (
- object_class,
- PROP_SERIAL,
- g_param_spec_string ("serial", NULL, NULL, NULL, G_PARAM_READABLE));
- g_object_class_install_property (
- object_class,
- PROP_UPDATE_TIME,
- g_param_spec_uint64 ("update-time", NULL, NULL, 0, G_MAXUINT64, 0, G_PARAM_READABLE));
- g_object_class_install_property (
- object_class,
- PROP_TYPE,
- g_param_spec_string ("type", NULL, NULL, NULL, G_PARAM_READABLE));
- g_object_class_install_property (
- object_class,
- PROP_BATTERY_IS_PRESENT,
- g_param_spec_boolean ("power-supply", NULL, NULL, FALSE, G_PARAM_READABLE));
- g_object_class_install_property (
- object_class,
- PROP_LINE_POWER_ONLINE,
- g_param_spec_boolean ("line-power-online", NULL, NULL, FALSE, G_PARAM_READABLE));
- g_object_class_install_property (
- object_class,
- PROP_BATTERY_ENERGY,
- g_param_spec_double ("battery-energy", NULL, NULL, 0, G_MAXDOUBLE, 0, G_PARAM_READABLE));
- g_object_class_install_property (
- object_class,
- PROP_BATTERY_IS_PRESENT,
- g_param_spec_boolean ("battery-is-present", NULL, NULL, FALSE, G_PARAM_READABLE));
- g_object_class_install_property (
- object_class,
- PROP_BATTERY_IS_RECHARGEABLE,
- g_param_spec_boolean ("battery-is-rechargeable", NULL, NULL, FALSE, G_PARAM_READABLE));
- g_object_class_install_property (
- object_class,
- PROP_BATTERY_STATE,
- g_param_spec_string ("battery-state", NULL, NULL, NULL, G_PARAM_READABLE));
- g_object_class_install_property (
- object_class,
- PROP_BATTERY_CAPACITY,
- g_param_spec_double ("battery-capacity", NULL, NULL, 0, G_MAXDOUBLE, 0, G_PARAM_READABLE));
- g_object_class_install_property (
- object_class,
- PROP_BATTERY_ENERGY_EMPTY,
- g_param_spec_double ("battery-energy-empty", NULL, NULL, 0, G_MAXDOUBLE, 0, G_PARAM_READABLE));
- g_object_class_install_property (
- object_class,
- PROP_BATTERY_ENERGY_FULL,
- g_param_spec_double ("battery-energy-full", NULL, NULL, 0, G_MAXDOUBLE, 0, G_PARAM_READABLE));
- g_object_class_install_property (
- object_class,
- PROP_BATTERY_ENERGY_FULL_DESIGN,
- g_param_spec_double ("battery-energy-full-design", NULL, NULL, 0, G_MAXDOUBLE, 0, G_PARAM_READABLE));
- g_object_class_install_property (
- object_class,
- PROP_BATTERY_ENERGY_RATE,
- g_param_spec_double ("battery-energy-rate", NULL, NULL, -G_MAXDOUBLE, G_MAXDOUBLE, 0, G_PARAM_READABLE));
- g_object_class_install_property (
- object_class,
- PROP_BATTERY_TIME_TO_EMPTY,
- g_param_spec_int64 ("battery-time-to-empty", NULL, NULL, -1, G_MAXINT64, -1, G_PARAM_READABLE));
- g_object_class_install_property (
- object_class,
- PROP_BATTERY_TIME_TO_FULL,
- g_param_spec_int64 ("battery-time-to-full", NULL, NULL, -1, G_MAXINT64, -1, G_PARAM_READABLE));
- g_object_class_install_property (
- object_class,
- PROP_BATTERY_PERCENTAGE,
- g_param_spec_double ("battery-percentage", NULL, NULL, -1, 100, -1, G_PARAM_READABLE));
- g_object_class_install_property (
- object_class,
- PROP_BATTERY_TECHNOLOGY,
- g_param_spec_string ("battery-technology", NULL, NULL, NULL, G_PARAM_READABLE));
-
- dbus_g_error_domain_register (DKP_SOURCE_ERROR, NULL, DKP_SOURCE_TYPE_ERROR);
-}
-
-/**
- * dkp_source_init:
- **/
-static void
-dkp_source_init (DkpSource *source)
-{
- source->priv = DKP_SOURCE_GET_PRIVATE (source);
- dkp_source_reset_values (source);
-}
-
-/**
- * dkp_source_finalize:
- **/
-static void
-dkp_source_finalize (GObject *object)
-{
- DkpSource *source;
-
- g_return_if_fail (object != NULL);
- g_return_if_fail (DKP_IS_SOURCE (object));
-
- source = DKP_SOURCE (object);
- g_return_if_fail (source->priv != NULL);
-
- g_object_unref (source->priv->d);
- g_object_unref (source->priv->daemon);
- g_object_unref (source->priv->history);
- dkp_object_free (source->priv->obj);
-
- if (source->priv->poll_timer_id > 0)
- g_source_remove (source->priv->poll_timer_id);
-
- G_OBJECT_CLASS (dkp_source_parent_class)->finalize (object);
-}
-
-/**
- * dkp_source_compute_object_path_from_basename:
- **/
-static char *
-dkp_source_compute_object_path_from_basename (const char *native_path_basename)
-{
- gchar *basename;
- gchar *object_path;
- unsigned int n;
-
- /* TODO: need to be more thorough with making proper object
- * names that won't make D-Bus crash. This is just to cope
- * with dm-0...
- */
- basename = g_path_get_basename (native_path_basename);
- for (n = 0; basename[n] != '\0'; n++)
- if (basename[n] == '-')
- basename[n] = '_';
- object_path = g_build_filename ("/sources/", basename, NULL);
- g_free (basename);
-
- return object_path;
-}
-
-/**
- * dkp_source_compute_object_path:
- **/
-static gchar *
-dkp_source_compute_object_path (const char *native_path)
-{
- gchar *basename;
- gchar *object_path;
-
- basename = g_path_get_basename (native_path);
- object_path = dkp_source_compute_object_path_from_basename (basename);
- g_free (basename);
- return object_path;
-}
-
-/**
- * dkp_source_register_source:
- **/
-static gboolean
-dkp_source_register_source (DkpSource *source)
-{
- DBusConnection *connection;
- GError *error = NULL;
-
- source->priv->system_bus_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
- if (source->priv->system_bus_connection == NULL) {
- if (error != NULL) {
- g_critical ("error getting system bus: %s", error->message);
- g_error_free (error);
- }
- goto error;
- }
- connection = dbus_g_connection_get_connection (source->priv->system_bus_connection);
-
- source->priv->object_path = dkp_source_compute_object_path (source->priv->obj->native_path);
-
- dbus_g_connection_register_g_object (source->priv->system_bus_connection,
- source->priv->object_path, G_OBJECT (source));
-
- source->priv->system_bus_proxy = dbus_g_proxy_new_for_name (source->priv->system_bus_connection,
- DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
-
- return TRUE;
-
-error:
- return FALSE;
-}
-
-/**
- * dkp_source_new:
- **/
-DkpSource *
-dkp_source_new (DkpDaemon *daemon, DevkitDevice *d)
-{
- DkpSource *source;
- const gchar *native_path;
- gchar *id;
-
- source = NULL;
- native_path = devkit_device_get_native_path (d);
-
- source = DKP_SOURCE (g_object_new (DKP_SOURCE_TYPE_SOURCE, NULL));
- source->priv->d = g_object_ref (d);
- source->priv->daemon = g_object_ref (daemon);
- source->priv->obj = dkp_object_new ();
- source->priv->obj->native_path = g_strdup (native_path);
- source->priv->history = dkp_history_new ();
-
- /* detect what kind of device we are */
- if (sysfs_file_exists (native_path, "online")) {
- source->priv->obj->type = DKP_SOURCE_TYPE_LINE_POWER;
- } else {
- /* this is correct, UPS and CSR are not in the kernel */
- source->priv->obj->type = DKP_SOURCE_TYPE_BATTERY;
- }
-
- /* coldplug */
- if (!dkp_source_update (source)) {
- dkp_warning ("coldplug of %s failed", source->priv->obj->native_path);
- g_object_unref (source);
- source = NULL;
- goto out;
- }
-
- /* register on the bus */
- if (!dkp_source_register_source (DKP_SOURCE (source))) {
- dkp_warning ("failed to register on the bus");
- g_object_unref (source);
- source = NULL;
- goto out;
- }
-
- /* get the id so we can load the old history */
- id = dkp_object_get_id (source->priv->obj);
- if (id != NULL)
- dkp_history_set_id (source->priv->history, id);
- g_free (id);
-
-out:
- return source;
-}
-
-/**
- * dkp_source_emit_changed:
- **/
-static void
-dkp_source_emit_changed (DkpSource *source)
-{
- dkp_debug ("emitting changed on %s", source->priv->obj->native_path);
- g_signal_emit_by_name (source->priv->daemon, "device-changed",
- source->priv->object_path, NULL);
- g_signal_emit (source, signals[CHANGED_SIGNAL], 0);
-}
-
-/**
- * dkp_source_changed:
- **/
-static gboolean
-dkp_source_changed (DkpDevice *device, DevkitDevice *d, gboolean synthesized)
-{
- DkpSource *source = DKP_SOURCE (device);
- gboolean keep_source;
-
- g_object_unref (source->priv->d);
- source->priv->d = g_object_ref (d);
-
- keep_source = dkp_source_update (source);
-
- /* this 'change' event might prompt us to remove the source */
- if (!keep_source)
- goto out;
-
- /* no, it's good .. keep it */
- dkp_source_emit_changed (source);
-
-out:
- return keep_source;
-}
-
-/**
- * dkp_source_removed:
- **/
-void
-dkp_source_removed (DkpDevice *device)
-{
-}
-
-/**
- * dkp_source_get_object_path:
- **/
-static const char *
-dkp_source_get_object_path (DkpDevice *device)
-{
- DkpSource *source = DKP_SOURCE (device);
- return source->priv->object_path;
-}
-
-/**
- * dkp_source_update_line_power:
- **/
-static gboolean
-dkp_source_update_line_power (DkpSource *source)
-{
- DkpObject *obj = source->priv->obj;
- DkpObject *obj_old;
- gboolean ret;
-
- /* make a copy so we can see if anything changed */
- obj_old = dkp_object_copy (obj);
-
- /* force true */
- obj->power_supply = TRUE;
-
- /* get new AC value */
- obj->line_power_online = sysfs_get_int (obj->native_path, "online");
-
- /* initial value */
- if (!source->priv->has_coldplug_values) {
- dkp_object_print (obj);
- source->priv->has_coldplug_values = TRUE;
- goto out;
- }
-
- /* print difference */
- ret = !dkp_object_equal (obj, obj_old);
- if (ret)
- dkp_object_diff (obj_old, obj);
-out:
- dkp_object_free (obj_old);
- return TRUE;
-}
-
-/**
- * dkp_source_reset_values:
- **/
-static void
-dkp_source_reset_values (DkpSource *source)
-{
- source->priv->has_coldplug_values = FALSE;
- source->priv->battery_energy_old = -1;
- source->priv->battery_energy_old_timespec.tv_sec = 0;
- dkp_object_clear (source->priv->obj);
-}
-
-/**
- * dkp_source_get_on_battery:
- **/
-static gboolean
-dkp_source_get_on_battery (DkpDevice *device, gboolean *on_battery)
-{
- DkpSource *source = DKP_SOURCE (device);
-
- g_return_val_if_fail (DKP_IS_SOURCE (source), FALSE);
- g_return_val_if_fail (on_battery != NULL, FALSE);
-
- if (source->priv->obj->type != DKP_SOURCE_TYPE_BATTERY)
- return FALSE;
- if (!source->priv->obj->battery_is_present)
- return FALSE;
-
- *on_battery = (source->priv->obj->battery_state == DKP_SOURCE_STATE_DISCHARGING);
- return TRUE;
-}
-
-/**
- * dkp_source_get_low_battery:
- **/
-static gboolean
-dkp_source_get_low_battery (DkpDevice *device, gboolean *low_battery)
-{
- gboolean ret;
- gboolean on_battery;
- DkpSource *source = DKP_SOURCE (device);
-
- g_return_val_if_fail (DKP_IS_SOURCE (source), FALSE);
- g_return_val_if_fail (low_battery != NULL, FALSE);
-
- /* reuse the common checks */
- ret = dkp_source_get_on_battery (device, &on_battery);
- if (!ret)
- return FALSE;
-
- /* shortcut */
- if (!on_battery) {
- *low_battery = FALSE;
- return TRUE;
- }
-
- *low_battery = (source->priv->obj->battery_percentage < 10);
- return TRUE;
-}
-
-/**
- * dkp_source_calculate_battery_rate:
- **/
-static void
-dkp_source_calculate_battery_rate (DkpSource *source)
-{
- guint time;
- gdouble energy;
- GTimeVal now;
- DkpObject *obj = source->priv->obj;
-
- if (obj->battery_energy < 0)
- return;
-
- if (source->priv->battery_energy_old < 0)
- return;
-
- if (source->priv->battery_energy_old == obj->battery_energy)
- return;
-
- /* get the time difference */
- g_get_current_time (&now);
- time = now.tv_sec - source->priv->battery_energy_old_timespec.tv_sec;
-
- if (time == 0)
- return;
-
- /* get the difference in charge */
- energy = source->priv->battery_energy_old - obj->battery_energy;
- if (energy < 0.1)
- return;
-
- /* probably okay */
- obj->battery_energy_rate = energy * 3600 / time;
-}
-
-/**
- * dkp_source_update_battery:
- *
- * Return value: TRUE if we changed
- **/
-static gboolean
-dkp_source_update_battery (DkpSource *source)
-{
- gchar *status = NULL;
- gboolean ret;
- gboolean just_added = FALSE;
- DkpSourceState battery_state;
- DkpObject *obj = source->priv->obj;
- DkpObject *obj_old;
-
- /* make a copy so we can see if anything changed */
- obj_old = dkp_object_copy (obj);
-
- /* have we just been removed? */
- obj->battery_is_present = sysfs_get_bool (obj->native_path, "present");
- if (!obj->battery_is_present) {
- dkp_source_reset_values (source);
- obj->type = DKP_SOURCE_TYPE_BATTERY;
- goto out;
- }
-
- /* initial values */
- if (!source->priv->has_coldplug_values) {
- gchar *technology_native;
-
- /* when we add via sysfs power_supply class then we know this is true */
- obj->power_supply = TRUE;
-
- /* the ACPI spec is bad at defining battery type constants */
- technology_native = g_strstrip (sysfs_get_string (obj->native_path, "technology"));
- obj->battery_technology = dkp_acpi_to_source_technology (technology_native);
- g_free (technology_native);
-
- obj->vendor = g_strstrip (sysfs_get_string (obj->native_path, "manufacturer"));
- obj->model = g_strstrip (sysfs_get_string (obj->native_path, "model_name"));
- obj->serial = g_strstrip (sysfs_get_string (obj->native_path, "serial_number"));
-
- /* assume true for laptops */
- obj->battery_is_rechargeable = TRUE;
-
- /* these don't change at runtime */
- obj->battery_energy_full =
- sysfs_get_double (obj->native_path, "energy_full") / 1000000.0;
- obj->battery_energy_full_design =
- sysfs_get_double (obj->native_path, "energy_full_design") / 1000000.0;
-
- /* the last full cannot be bigger than the design */
- if (obj->battery_energy_full > obj->battery_energy_full_design)
- obj->battery_energy_full = obj->battery_energy_full_design;
-
- /* calculate how broken our battery is */
- obj->battery_capacity = obj->battery_energy_full_design / obj->battery_energy_full * 100.0f;
- if (obj->battery_capacity < 0)
- obj->battery_capacity = 0;
- if (obj->battery_capacity > 100.0)
- obj->battery_capacity = 100.0;
-
- /* we only coldplug once, as these values will never change */
- source->priv->has_coldplug_values = TRUE;
- just_added = TRUE;
- }
-
- status = g_strstrip (sysfs_get_string (obj->native_path, "status"));
- if (strcasecmp (status, "charging") == 0)
- battery_state = DKP_SOURCE_STATE_CHARGING;
- else if (strcasecmp (status, "discharging") == 0)
- battery_state = DKP_SOURCE_STATE_DISCHARGING;
- else if (strcasecmp (status, "full") == 0)
- battery_state = DKP_SOURCE_STATE_FULLY_CHARGED;
- else if (strcasecmp (status, "empty") == 0)
- battery_state = DKP_SOURCE_STATE_EMPTY;
- else {
- dkp_warning ("unknown status string: %s", status);
- battery_state = DKP_SOURCE_STATE_UNKNOWN;
- }
-
- /* get the currect charge */
- obj->battery_energy =
- sysfs_get_double (obj->native_path, "energy_avg") / 1000000.0;
- if (obj->battery_energy == 0)
- obj->battery_energy =
- sysfs_get_double (obj->native_path, "energy_now") / 1000000.0;
-
- /* some batteries don't update last_full attribute */
- if (obj->battery_energy > obj->battery_energy_full)
- obj->battery_energy_full = obj->battery_energy;
-
- obj->battery_energy_rate =
- fabs (sysfs_get_double (obj->native_path, "current_now") / 1000000.0);
-
- /* ACPI gives out the special 'Ones' value for rate when it's unable
- * to calculate the true rate. We should set the rate zero, and wait
- * for the BIOS to stabilise. */
- if (obj->battery_energy_rate == 0xffff)
- obj->battery_energy_rate = -1;
-
- /* sanity check to less than 100W */
- if (obj->battery_energy_rate > 100*1000)
- obj->battery_energy_rate = -1;
-
- /* the hardware reporting failed -- try to calculate this */
- if (obj->battery_energy_rate < 0) {
- dkp_source_calculate_battery_rate (source);
- }
-
- /* charging has a negative rate */
- if (obj->battery_energy_rate > 0 && battery_state == DKP_SOURCE_STATE_CHARGING)
- obj->battery_energy_rate *= -1.0;
-
- /* get a precise percentage */
- obj->battery_percentage = 100.0 * obj->battery_energy / obj->battery_energy_full;
- if (obj->battery_percentage < 0)
- obj->battery_percentage = 0;
- if (obj->battery_percentage > 100.0)
- obj->battery_percentage = 100.0;
-
- /* calculate a quick and dirty time remaining value */
- obj->battery_time_to_empty = -1;
- obj->battery_time_to_full = -1;
- if (obj->battery_energy_rate > 0) {
- if (battery_state == DKP_SOURCE_STATE_DISCHARGING) {
- obj->battery_time_to_empty = 3600 * (obj->battery_energy / obj->battery_energy_rate);
- } else if (battery_state == DKP_SOURCE_STATE_CHARGING) {
- obj->battery_time_to_full = 3600 * ((obj->battery_energy_full - obj->battery_energy) / obj->battery_energy_rate);
- }
- }
- /* check the remaining time is under a set limit, to deal with broken
- primary batteries rate */
- if (obj->battery_time_to_empty > (100 * 60 * 60))
- obj->battery_time_to_empty = -1;
- if (obj->battery_time_to_full > (100 * 60 * 60))
- obj->battery_time_to_full = -1;
-
- /* set the old status */
- source->priv->battery_energy_old = obj->battery_energy;
- g_get_current_time (&source->priv->battery_energy_old_timespec);
-
- /* we changed state */
- if (obj->battery_state != battery_state) {
- source->priv->battery_energy_old = -1;
- obj->battery_state = battery_state;
- }
-
-out:
- /* did anything change? */
- ret = !dkp_object_equal (obj, obj_old);
- if (!just_added && ret)
- dkp_object_diff (obj_old, obj);
- dkp_object_free (obj_old);
-
- /* just for debugging */
- if (just_added)
- dkp_object_print (obj);
-
- /* save new history */
- if (ret) {
- dkp_history_set_state (source->priv->history, obj->battery_state);
- dkp_history_set_charge_data (source->priv->history, obj->battery_percentage);
- dkp_history_set_rate_data (source->priv->history, obj->battery_energy_rate);
- }
-
- g_free (status);
- return ret;
-}
-
-/**
- * dkp_source_poll_battery:
- **/
-static gboolean
-dkp_source_poll_battery (DkpSource *source)
-{
- gboolean ret;
- DkpObject *obj = source->priv->obj;
-
- dkp_debug ("No updates on source %s for 30 seconds; forcing update", obj->native_path);
- source->priv->poll_timer_id = 0;
- ret = dkp_source_update (source);
- if (ret) {
- dkp_source_emit_changed (source);
- }
- return FALSE;
-}
-
-/**
- * dkp_source_update:
- *
- * Return value: TRUE if we changed
- **/
-static gboolean
-dkp_source_update (DkpSource *source)
-{
- gboolean ret;
- GTimeVal time;
- DkpObject *obj = source->priv->obj;
-
- if (source->priv->poll_timer_id > 0) {
- g_source_remove (source->priv->poll_timer_id);
- source->priv->poll_timer_id = 0;
- }
-
- g_get_current_time (&time);
- obj->update_time = time.tv_sec;
-
- switch (source->priv->obj->type) {
- case DKP_SOURCE_TYPE_LINE_POWER:
- ret = dkp_source_update_line_power (source);
- break;
- case DKP_SOURCE_TYPE_BATTERY:
- ret = dkp_source_update_battery (source);
- /* Seems that we don't get change uevents from the
- * kernel on some BIOS types; set up a timer to poll
- * if we are charging or discharging */
- if (obj->battery_state == DKP_SOURCE_STATE_CHARGING ||
- obj->battery_state == DKP_SOURCE_STATE_DISCHARGING)
- source->priv->poll_timer_id = g_timeout_add_seconds (30, (GSourceFunc) dkp_source_poll_battery, source);
- break;
- default:
- g_assert_not_reached ();
- break;
- }
-
- return ret;
-}
-
-#define DKP_DBUS_STRUCT_UINT_DOUBLE_STRING (dbus_g_type_get_struct ("GValueArray", \
- G_TYPE_UINT, G_TYPE_DOUBLE, G_TYPE_STRING, G_TYPE_INVALID))
-
-/**
- * dkp_source_get_statistics:
- **/
-gboolean
-dkp_source_get_statistics (DkpSource *source, const gchar *type, guint timespan, DBusGMethodInvocation *context)
-{
- GError *error;
- GPtrArray *array;
- GPtrArray *complex;
- const DkpHistoryObj *obj;
- GValue *value;
- guint i;
-
- g_return_val_if_fail (DKP_IS_SOURCE (source), FALSE);
- g_return_val_if_fail (type != NULL, FALSE);
-
- /* get the correct data */
- if (strcmp (type, "rate") == 0)
- array = dkp_history_get_rate_data (source->priv->history, timespan);
- else if (strcmp (type, "charge") == 0)
- array = dkp_history_get_charge_data (source->priv->history, timespan);
- else {
- error = g_error_new (DKP_DAEMON_ERROR, DKP_DAEMON_ERROR_GENERAL, "type '%s' not recognised", type);
- dbus_g_method_return_error (context, error);
- goto out;
- }
-
- /* maybe the device doesn't support histories */
- if (array == NULL) {
- error = g_error_new (DKP_DAEMON_ERROR, DKP_DAEMON_ERROR_GENERAL, "device has no history");
- dbus_g_method_return_error (context, error);
- goto out;
- }
-
- /* copy data to dbus struct */
- complex = g_ptr_array_sized_new (array->len);
- for (i=0; i<array->len; i++) {
- obj = (const DkpHistoryObj *) g_ptr_array_index (array, i);
- value = g_new0 (GValue, 1);
- g_value_init (value, DKP_DBUS_STRUCT_UINT_DOUBLE_STRING);
- g_value_take_boxed (value, dbus_g_type_specialized_construct (DKP_DBUS_STRUCT_UINT_DOUBLE_STRING));
- dbus_g_type_struct_set (value, 0, obj->time, 1, obj->value, 2, dkp_source_state_to_text (obj->state), -1);
- g_ptr_array_add (complex, g_value_get_boxed (value));
- g_free (value);
- }
-
- g_ptr_array_free (array, TRUE);
- dbus_g_method_return (context, complex);
-out:
- return TRUE;
-}
-
-/**
- * dkp_source_refresh:
- **/
-gboolean
-dkp_source_refresh (DkpSource *source, DBusGMethodInvocation *context)
-{
- g_return_val_if_fail (DKP_IS_SOURCE (source), FALSE);
-
- dkp_source_update (source);
- dbus_g_method_return (context);
- return TRUE;
-}
diff --git a/src/dkp-source.h b/src/dkp-source.h
deleted file mode 100644
index e32589f..0000000
--- a/src/dkp-source.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2008 David Zeuthen <david@fubar.dk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef __DKP_SOURCE_H__
-#define __DKP_SOURCE_H__
-
-#include <glib-object.h>
-#include <polkit-dbus/polkit-dbus.h>
-#include <devkit-gobject.h>
-
-#include "dkp-daemon.h"
-#include "dkp-device.h"
-
-G_BEGIN_DECLS
-
-#define DKP_SOURCE_TYPE_SOURCE (dkp_source_get_type ())
-#define DKP_SOURCE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DKP_SOURCE_TYPE_SOURCE, DkpSource))
-#define DKP_SOURCE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), DKP_SOURCE_TYPE_SOURCE, DkpSourceClass))
-#define DKP_IS_SOURCE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), DKP_SOURCE_TYPE_SOURCE))
-#define DKP_IS_SOURCE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DKP_SOURCE_TYPE_SOURCE))
-#define DKP_SOURCE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DKP_SOURCE_TYPE_SOURCE, DkpSourceClass))
-
-typedef struct DkpSourcePrivate DkpSourcePrivate;
-
-typedef struct
-{
- DkpDevice parent;
- DkpSourcePrivate *priv;
-} DkpSource;
-
-typedef struct
-{
- DkpDeviceClass parent_class;
-} DkpSourceClass;
-
-typedef enum
-{
- DKP_SOURCE_ERROR_GENERAL,
- DKP_SOURCE_NUM_ERRORS
-} DkpSourceError;
-
-#define DKP_SOURCE_ERROR dkp_source_error_quark ()
-
-GType dkp_source_error_get_type (void);
-#define DKP_SOURCE_TYPE_ERROR (dkp_source_error_get_type ())
-
-GQuark dkp_source_error_quark (void);
-GType dkp_source_get_type (void);
-DkpSource *dkp_source_new (DkpDaemon *daemon,
- DevkitDevice *d);
-
-/* exported methods */
-gboolean dkp_source_refresh (DkpSource *source,
- DBusGMethodInvocation *context);
-gboolean dkp_source_get_statistics (DkpSource *source,
- const gchar *type,
- guint timespan,
- DBusGMethodInvocation *context);
-
-G_END_DECLS
-
-#endif /* __DKP_SOURCE_H__ */
diff --git a/src/dkp-supply.c b/src/dkp-supply.c
new file mode 100644
index 0000000..ff2fae6
--- /dev/null
+++ b/src/dkp-supply.c
@@ -0,0 +1,520 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 David Zeuthen <david@fubar.dk>
+ * Copyright (C) 2008 Richard Hughes <richard@hughsie.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <math.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <glib/gi18n-lib.h>
+#include <glib-object.h>
+#include <devkit-gobject.h>
+
+#include "sysfs-utils.h"
+#include "dkp-debug.h"
+#include "dkp-enum.h"
+#include "dkp-object.h"
+#include "dkp-supply.h"
+#include "dkp-history.h"
+
+#define DK_POWER_MIN_CHARGED_PERCENTAGE 60
+
+struct DkpSupplyPrivate
+{
+ DkpHistory *history;
+ guint poll_timer_id;
+ gboolean has_coldplug_values;
+ gdouble battery_energy_old;
+ GTimeVal battery_energy_old_timespec;
+};
+
+static void dkp_supply_class_init (DkpSupplyClass *klass);
+
+G_DEFINE_TYPE (DkpSupply, dkp_supply, DKP_TYPE_DEVICE)
+#define DKP_SUPPLY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DKP_TYPE_SUPPLY, DkpSupplyPrivate))
+
+static gboolean dkp_supply_refresh (DkpDevice *device);
+
+/**
+ * dkp_supply_refresh_line_power:
+ **/
+static gboolean
+dkp_supply_refresh_line_power (DkpSupply *supply)
+{
+ DkpDevice *device = DKP_DEVICE (supply);
+ DkpObject *obj = dkp_device_get_obj (device);
+
+ /* force true */
+ obj->power_supply = TRUE;
+
+ /* get new AC value */
+ obj->line_power_online = sysfs_get_int (obj->native_path, "online");
+
+ return TRUE;
+}
+
+/**
+ * dkp_supply_reset_values:
+ **/
+static void
+dkp_supply_reset_values (DkpSupply *supply)
+{
+ gchar *native_path;
+ DkpSourceType type;
+ DkpDevice *device = DKP_DEVICE (supply);
+ DkpObject *obj = dkp_device_get_obj (device);
+
+ /* some stuff we copy */
+ type = obj->type;
+ native_path = g_strdup (obj->native_path);
+
+ supply->priv->has_coldplug_values = FALSE;
+ supply->priv->battery_energy_old = -1;
+ supply->priv->battery_energy_old_timespec.tv_sec = 0;
+ dkp_object_clear (obj);
+
+ /* restore the saved stuff */
+ obj->type = type;
+ obj->native_path = native_path;
+}
+
+/**
+ * dkp_supply_get_on_battery:
+ **/
+static gboolean
+dkp_supply_get_on_battery (DkpDevice *device, gboolean *on_battery)
+{
+ DkpSupply *supply = DKP_SUPPLY (device);
+ DkpObject *obj = dkp_device_get_obj (device);
+
+ g_return_val_if_fail (DKP_IS_SUPPLY (supply), FALSE);
+ g_return_val_if_fail (on_battery != NULL, FALSE);
+
+ if (obj->type != DKP_SOURCE_TYPE_BATTERY)
+ return FALSE;
+ if (!obj->battery_is_present)
+ return FALSE;
+
+ *on_battery = (obj->battery_state == DKP_SOURCE_STATE_DISCHARGING);
+ return TRUE;
+}
+
+/**
+ * dkp_supply_get_low_battery:
+ **/
+static gboolean
+dkp_supply_get_low_battery (DkpDevice *device, gboolean *low_battery)
+{
+ gboolean ret;
+ gboolean on_battery;
+ DkpSupply *supply = DKP_SUPPLY (device);
+ DkpObject *obj = dkp_device_get_obj (device);
+
+ g_return_val_if_fail (DKP_IS_SUPPLY (supply), FALSE);
+ g_return_val_if_fail (low_battery != NULL, FALSE);
+
+ /* reuse the common checks */
+ ret = dkp_supply_get_on_battery (device, &on_battery);
+ if (!ret)
+ return FALSE;
+
+ /* shortcut */
+ if (!on_battery) {
+ *low_battery = FALSE;
+ return TRUE;
+ }
+
+ *low_battery = (obj->battery_percentage < 10);
+ return TRUE;
+}
+
+/**
+ * dkp_supply_calculate_battery_rate:
+ **/
+static void
+dkp_supply_calculate_battery_rate (DkpSupply *supply)
+{
+ guint time;
+ gdouble energy;
+ GTimeVal now;
+ DkpDevice *device = DKP_DEVICE (supply);
+ DkpObject *obj = dkp_device_get_obj (device);
+
+ if (obj->battery_energy < 0)
+ return;
+
+ if (supply->priv->battery_energy_old < 0)
+ return;
+
+ if (supply->priv->battery_energy_old == obj->battery_energy)
+ return;
+
+ /* get the time difference */
+ g_get_current_time (&now);
+ time = now.tv_sec - supply->priv->battery_energy_old_timespec.tv_sec;
+
+ if (time == 0)
+ return;
+
+ /* get the difference in charge */
+ energy = supply->priv->battery_energy_old - obj->battery_energy;
+ if (energy < 0.1)
+ return;
+
+ /* probably okay */
+ obj->battery_energy_rate = energy * 3600 / time;
+}
+
+/**
+ * dkp_supply_refresh_battery:
+ *
+ * Return value: TRUE if we changed
+ **/
+static gboolean
+dkp_supply_refresh_battery (DkpSupply *supply)
+{
+ gchar *status = NULL;
+ gboolean ret = TRUE;
+ DkpSourceState battery_state;
+ DkpDevice *device = DKP_DEVICE (supply);
+ DkpObject *obj = dkp_device_get_obj (device);
+
+ /* have we just been removed? */
+ obj->battery_is_present = sysfs_get_bool (obj->native_path, "present");
+ if (!obj->battery_is_present) {
+ dkp_supply_reset_values (supply);
+ obj->type = DKP_SOURCE_TYPE_BATTERY;
+ goto out;
+ }
+
+ /* initial values */
+ if (!supply->priv->has_coldplug_values) {
+ gchar *technology_native;
+
+ /* when we add via sysfs power_supply class then we know this is true */
+ obj->power_supply = TRUE;
+
+ /* the ACPI spec is bad at defining battery type constants */
+ technology_native = g_strstrip (sysfs_get_string (obj->native_path, "technology"));
+ obj->battery_technology = dkp_acpi_to_source_technology (technology_native);
+ g_free (technology_native);
+
+ obj->vendor = g_strstrip (sysfs_get_string (obj->native_path, "manufacturer"));
+ obj->model = g_strstrip (sysfs_get_string (obj->native_path, "model_name"));
+ obj->serial = g_strstrip (sysfs_get_string (obj->native_path, "serial_number"));
+
+ /* assume true for laptops */
+ obj->battery_is_rechargeable = TRUE;
+
+ /* these don't change at runtime */
+ obj->battery_energy_full =
+ sysfs_get_double (obj->native_path, "energy_full") / 1000000.0;
+ obj->battery_energy_full_design =
+ sysfs_get_double (obj->native_path, "energy_full_design") / 1000000.0;
+
+ /* the last full cannot be bigger than the design */
+ if (obj->battery_energy_full > obj->battery_energy_full_design)
+ obj->battery_energy_full = obj->battery_energy_full_design;
+
+ /* calculate how broken our battery is */
+ obj->battery_capacity = obj->battery_energy_full_design / obj->battery_energy_full * 100.0f;
+ if (obj->battery_capacity < 0)
+ obj->battery_capacity = 0;
+ if (obj->battery_capacity > 100.0)
+ obj->battery_capacity = 100.0;
+
+ /* we only coldplug once, as these values will never change */
+ supply->priv->has_coldplug_values = TRUE;
+ }
+
+ status = g_strstrip (sysfs_get_string (obj->native_path, "status"));
+ if (strcasecmp (status, "charging") == 0)
+ battery_state = DKP_SOURCE_STATE_CHARGING;
+ else if (strcasecmp (status, "discharging") == 0)
+ battery_state = DKP_SOURCE_STATE_DISCHARGING;
+ else if (strcasecmp (status, "full") == 0)
+ battery_state = DKP_SOURCE_STATE_FULLY_CHARGED;
+ else if (strcasecmp (status, "empty") == 0)
+ battery_state = DKP_SOURCE_STATE_EMPTY;
+ else {
+ dkp_warning ("unknown status string: %s", status);
+ battery_state = DKP_SOURCE_STATE_UNKNOWN;
+ }
+
+ /* get the currect charge */
+ obj->battery_energy =
+ sysfs_get_double (obj->native_path, "energy_avg") / 1000000.0;
+ if (obj->battery_energy == 0)
+ obj->battery_energy =
+ sysfs_get_double (obj->native_path, "energy_now") / 1000000.0;
+
+ /* some batteries don't update last_full attribute */
+ if (obj->battery_energy > obj->battery_energy_full)
+ obj->battery_energy_full = obj->battery_energy;
+
+ obj->battery_energy_rate =
+ fabs (sysfs_get_double (obj->native_path, "current_now") / 1000000.0);
+
+ /* ACPI gives out the special 'Ones' value for rate when it's unable
+ * to calculate the true rate. We should set the rate zero, and wait
+ * for the BIOS to stabilise. */
+ if (obj->battery_energy_rate == 0xffff)
+ obj->battery_energy_rate = -1;
+
+ /* sanity check to less than 100W */
+ if (obj->battery_energy_rate > 100*1000)
+ obj->battery_energy_rate = -1;
+
+ /* the hardware reporting failed -- try to calculate this */
+ if (obj->battery_energy_rate < 0) {
+ dkp_supply_calculate_battery_rate (supply);
+ }
+
+ /* charging has a negative rate */
+ if (obj->battery_energy_rate > 0 && battery_state == DKP_SOURCE_STATE_CHARGING)
+ obj->battery_energy_rate *= -1.0;
+
+ /* get a precise percentage */
+ obj->battery_percentage = 100.0 * obj->battery_energy / obj->battery_energy_full;
+ if (obj->battery_percentage < 0)
+ obj->battery_percentage = 0;
+ if (obj->battery_percentage > 100.0)
+ obj->battery_percentage = 100.0;
+
+ /* calculate a quick and dirty time remaining value */
+ obj->battery_time_to_empty = -1;
+ obj->battery_time_to_full = -1;
+ if (obj->battery_energy_rate > 0) {
+ if (battery_state == DKP_SOURCE_STATE_DISCHARGING) {
+ obj->battery_time_to_empty = 3600 * (obj->battery_energy / obj->battery_energy_rate);
+ } else if (battery_state == DKP_SOURCE_STATE_CHARGING) {
+ obj->battery_time_to_full = 3600 * ((obj->battery_energy_full - obj->battery_energy) / obj->battery_energy_rate);
+ }
+ }
+ /* check the remaining time is under a set limit, to deal with broken
+ primary batteries rate */
+ if (obj->battery_time_to_empty > (100 * 60 * 60))
+ obj->battery_time_to_empty = -1;
+ if (obj->battery_time_to_full > (100 * 60 * 60))
+ obj->battery_time_to_full = -1;
+
+ /* set the old status */
+ supply->priv->battery_energy_old = obj->battery_energy;
+ g_get_current_time (&supply->priv->battery_energy_old_timespec);
+
+ /* we changed state */
+ if (obj->battery_state != battery_state) {
+ supply->priv->battery_energy_old = -1;
+ obj->battery_state = battery_state;
+ }
+
+out:
+ /* save new history */
+ dkp_history_set_state (supply->priv->history, obj->battery_state);
+ dkp_history_set_charge_data (supply->priv->history, obj->battery_percentage);
+ dkp_history_set_rate_data (supply->priv->history, obj->battery_energy_rate);
+
+ g_free (status);
+ return ret;
+}
+
+/**
+ * dkp_supply_poll_battery:
+ **/
+static gboolean
+dkp_supply_poll_battery (DkpSupply *supply)
+{
+ gboolean ret;
+ DkpDevice *device = DKP_DEVICE (supply);
+ DkpObject *obj = dkp_device_get_obj (device);
+
+ dkp_debug ("No updates on supply %s for 30 seconds; forcing update", obj->native_path);
+ supply->priv->poll_timer_id = 0;
+ ret = dkp_supply_refresh (device);
+ if (ret)
+ dkp_device_emit_changed (device);
+ return FALSE;
+}
+
+/**
+ * dkp_supply_get_stats:
+ **/
+static GPtrArray *
+dkp_supply_get_stats (DkpDevice *device, const gchar *type, guint timespan)
+{
+ DkpSupply *supply = DKP_SUPPLY (device);
+ GPtrArray *array = NULL;
+
+ g_return_val_if_fail (DKP_IS_SUPPLY (supply), FALSE);
+ g_return_val_if_fail (type != NULL, FALSE);
+
+ /* get the correct data */
+ if (strcmp (type, "rate") == 0)
+ array = dkp_history_get_rate_data (supply->priv->history, timespan);
+ else if (strcmp (type, "charge") == 0)
+ array = dkp_history_get_charge_data (supply->priv->history, timespan);
+
+ return array;
+}
+
+/**
+ * dkp_supply_coldplug:
+ **/
+static gboolean
+dkp_supply_coldplug (DkpDevice *device)
+{
+ DkpSupply *supply = DKP_SUPPLY (device);
+ DevkitDevice *d;
+ const gchar *native_path;
+ DkpObject *obj = dkp_device_get_obj (device);
+ gchar *id;
+
+ dkp_supply_reset_values (supply);
+
+ /* detect what kind of device we are */
+ d = dkp_device_get_d (device);
+ if (d == NULL)
+ dkp_error ("could not get device");
+
+ native_path = devkit_device_get_native_path (d);
+ if (native_path == NULL)
+ dkp_error ("could not get native path");
+
+ if (sysfs_file_exists (native_path, "online")) {
+ obj->type = DKP_SOURCE_TYPE_LINE_POWER;
+ } else {
+ /* this is correct, UPS and CSR are not in the kernel */
+ obj->type = DKP_SOURCE_TYPE_BATTERY;
+ }
+
+ /* get the id so we can load the old history */
+ id = dkp_object_get_id (obj);
+ if (id != NULL)
+ dkp_history_set_id (supply->priv->history, id);
+ g_free (id);
+
+ /* coldplug */
+ dkp_supply_refresh (device);
+ return TRUE;
+}
+
+/**
+ * dkp_supply_refresh:
+ **/
+static gboolean
+dkp_supply_refresh (DkpDevice *device)
+{
+ gboolean ret;
+ GTimeVal time;
+ DkpSupply *supply = DKP_SUPPLY (device);
+ DkpObject *obj = dkp_device_get_obj (device);
+
+ if (supply->priv->poll_timer_id > 0) {
+ g_source_remove (supply->priv->poll_timer_id);
+ supply->priv->poll_timer_id = 0;
+ }
+
+ g_get_current_time (&time);
+ obj->update_time = time.tv_sec;
+
+ switch (obj->type) {
+ case DKP_SOURCE_TYPE_LINE_POWER:
+ ret = dkp_supply_refresh_line_power (supply);
+ break;
+ case DKP_SOURCE_TYPE_BATTERY:
+ ret = dkp_supply_refresh_battery (supply);
+ /* Seems that we don't get change uevents from the
+ * kernel on some BIOS types; set up a timer to poll
+ * if we are charging or discharging */
+ if (obj->battery_state == DKP_SOURCE_STATE_CHARGING ||
+ obj->battery_state == DKP_SOURCE_STATE_DISCHARGING)
+ supply->priv->poll_timer_id = g_timeout_add_seconds (30, (GSourceFunc) dkp_supply_poll_battery, supply);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ return ret;
+}
+
+/**
+ * dkp_supply_init:
+ **/
+static void
+dkp_supply_init (DkpSupply *supply)
+{
+ supply->priv = DKP_SUPPLY_GET_PRIVATE (supply);
+ supply->priv->history = dkp_history_new ();
+}
+
+/**
+ * dkp_supply_finalize:
+ **/
+static void
+dkp_supply_finalize (GObject *object)
+{
+ DkpSupply *supply;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (DKP_IS_SUPPLY (object));
+
+ supply = DKP_SUPPLY (object);
+ g_return_if_fail (supply->priv != NULL);
+
+ g_object_unref (supply->priv->history);
+ if (supply->priv->poll_timer_id > 0)
+ g_source_remove (supply->priv->poll_timer_id);
+
+ G_OBJECT_CLASS (dkp_supply_parent_class)->finalize (object);
+}
+
+/**
+ * dkp_supply_class_init:
+ **/
+static void
+dkp_supply_class_init (DkpSupplyClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ DkpDeviceClass *device_class = DKP_DEVICE_CLASS (klass);
+
+ object_class->finalize = dkp_supply_finalize;
+ device_class->get_on_battery = dkp_supply_get_on_battery;
+ device_class->get_low_battery = dkp_supply_get_low_battery;
+ device_class->coldplug = dkp_supply_coldplug;
+ device_class->refresh = dkp_supply_refresh;
+ device_class->get_stats = dkp_supply_get_stats;
+
+ g_type_class_add_private (klass, sizeof (DkpSupplyPrivate));
+}
+
+/**
+ * dkp_supply_new:
+ **/
+DkpSupply *
+dkp_supply_new (void)
+{
+ return g_object_new (DKP_TYPE_SUPPLY, NULL);
+}
+
diff --git a/src/dkp-supply.h b/src/dkp-supply.h
new file mode 100644
index 0000000..1f8c961
--- /dev/null
+++ b/src/dkp-supply.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 David Zeuthen <david@fubar.dk>
+ * Copyright (C) 2008 Richard Hughes <richard@hughsie.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __DKP_SUPPLY_H__
+#define __DKP_SUPPLY_H__
+
+#include <glib-object.h>
+#include "dkp-device.h"
+
+G_BEGIN_DECLS
+
+#define DKP_TYPE_SUPPLY (dkp_supply_get_type ())
+#define DKP_SUPPLY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DKP_TYPE_SUPPLY, DkpSupply))
+#define DKP_SUPPLY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), DKP_TYPE_SUPPLY, DkpSupplyClass))
+#define DKP_IS_SUPPLY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), DKP_TYPE_SUPPLY))
+#define DKP_IS_SUPPLY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DKP_TYPE_SUPPLY))
+#define DKP_SUPPLY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DKP_TYPE_SUPPLY, DkpSupplyClass))
+
+typedef struct DkpSupplyPrivate DkpSupplyPrivate;
+
+typedef struct
+{
+ DkpDevice parent;
+ DkpSupplyPrivate *priv;
+} DkpSupply;
+
+typedef struct
+{
+ DkpDeviceClass parent_class;
+} DkpSupplyClass;
+
+GType dkp_supply_get_type (void);
+DkpSupply *dkp_supply_new (void);
+
+G_END_DECLS
+
+#endif /* __DKP_SUPPLY_H__ */
+
diff --git a/src/org.freedesktop.DeviceKit.Power.Source.xml b/src/org.freedesktop.DeviceKit.Power.Device.xml
index 59e9143..74560f0 100644
--- a/src/org.freedesktop.DeviceKit.Power.Source.xml
+++ b/src/org.freedesktop.DeviceKit.Power.Device.xml
@@ -1,10 +1,10 @@
<!DOCTYPE node PUBLIC
"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd" [
- <!ENTITY ERROR_GENERAL "org.freedesktop.DeviceKit.Power.Source.GeneralError">
+ <!ENTITY ERROR_GENERAL "org.freedesktop.DeviceKit.Power.Device.GeneralError">
]>
<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
- <interface name="org.freedesktop.DeviceKit.Power.Source">
+ <interface name="org.freedesktop.DeviceKit.Power.Device">
<doc:doc>
<doc:description>
<doc:para>
diff --git a/tools/.gitignore b/tools/.gitignore
index 173da61..ea46275 100644
--- a/tools/.gitignore
+++ b/tools/.gitignore
@@ -1,5 +1,6 @@
.deps
devkit-power
+devkit-power-on-battery
*-glue.h
*.o
*-marshal.c
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 6519c57..4c88843 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -30,7 +30,7 @@ dkp-marshal.c: $(top_srcdir)/src/dkp-marshal.list
dkp-daemon-glue.h: $(top_srcdir)/src/org.freedesktop.DeviceKit.Power.xml Makefile.am
dbus-binding-tool --prefix=devkit_power_daemon --mode=glib-client --output=dkp-daemon-glue.h $(top_srcdir)/src/org.freedesktop.DeviceKit.Power.xml
-bin_PROGRAMS = devkit-power devkit-battery-power
+bin_PROGRAMS = devkit-power devkit-power-on-battery
devkit_power_SOURCES = \
dkp-tool.c \
@@ -50,16 +50,16 @@ devkit_power_LDADD = \
$(DEVKIT_POWER_LIBS) \
$(POLKIT_DBUS_LIBS)
-devkit_battery_power_SOURCES = \
+devkit_power_on_battery_SOURCES = \
dkp-battery-power.c \
$(BUILT_SOURCES)
-devkit_battery_power_CPPFLAGS = \
+devkit_power_on_battery_CPPFLAGS = \
-DG_LOG_DOMAIN=\"devkit-power\" \
$(DISABLE_DEPRECATED) \
$(AM_CPPFLAGS)
-devkit_battery_power_LDADD = \
+devkit_power_on_battery_LDADD = \
$(DBUS_GLIB_LIBS) \
$(DEVKIT_POWER_LIBS) \
$(POLKIT_DBUS_LIBS)
diff --git a/tools/dkp-client-device.c b/tools/dkp-client-device.c
index a3effc9..ad4a245 100644
--- a/tools/dkp-client-device.c
+++ b/tools/dkp-client-device.c
@@ -146,7 +146,7 @@ dkp_client_device_set_object_path (DkpClientDevice *device, const gchar *object_
/* connect to the correct path for all the other methods */
proxy_source = dbus_g_proxy_new_for_name (device->priv->bus, "org.freedesktop.DeviceKit.Power",
- object_path, "org.freedesktop.DeviceKit.Power.Source");
+ object_path, "org.freedesktop.DeviceKit.Power.Device");
if (proxy_source == NULL) {
dkp_warning ("Couldn't connect to proxy");
goto out;