+ 0x45,0x31,0x37,0x5F,
};
diff --git a/tools/xenpmd/Makefile b/tools/xenpmd/Makefile
-index 10cb2fb..6881169 100644
+index 10cb2fb..28d51a5 100644
--- a/tools/xenpmd/Makefile
+++ b/tools/xenpmd/Makefile
-@@ -10,6 +10,8 @@ BIN = xenpmd
- .PHONY: all
- all: $(BIN)
+@@ -3,12 +3,17 @@ include $(XEN_ROOT)/tools/Rules.mk
+
+ CFLAGS += -Werror
+ CFLAGS += $(CFLAGS_libxenstore)
++CFLAGS += -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include
+ LDFLAGS += $(LDFLAGS_libxenstore)
++LDFLAGS += -ldbus-glib-1 -ldbus-1 -lpthread -lgobject-2.0 -lglib-2.0 -lintl
-+$(BIN): xenpmd.o acpi-events.o
+ BIN = xenpmd
++GENERATE_HEADERS = xenpmd-dbus-server-bindings.h xenpmd-dbus-client-bindings.h
+
+ .PHONY: all
+-all: $(BIN)
++all: $(GENERATE_HEADERS) $(BIN)
+
++$(BIN): xenpmd.o acpi-events.o xenpmd-dbus-server.o
+
.PHONY: install
install: all
- $(INSTALL_DIR) $(DESTDIR)$(SBINDIR)
-@@ -17,9 +19,8 @@ install: all
+@@ -17,9 +22,15 @@ install: all
.PHONY: clean
clean:
- $(RM) -f $(BIN) $(DEPS)
-+ $(RM) -f $(BIN) *.o
++ $(RM) -f $(BIN) *.o $(GENERATE_HEADERS)
-%: %.c Makefile
+%.o: %.c Makefile
$(CC) $(CFLAGS) $< $(LDFLAGS) -o $@
--include $(DEPS)
++xenpmd-dbus-server-bindings.h:xenpmd.xml
++ dbus-binding-tool --mode=glib-server --prefix=xenpmd_object $< > $@
++
++xenpmd-dbus-client-bindings.h:xenpmd.xml
++ dbus-binding-tool --mode=glib-client $< > $@
++
++
diff --git a/tools/xenpmd/acpi-events.c b/tools/xenpmd/acpi-events.c
new file mode 100644
-index 0000000..d991eb0
+index 0000000..633b560
--- /dev/null
+++ b/tools/xenpmd/acpi-events.c
-@@ -0,0 +1,164 @@
+@@ -0,0 +1,168 @@
+/*
+ * acpi-events.c
+ *
+ write_state_info_in_xenstore(AC_ADAPTER_STATE_FILE_PATH,
+ XS_AC_ADAPTER_STATE_PATH, "off-line", "1", "0");
+ xs_write(xs, XBT_NULL, XS_AC_ADAPTER_EVENT_PATH, "1", 1);
++ xenpmd_dbus_signal_event(E_AC_ADAPTER_STATE_CHANGED);
+}
+
+void handle_lid_state_change(void)
+ write_state_info_in_xenstore(LID_STATE_FILE_PATH, XS_LID_STATE_PATH,
+ "closed", "1", "0");
+ xs_write(xs, XBT_NULL, XS_LID_EVENT_PATH, "1", 1);
++ xenpmd_dbus_signal_event(E_LID_STATE_CHANGED);
+}
+
+void handle_pbtn_pressed_event(void)
+{
+ xenpmd_log(LOG_INFO, "Power button pressed event\n");
+ xs_write(xs, XBT_NULL, XS_PBTN_EVENT_PATH, "1", 1);
++ xenpmd_dbus_signal_event(E_POWER_BUTTON_PRESSED);
+}
+
+void handle_sbtn_pressed_event(void)
+{
+ xenpmd_log(LOG_INFO, "Sleep button pressed event\n");
+ xs_write(xs, XBT_NULL, XS_SBTN_EVENT_PATH, "1", 1);
++ xenpmd_dbus_signal_event(E_SLEEP_BUTTON_PRESSED);
+}
+
+void process_acpi_message(char *acpi_buffer)
+ pthread_cancel(acpi_thread);
+}
+
+diff --git a/tools/xenpmd/xenpmd-dbus-server.c b/tools/xenpmd/xenpmd-dbus-server.c
+new file mode 100644
+index 0000000..c9b80cd
+--- /dev/null
++++ b/tools/xenpmd/xenpmd-dbus-server.c
+@@ -0,0 +1,206 @@
++/*
++ * xenpmd-dbus-server.c
++ *
++ * Put xenpmd on dbus, implement xenpmd dbus methods and
++ * signal power management events.
++ *
++ * Copyright (c) 2009 Citrix Systems, Inc.
++ * Author Kamala Narasimhan <kamala.narasimhan@citrix.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <dbus/dbus.h>
++#include <dbus/dbus-glib.h>
++#include "xenpmd.h"
++
++static char *xenpmd_dbus_signal_names[E_XENPMD_EVENTS_COUNT] =
++{
++ "ac_adapter_state_changed",
++ "lid_state_changed",
++ "power_button_pressed",
++ "sleep_button_pressed",
++ "oem_event_triggered"
++};
++
++typedef struct XenpmdObject
++{
++ GObject parent;
++} XenpmdObject;
++
++typedef struct XenpmdObjectClass
++{
++ GObjectClass parent;
++ guint xenpmd_signal_ids[E_XENPMD_EVENTS_COUNT];
++} XenpmdObjectClass;
++
++static pthread_t xenpmd_dbus_thread;
++static DBusGProxy *bus_proxy;
++static XenpmdObject *xenpmd_obj;
++extern struct xs_handle *xs;
++
++#define XENPMD_TYPE_OBJECT (xenpmd_object_get_type ())
++#define XENPMD_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), XENPMD_TYPE_OBJECT, XenpmdObject))
++#define XENPMD_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), XENPMD_TYPE_OBJECT, XenpmdObjectClass))
++#define XENPMD_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), XENPMD_TYPE_OBJECT))
++#define XENPMD_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XENPMD_TYPE_OBJECT))
++#define XENPMD_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), XENPMD_TYPE_OBJECT, XenpmdObjectClass))
++
++G_DEFINE_TYPE (XenpmdObject, xenpmd_object, G_TYPE_OBJECT);
++
++static void xenpmd_object_init (XenpmdObject * obj) { }
++
++static void xenpmd_object_class_init (XenpmdObjectClass * klass)
++{
++ guint count;
++
++ for (count = 0; count < E_XENPMD_EVENTS_COUNT; count++)
++ klass->xenpmd_signal_ids[count] = g_signal_new(xenpmd_dbus_signal_names[count],
++ G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL,
++ g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
++}
++
++char * xenstore_read_str(char *path)
++{
++ char *buf;
++ unsigned int len;
++
++ buf = xs_read(xs, XBT_NULL, path, &len);
++ return buf;
++}
++
++unsigned int xenstore_read_uint(char *path)
++{
++ char *buf;
++ int ret;
++
++ buf = xenstore_read_str(path);
++ if ( buf == NULL)
++ return 0;
++
++ ret = atoi(buf);
++ free(buf);
++ return ret;
++}
++
++static gboolean xenpmd_object_get_ac_adapter_state(XenpmdObject * this, guint *ac_ret)
++{
++ *ac_ret = xenstore_read_uint(XS_AC_ADAPTER_STATE_PATH);
++ return TRUE;
++}
++
++static gboolean xenpmd_object_get_lid_state(XenpmdObject * this, guint *lid_ret)
++{
++ *lid_ret = xenstore_read_uint(XS_LID_STATE_PATH);
++ return TRUE;
++}
++
++static gboolean xenpmd_object_get_current_temperature(XenpmdObject * this, guint *cur_temp_ret)
++{
++ *cur_temp_ret = xenstore_read_uint(XS_CURRENT_TEMPERATURE);
++ return TRUE;
++}
++
++static gboolean xenpmd_object_get_critical_temperature(XenpmdObject * this, guint *crit_temp_ret)
++{
++ *crit_temp_ret = xenstore_read_uint(XS_CRITICAL_TEMPERATURE);
++ return TRUE;
++}
++
++static gboolean xenpmd_object_get_bif(XenpmdObject * this, char **bif_ret)
++{
++ *bif_ret = xenstore_read_str(XS_BIF);
++ return TRUE;
++}
++
++static gboolean xenpmd_object_get_bst(XenpmdObject * this, char **bst_ret)
++{
++ *bst_ret = xenstore_read_str(XS_BST);
++ return TRUE;
++}
++
++void xenpmd_dbus_signal_event(enum xenpmd_dbus_event_numbers evt_num)
++{
++ XenpmdObjectClass *klass = XENPMD_OBJECT_GET_CLASS(xenpmd_obj);
++ if ( klass == NULL )
++ {
++ xenpmd_log(LOG_ERR, "XenpmdObjectClass instance is NULL!\n");
++ return;
++ }
++
++ g_signal_emit(xenpmd_obj, klass->xenpmd_signal_ids[evt_num],
++ 0, xenpmd_dbus_signal_names[evt_num]);
++}
++
++#include "xenpmd-dbus-server-bindings.h"
++
++static void *xenpmd_dbus_main_thread(void *arg)
++{
++ DBusGConnection *bus;
++ GMainLoop *mainloop;
++ GError *error = NULL;
++ guint request_name_result;
++
++ g_type_init();
++
++ dbus_g_object_type_install_info(XENPMD_TYPE_OBJECT,
++ &dbus_glib_xenpmd_object_object_info);
++ mainloop = g_main_loop_new(NULL, FALSE);
++
++ bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
++ if ( bus == NULL )
++ {
++ xenpmd_log(LOG_ERR, "DBus get system bus failed with %d - %s\n",
++ error->code, error->message);
++ g_error_free(error);
++ g_main_loop_unref(mainloop);
++ return (void *) -1;
++ }
++
++ bus_proxy = dbus_g_proxy_new_for_name(bus, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
++ DBUS_INTERFACE_DBUS);
++ if (dbus_g_proxy_call(bus_proxy, "RequestName", &error,
++ G_TYPE_STRING, "com.citrix.xenclient.xenpmd",
++ G_TYPE_UINT, 0, G_TYPE_INVALID, G_TYPE_UINT,
++ &request_name_result, G_TYPE_INVALID) != TRUE)
++ {
++ xenpmd_log(LOG_ERR,"RequestName failed with error - %d - %s\n",
++ error->code, error->message);
++ g_error_free(error);
++ dbus_g_connection_unref(bus);
++ g_main_loop_unref(mainloop);
++ return (void *) -1;
++ }
++
++ xenpmd_obj = g_object_new(XENPMD_TYPE_OBJECT, NULL);
++ dbus_g_connection_register_g_object(bus,
++ "/com/citrix/xenclient/xenpmd/XenpmdObject",
++ G_OBJECT(xenpmd_obj));
++
++ g_main_loop_run(mainloop);
++
++ return 0;
++}
++
++void xenpmd_dbus_initialize(void)
++{
++ pthread_create(&xenpmd_dbus_thread, NULL, &xenpmd_dbus_main_thread, NULL);
++}
++
++void xenpmd_dbus_cleanup(void)
++{
++ pthread_cancel(xenpmd_dbus_thread);
++}
++
diff --git a/tools/xenpmd/xenpmd.c b/tools/xenpmd/xenpmd.c
-index 28de744..ff6d39d 100644
+index 28de744..7fffcf7 100644
--- a/tools/xenpmd/xenpmd.c
+++ b/tools/xenpmd/xenpmd.c
@@ -33,68 +33,10 @@
void write_ulong_lsb_first(char *temp_val, unsigned long val)
{
+@@ -370,7 +324,7 @@ void write_battery_info_to_xenstore(struct battery_info *info)
+ (unsigned int)strlen(info->battery_type), info->battery_type,
+ (unsigned int)strlen(info->oem_info), info->oem_info);
+ strncat(val+73, string_info, 1024-73-1);
+- xs_write(xs, XBT_NULL, "/pm/bif",
++ xs_write(xs, XBT_NULL, XS_BIF,
+ val, 73+8+strlen(info->model_number)+strlen(info->serial_number)+
+ strlen(info->battery_type)+strlen(info->oem_info)+1);
+ }
@@ -383,16 +337,21 @@ int write_one_time_battery_info(void)
dir = opendir(BATTERY_DIR_PATH);
void write_battery_status_to_xenstore(struct battery_status *status)
{
-@@ -427,55 +387,78 @@ void write_battery_status_to_xenstore(struct battery_status *status)
+@@ -426,56 +386,79 @@ void write_battery_status_to_xenstore(struct battery_status *status)
+ write_ulong_lsb_first(val+18, status->remaining_capacity);
write_ulong_lsb_first(val+26, status->present_voltage);
- xs_write(xs, XBT_NULL, "/pm/bst", val, 35);
+- xs_write(xs, XBT_NULL, "/pm/bst", val, 35);
++ xs_write(xs, XBT_NULL, XS_BST, val, 35);
+#ifdef XENPMD_DEBUG
+ xenpmd_log(LOG_DEBUG, "Updated battery information in xenstore\n");
+#endif
if ( pid != 0 )
exit(0);
-@@ -483,34 +466,73 @@ static void daemonize(void)
+@@ -483,34 +466,75 @@ static void daemonize(void)
setsid();
if ( (pid = fork()) < 0 )
- if ( write_one_time_battery_info() == 0 )
+ initialize_system_state_info();
++ xenpmd_dbus_initialize();
+ monitor_acpi_events();
+ if ( write_one_time_battery_info() == 0 )
{
- wait_for_and_update_battery_status_request();
+ wait_for_and_update_power_mgmt_info();
+ acpi_events_cleanup();
++ xenpmd_dbus_cleanup();
xs_daemon_close(xs);
- return 0;
+ closelog();
+}
diff --git a/tools/xenpmd/xenpmd.h b/tools/xenpmd/xenpmd.h
new file mode 100644
-index 0000000..211e847
+index 0000000..b3dddac
--- /dev/null
+++ b/tools/xenpmd/xenpmd.h
-@@ -0,0 +1,115 @@
+@@ -0,0 +1,130 @@
+/*
+ * xenpmd.h
+ *
+void monitor_acpi_events(void);
+void acpi_events_cleanup(void);
+
++enum xenpmd_dbus_event_numbers
++{
++ E_AC_ADAPTER_STATE_CHANGED,
++ E_LID_STATE_CHANGED,
++ E_POWER_BUTTON_PRESSED,
++ E_SLEEP_BUTTON_PRESSED,
++ E_XENPMD_EVENTS_COUNT
++};
++
++void xenpmd_dbus_initialize(void);
++void xenpmd_dbus_cleanup(void);
++void xenpmd_dbus_signal_event(enum xenpmd_dbus_event_numbers evt_num);
++
+#ifdef RUN_IN_SIMULATE_MODE
+ #define BATTERY_DIR_PATH "/tmp/battery"
+ #define BATTERY_INFO_FILE_PATH "/tmp/battery/%s/info"
+#define LID_STATE_FILE_PATH "/proc/acpi/button/lid/LID/state"
+#define ACPID_SOCKET_PATH "/var/run/acpid.socket"
+
++#define XS_BIF "/pm/bif"
++#define XS_BST "/pm/bst"
+#define XS_AC_ADAPTER_STATE_PATH "/pm/ac_adapter"
+#define XS_LID_STATE_PATH "/pm/lid_state"
+
+ #define xenpmd_log(priority, format, p...) printf(format, ##p)
+#endif
+
+diff --git a/tools/xenpmd/xenpmd.xml b/tools/xenpmd/xenpmd.xml
+new file mode 100644
+index 0000000..23328f4
+--- /dev/null
++++ b/tools/xenpmd/xenpmd.xml
+@@ -0,0 +1,127 @@
++<?xml version="1.0" encoding="UTF-8" ?>
++
++<node name="/com/citrix/xenclient/xenpmd">
++
++ <interface name="com.citrix.xenclient.xenpmd.power_mgmt_interface">
++
++ <method name="get_ac_adapter_state">
++ <arg type="u" name="ac_ret" direction="out" />
++ <doc:doc>
++ <doc:summary>
++ <doc:para>
++ Returns AC adapter state. A value of 1 means AC adapter in use.
++ Otherwise, zero.
++ </doc:para>
++ </doc:summary>
++ </doc:doc>
++ </method>
++
++ <method name="get_lid_state">
++ <arg type="u" name="lid_ret" direction="out" />
++ <doc:doc>
++ <doc:summary>
++ <doc:para>
++ Returns lid state. A value of one indicates lid is open otherwise closed.
++ </doc:para>
++ </doc:summary>
++ </doc:doc>
++
++ </method>
++
++ <method name="get_current_temperature">
++ <arg type="u" name="cur_temp_ret" direction="out" />
++ <doc:doc>
++ <doc:summary>
++ <doc:para>
++ Returns current platform temperature.
++ </doc:para>
++ </doc:summary>
++ </doc:doc>
++ </method>
++
++ <method name="get_critical_temperature">
++ <arg type="u" name="crit_temp_ret" direction="out" />
++ <doc:doc>
++ <doc:summary>
++ <doc:para>
++ Returns current critical platform temperature.
++ </doc:para>
++ </doc:summary>
++ </doc:doc>
++ </method>
++
++ <method name="get_bif">
++ <arg type="s" name="bif_ret" direction="out" />
++ <doc:doc>
++ <doc:summary>
++ <doc:para>
++ Returns battery information as string.
++ </doc:para>
++ </doc:summary>
++ </doc:doc>
++ </method>
++
++ <method name="get_bst">
++ <arg type="s" name="bst_ret" direction="out" />
++ <doc:doc>
++ <doc:summary>
++ <doc:para>
++ Returns battery status as string.
++ </doc:para>
++ </doc:summary>
++ </doc:doc>
++ </method>
++
++ <signal name="ac_adapter_state_changed">
++ <doc:doc>
++ <doc:summary>
++ <doc:para>
++ Signals change in platform AC adapter status.
++ </doc:para>
++ </doc:summary>
++ </doc:doc>
++ </signal>
++
++ <signal name="lid_state_changed">
++ <doc:doc>
++ <doc:summary>
++ <doc:para>
++ Signals when a laptop lid is opened or closed.
++ </doc:para>
++ </doc:summary>
++ </doc:doc>
++ </signal>
++
++ <signal name="power_button_pressed">
++ <doc:doc>
++ <doc:summary>
++ <doc:para>
++ Signals when power button is pressed.
++ </doc:para>
++ </doc:summary>
++ </doc:doc>
++ </signal>
++
++ <signal name="sleep_button_pressed">
++ <doc:doc>
++ <doc:summary>
++ <doc:para>
++ Signals when sleep button is pressed.
++ </doc:para>
++ </doc:summary>
++ </doc:doc>
++ </signal>
++
++ <signal name="oem_event_triggered">
++ <doc:doc>
++ <doc:summary>
++ <doc:para>
++ Signals when OEM special buttons/hotkeys are pressed.
++ </doc:para>
++ </doc:summary>
++ </doc:doc>
++ </signal>
++
++ </interface>
++
++</node>