summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rw-r--r--COPYING353
-rw-r--r--HACKING93
-rw-r--r--Makefile.am39
-rw-r--r--NEWS2
-rw-r--r--README2
-rw-r--r--acinclude.m451
-rwxr-xr-xautogen.sh95
-rw-r--r--configure.in165
-rw-r--r--doc/Makefile.am81
-rw-r--r--doc/TODO34
-rw-r--r--doc/dbus/Makefile.am15
-rw-r--r--doc/dbus/dbus-introspect-docs.dtd32
-rw-r--r--doc/dbus/spec-to-docbook.xsl543
-rw-r--r--doc/devkit-power-docs.xml94
-rw-r--r--doc/man/DeviceKit-power.xml64
-rw-r--r--doc/man/Makefile.am24
-rw-r--r--doc/man/devkit-power-daemon.xml84
-rw-r--r--doc/man/devkit-power.xml99
-rw-r--r--doc/version.xml1
-rw-r--r--gtk-doc.make159
-rwxr-xr-xmkinstalldirs111
-rw-r--r--po/ChangeLog0
-rw-r--r--po/LINGUAS4
-rw-r--r--po/POTFILES.in4
-rw-r--r--policy/Makefile.am17
-rw-r--r--policy/org.freedesktop.devicekit.power.policy.in32
-rw-r--r--src/Makefile.am82
-rw-r--r--src/devkit-power-daemon.c631
-rw-r--r--src/devkit-power-daemon.h84
-rw-r--r--src/devkit-power-device.c92
-rw-r--r--src/devkit-power-device.h68
-rw-r--r--src/devkit-power-marshal.list2
-rw-r--r--src/devkit-power-source.c593
-rw-r--r--src/devkit-power-source.h64
-rw-r--r--src/main.c157
-rw-r--r--src/org.freedesktop.DeviceKit.Power.Source.xml228
-rw-r--r--src/org.freedesktop.DeviceKit.Power.xml77
-rw-r--r--src/sysfs-utils.c203
-rw-r--r--src/sysfs-utils.h36
-rw-r--r--tools/Makefile.am49
-rw-r--r--tools/devkit-power.c376
42 files changed, 4941 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..c686966
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+David Zeuthen <davidz@redhat.com>
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..451efcd
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,353 @@
+Copyright (C) 2008 David Zeuthen <david@fubar.dk>
+All Rights Reserved.
+
+The DeviceKit-power source code is licensed to you under the GNU
+General Public License. Either version 2 of the License, or (at your
+option) any later version. The license is included below.
+
+-- BEGIN GPLv2+ License ---
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+-- END GPLv2+ License ---
+
diff --git a/HACKING b/HACKING
new file mode 100644
index 0000000..8d32cc0
--- /dev/null
+++ b/HACKING
@@ -0,0 +1,93 @@
+SCM
+===
+
+ - anonymous checkouts
+
+ $ git clone git://git.freedesktop.org/git/DeviceKit-disks.git
+
+ - checkouts if you got an ssh account on fd.o (username@ is optional)
+
+ $ git clone ssh://[username@]git.freedesktop.org/git/DeviceKit-disks.git
+
+ - commit to local repository
+
+ $ git commit -a
+
+ - push local repository to master repository at fd.o (remember most patches
+ requires review at the mailing list)
+
+ $ git push
+
+ - pull changes from master repository at fd.o
+
+ $ git pull
+
+ - diff of working tree versus local repository
+
+ $ git diff
+
+ - diff of local repository vs. master repository at fd.o
+
+ synchronize with upstream repo:
+ $ git pull
+
+ (possibly merge changes)
+
+ generate the diff:
+ $ git diff origin HEAD
+
+ - influential environment variables (set these in e.g. .bash_profile)
+
+ export GIT_AUTHOR_NAME='Your Full Name'
+ export GIT_COMMITTER_NAME='Your Full Name'
+ export GIT_COMMITTER_EMAIL=youremail@domain.net
+ export GIT_AUTHOR_EMAIL=youremail@domain.net
+
+ - see also
+
+ http://www.kernel.org/pub/software/scm/git/docs/
+
+
+Committing code
+===
+
+ - Commit messages should be of the form (the five lines between the
+ lines starting with ===)
+
+=== begin example commit ===
+short explanation of the commit
+
+Longer explanation explaining exactly what's changed, whether any
+external or private interfaces changed, what bugs were fixed (with bug
+tracker reference if applicable) and so forth. Be concise but not too brief.
+=== end example commit ===
+
+ - Always add a brief description of the commit to the _first_ line of
+ the commit and terminate by two newlines (it will work without the
+ second newline, but that is not nice for the interfaces).
+
+ - First line (the brief description) must only be one sentence and
+ must not start with a capital letter. Don't use a trailing period
+ either.
+
+ - The main description (the body) is normal prose and should use normal
+ punctuation and capital letters where appropriate. Normally, for patches
+ sent to a mailing list it's copied from there.
+
+ - When committing code on behalf of others use the --author option, e.g.
+ git commit -a --author "Joe Coder <joe@coder.org>"
+
+Coding Style
+===
+
+ - Please follow the coding style already used.
+
+ - Write docs for all functions and structs and so on. We use gtkdoc format.
+
+ - All external interfaces (network protocols, file formats, etc.)
+ should have documented specifications sufficient to allow an
+ alternative implementation to be written. Our implementation should
+ be strict about specification compliance (should not for example
+ heuristically parse a file and accept not-well-formed
+ data). Avoiding heuristics is also important for security reasons;
+ if it looks funny, ignore it (or exit, or disconnect).
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..34fc235
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,39 @@
+## Process this file with automake to produce Makefile.in
+
+SUBDIRS = src doc tools policy po
+
+# Creating ChangeLog from git log (taken from cairo/Makefile.am):
+ChangeLog: $(srcdir)/ChangeLog
+
+$(srcdir)/ChangeLog:
+ @if test -d "$(srcdir)/.git"; then \
+ (cd "$(srcdir)" && \
+ ./missing --run git-log --stat) | fmt --split-only > $@.tmp \
+ && mv -f $@.tmp $@ \
+ || ($(RM) $@.tmp; \
+ echo Failed to generate ChangeLog, your ChangeLog may be outdated >&2; \
+ (test -f $@ || echo git-log is required to generate this file >> $@)); \
+ else \
+ test -f $@ || \
+ (echo A git checkout and git-log is required to generate ChangeLog >&2 && \
+ echo A git checkout and git-log is required to generate this file >> $@); \
+ fi
+
+EXTRA_DIST = \
+ HACKING \
+ mkinstalldirs \
+ ChangeLog \
+ intltool-extract.in \
+ intltool-merge.in \
+ intltool-update.in
+
+DISTCLEANFILES = \
+ intltool-extract \
+ intltool-merge \
+ intltool-update
+
+# xsltproc barfs on 'make distcheck'; disable for now
+DISTCHECK_CONFIGURE_FLAGS=--disable-man-pages --disable-gtk-doc
+
+clean-local :
+ rm -f *~
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..1eb76e2
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,2 @@
+TODO: for now see doc/TODO
+
diff --git a/README b/README
new file mode 100644
index 0000000..6921cea
--- /dev/null
+++ b/README
@@ -0,0 +1,2 @@
+
+TODO
diff --git a/acinclude.m4 b/acinclude.m4
new file mode 100644
index 0000000..18fa66a
--- /dev/null
+++ b/acinclude.m4
@@ -0,0 +1,51 @@
+dnl GTK_DOC_CHECK borrowed from cairo, thanks!
+
+dnl Usage:
+dnl GTK_DOC_CHECK([minimum-gtk-doc-version])
+AC_DEFUN([GTK_DOC_CHECK],
+[
+ AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first
+ AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first
+ dnl for overriding the documentation installation directory
+ AC_ARG_WITH(html-dir,
+ AC_HELP_STRING([--with-html-dir=PATH], [path to installed docs]),,
+ [with_html_dir='${datadir}/gtk-doc/html'])
+ HTML_DIR="$with_html_dir"
+ AC_SUBST(HTML_DIR)
+
+ dnl enable/disable documentation building
+ AC_ARG_ENABLE(gtk-doc,
+ AC_HELP_STRING([--enable-gtk-doc],
+ [use gtk-doc to build documentation [default=yes]]),,
+ enable_gtk_doc=yes)
+
+ have_gtk_doc=no
+ if test x$enable_gtk_doc = xyes; then
+ if test -z "$PKG_CONFIG"; then
+ AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+ fi
+ if test "$PKG_CONFIG" != "no" && $PKG_CONFIG --exists gtk-doc; then
+ have_gtk_doc=yes
+ fi
+
+ dnl do we want to do a version check?
+ifelse([$1],[],,
+ [gtk_doc_min_version=$1
+ if test "$have_gtk_doc" = yes; then
+ AC_MSG_CHECKING([gtk-doc version >= $gtk_doc_min_version])
+ if $PKG_CONFIG --atleast-version $gtk_doc_min_version gtk-doc; then
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ have_gtk_doc=no
+ fi
+ fi
+])
+ if test "$have_gtk_doc" != yes; then
+ enable_gtk_doc=no
+ fi
+ fi
+
+ AM_CONDITIONAL(ENABLE_GTK_DOC, test x$enable_gtk_doc = xyes)
+ AM_CONDITIONAL(GTK_DOC_USE_LIBTOOL, test -n "$LIBTOOL")
+])
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..05b1526
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,95 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+DIE=0
+
+(test -f $srcdir/configure.in) || {
+ echo -n "**Error**: Directory $srcdir does not look like the"
+ echo " top-level package directory"
+ exit 1
+}
+
+(autoconf --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "**Error**: You must have autoconf installed."
+ echo "Download the appropriate package for your distribution,"
+ echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
+ DIE=1
+}
+
+(grep "^AM_PROG_LIBTOOL" $srcdir/configure.in >/dev/null) && {
+ (libtool --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "**Error**: You must have libtool installed."
+ echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/"
+ DIE=1
+ }
+}
+
+(automake --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "**Error**: You must have automake installed."
+ echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/"
+ DIE=1
+ NO_AUTOMAKE=yes
+}
+
+
+# if no automake, don't bother testing for aclocal
+test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "**Error**: Missing aclocal. The version of automake"
+ echo "installed doesn't appear recent enough."
+ echo "You can get automake from ftp://ftp.gnu.org/pub/gnu/"
+ DIE=1
+}
+
+if test "$DIE" -eq 1; then
+ exit 1
+fi
+
+if test -z "$*"; then
+ echo "**Warning**: I am going to run configure with no arguments."
+ echo "If you wish to pass any to it, please specify them on the"
+ echo $0 " command line."
+ echo
+fi
+
+case $CC in
+xlc )
+ am_opt=--include-deps;;
+esac
+
+ aclocalinclude="$ACLOCAL_FLAGS"
+
+ if grep "^AM_PROG_LIBTOOL" configure.in >/dev/null; then
+ if test -z "$NO_LIBTOOLIZE" ; then
+ echo "Running libtoolize..."
+ libtoolize --force --copy
+ fi
+ fi
+ echo "Running aclocal $aclocalinclude ..."
+ aclocal $aclocalinclude
+ if grep "^AM_CONFIG_HEADER" configure.in >/dev/null; then
+ echo "Running autoheader..."
+ autoheader
+ fi
+ echo "Running automake --gnu -Wno-portability $am_opt ..."
+ automake --add-missing --gnu -Wno-portability $am_opt
+ echo "Running autoconf ..."
+ autoconf
+
+intltoolize --copy --force --automake || exit 1
+
+conf_flags="--enable-maintainer-mode --enable-gtk-doc"
+
+if test x$NOCONFIGURE = x; then
+ echo "Running $srcdir/configure $conf_flags $@ ..."
+ $srcdir/configure $conf_flags "$@" \
+ && echo "Now type make to compile." || exit 1
+else
+ echo "Skipping configure process."
+fi
diff --git a/configure.in b/configure.in
new file mode 100644
index 0000000..f027f8e
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,165 @@
+dnl Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.59c)
+AC_INIT(DeviceKit-power, 001, david@fubar.dk)
+AM_INIT_AUTOMAKE(DeviceKit-power, 001)
+AM_CONFIG_HEADER(config.h)
+AM_MAINTAINER_MODE
+
+AC_ISC_POSIX
+AC_PROG_CC
+AM_PROG_CC_STDC
+AC_HEADER_STDC
+AM_PROG_LIBTOOL
+AC_PROG_MAKE_SET
+AC_PROG_LN_S
+AC_SYS_LARGEFILE
+AM_PROG_CC_C_O
+
+# Taken from dbus
+AC_ARG_ENABLE(ansi, [ --enable-ansi enable -ansi -pedantic gcc flags],enable_ansi=$enableval,enable_ansi=no)
+AC_ARG_ENABLE(verbose-mode, [ --enable-verbose-mode support verbose debug mode],enable_verbose_mode=$enableval,enable_verbose_mode=$USE_MAINTAINER_MODE)
+AC_ARG_ENABLE(man-pages, [ --enable-man-pages build manual pages],enable_man_pages=$enableval,enable_man_pages=yes)
+
+if test "${enable_man_page}" != no; then
+dnl
+dnl Check for xsltproc
+dnl
+AC_PATH_PROG([XSLTPROC], [xsltproc])
+ if test -z "$XSLTPROC"; then
+ enable_man_pages=no
+ fi
+fi
+AM_CONDITIONAL(MAN_PAGES_ENABLED, test x$enable_man_pages = xyes)
+
+GTK_DOC_CHECK([1.3])
+
+#### gcc warning flags
+
+if test "x$GCC" = "xyes"; then
+ changequote(,)dnl
+ case " $CFLAGS " in
+ *[\ \ ]-Wall[\ \ ]*) ;;
+ *) CFLAGS="$CFLAGS -Wall" ;;
+ esac
+
+ case " $CFLAGS " in
+ *[\ \ ]-Wchar-subscripts[\ \ ]*) ;;
+ *) CFLAGS="$CFLAGS -Wchar-subscripts" ;;
+ esac
+
+ case " $CFLAGS " in
+ *[\ \ ]-Wmissing-declarations[\ \ ]*) ;;
+ *) CFLAGS="$CFLAGS -Wmissing-declarations" ;;
+ esac
+
+ case " $CFLAGS " in
+ *[\ \ ]-Wnested-externs[\ \ ]*) ;;
+ *) CFLAGS="$CFLAGS -Wnested-externs" ;;
+ esac
+
+ case " $CFLAGS " in
+ *[\ \ ]-Wpointer-arith[\ \ ]*) ;;
+ *) CFLAGS="$CFLAGS -Wpointer-arith" ;;
+ esac
+
+ case " $CFLAGS " in
+ *[\ \ ]-Wcast-align[\ \ ]*) ;;
+ *) CFLAGS="$CFLAGS -Wcast-align" ;;
+ esac
+
+ case " $CFLAGS " in
+ *[\ \ ]-Wsign-compare[\ \ ]*) ;;
+ *) CFLAGS="$CFLAGS -Wsign-compare" ;;
+ esac
+
+ if test "x$enable_ansi" = "xyes"; then
+ case " $CFLAGS " in
+ *[\ \ ]-ansi[\ \ ]*) ;;
+ *) CFLAGS="$CFLAGS -ansi" ;;
+ esac
+
+ case " $CFLAGS " in
+ *[\ \ ]-D_POSIX_C_SOURCE*) ;;
+ *) CFLAGS="$CFLAGS -D_POSIX_C_SOURCE=199309L" ;;
+ esac
+
+ case " $CFLAGS " in
+ *[\ \ ]-D_BSD_SOURCE[\ \ ]*) ;;
+ *) CFLAGS="$CFLAGS -D_BSD_SOURCE" ;;
+ esac
+
+ case " $CFLAGS " in
+ *[\ \ ]-pedantic[\ \ ]*) ;;
+ *) CFLAGS="$CFLAGS -pedantic" ;;
+ esac
+ fi
+ changequote([,])dnl
+fi
+
+PKG_CHECK_MODULES(DEVKIT, [devkit-gobject >= 002])
+AC_SUBST(DEVKIT_GOBJECT_CFLAGS)
+AC_SUBST(DEVKIT_GOBJECT_LIBS)
+
+PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.6.0])
+AC_SUBST(GLIB_CFLAGS)
+AC_SUBST(GLIB_LIBS)
+
+PKG_CHECK_MODULES(DBUS, [dbus-1 >= 1.0])
+AC_SUBST(DBUS_CFLAGS)
+AC_SUBST(DBUS_LIBS)
+
+PKG_CHECK_MODULES(DBUS_GLIB, [dbus-glib-1 >= 0.74])
+AC_SUBST(DBUS_GLIB_CFLAGS)
+AC_SUBST(DBUS_GLIB_LIBS)
+
+PKG_CHECK_MODULES(POLKIT_DBUS, [polkit-dbus >= 0.7])
+AC_SUBST(POLKIT_DBUS_CFLAGS)
+AC_SUBST(POLKIT_DBUS_LIBS)
+
+if test "x$GCC" = "xyes"; then
+ LDFLAGS="-Wl,--as-needed $LDFLAGS"
+fi
+
+IT_PROG_INTLTOOL([0.36.0])
+GETTEXT_PACKAGE=DeviceKit-power
+AC_SUBST([GETTEXT_PACKAGE])
+AM_GLIB_GNU_GETTEXT
+AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE],["$GETTEXT_PACKAGE"],[gettext domain])
+
+AC_OUTPUT([
+Makefile
+src/Makefile
+tools/Makefile
+doc/Makefile
+doc/version.xml
+doc/man/Makefile
+doc/dbus/Makefile
+policy/Makefile
+po/Makefile.in
+])
+
+dnl ==========================================================================
+echo "
+ DeviceKit-power $VERSION
+ =======================
+
+ prefix: ${prefix}
+ libdir: ${libdir}
+ libexecdir: ${libexecdir}
+ bindir: ${bindir}
+ sbindir: ${sbindir}
+ datadir: ${datadir}
+ sysconfdir: ${sysconfdir}
+ localstatedir: ${localstatedir}
+ docdir: ${docdir}
+
+ compiler: ${CC}
+ cflags: ${CFLAGS}
+ cppflags: ${CPPFLAGS}
+ xsltproc: ${XSLTPROC}
+
+ Maintainer mode: ${USE_MAINTAINER_MODE}
+ Building api docs: ${enable_gtk_doc}
+ Building man pages: ${enable_man_pages}
+"
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644
index 0000000..9953167
--- /dev/null
+++ b/doc/Makefile.am
@@ -0,0 +1,81 @@
+
+SUBDIRS = man dbus
+
+NULL =
+
+AUTOMAKE_OPTIONS = 1.7
+
+# The name of the module.
+DOC_MODULE=devkit-power
+
+# The top-level SGML file.
+DOC_MAIN_SGML_FILE=devkit-power-docs.xml
+
+# Extra options to supply to gtkdoc-scan
+SCAN_OPTIONS=--ignore-headers=config.h
+
+# The directory containing the source code. Relative to $(srcdir)
+DOC_SOURCE_DIR=../policy
+
+# Used for dependencies
+HFILE_GLOB=
+#$(top_srcdir)/policy/*.h
+CFILE_GLOB=
+#$(top_srcdir)/policy/*.c
+
+# Headers to ignore
+IGNORE_HFILES= \
+ $(NULL)
+
+# CFLAGS and LDFLAGS for compiling scan program. Only needed
+# if $(DOC_MODULE).types is non-empty.
+INCLUDES = \
+ $(DBUS_GLIB_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ -I$(top_srcdir)/policy \
+ -I$(top_builddir)/policy \
+ $(NULL)
+
+GTKDOC_LIBS = \
+ $(DBUS_GLIB_LIBS) \
+ $(NULL)
+
+# Extra options to supply to gtkdoc-mkdb
+MKDB_OPTIONS=--sgml-mode --output-format=xml
+
+# Extra options to supply to gtkdoc-mktmpl
+MKTMPL_OPTIONS=
+
+# Non-autogenerated SGML files to be included in $(DOC_MAIN_SGML_FILE)
+content_files = \
+ version.xml \
+ man/devkit-power.xml \
+ man/devkit-power-daemon.xml \
+ man/DeviceKit-power.xml \
+ dbus/org.freedesktop.DeviceKit.Power.ref.xml \
+ dbus/org.freedesktop.DeviceKit.Power.Source.ref.xml \
+ $(NULL)
+
+# Images to copy into HTML directory
+HTML_IMAGES = \
+ $(NULL)
+
+# Extra options to supply to gtkdoc-fixref
+FIXXREF_OPTIONS=
+
+MAINTAINERCLEANFILES = \
+ *~ \
+ Makefile.in \
+ devkit-power.types \
+ devkit-power-*.txt \
+ $(NULL)
+
+if ENABLE_GTK_DOC
+include $(top_srcdir)/gtk-doc.make
+else
+EXTRA_DIST =
+endif
+
+# Version information for marking the documentation
+EXTRA_DIST += version.xml.in
+
diff --git a/doc/TODO b/doc/TODO
new file mode 100644
index 0000000..3eb289a
--- /dev/null
+++ b/doc/TODO
@@ -0,0 +1,34 @@
+
+------------------------------------------------------------------------
+- Current dependencies
+------------------------------------------------------------------------
+
+ - DeviceKit from git
+ - http://gitweb.freedesktop.org/?p=users/david/DeviceKit.git
+ - http://people.freedesktop.org/~david/DK/F9/src/DeviceKit-002-0.git20080506.fc9.src.rpm
+
+ - D-Bus GLib 0.74 with some patches
+ - necessary changes are already committed upstream
+ - See Fedora 9 / Rawhide package for the patches needed
+
+ - PolicyKit >= 0.8
+
+ - D-Bus >= 1.1.20
+
+------------------------------------------------------------------------
+- TODO List (TODO: this section is incomplete)
+------------------------------------------------------------------------
+
+Before (next) release:
+
+ - General project management tasks
+ - review licenses, NEWS, TODO, HACKING etc. file
+
+------------------------------------------------------------------------
+- Current features (TODO: this section is incomplete)
+------------------------------------------------------------------------
+
+------------------------------------------------------------------------
+- Future features (TODO: this section is incomplete)
+------------------------------------------------------------------------
+
diff --git a/doc/dbus/Makefile.am b/doc/dbus/Makefile.am
new file mode 100644
index 0000000..d2685f4
--- /dev/null
+++ b/doc/dbus/Makefile.am
@@ -0,0 +1,15 @@
+
+all : org.freedesktop.DeviceKit.Power.ref.xml org.freedesktop.DeviceKit.Power.Source.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
+ 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 >> $@
+
+EXTRA_DIST = spec-to-docbook.xsl dbus-introspect-docs.dtd
+
+clean-local :
+ rm -f *~ *.ref.xml
diff --git a/doc/dbus/dbus-introspect-docs.dtd b/doc/dbus/dbus-introspect-docs.dtd
new file mode 100644
index 0000000..ca918fb
--- /dev/null
+++ b/doc/dbus/dbus-introspect-docs.dtd
@@ -0,0 +1,32 @@
+<!-- DTD for D-Bus Introspection Documentation -->
+
+<!ELEMENT doc (summary?,description?,errors?,permission?,since?,deprecated,seealso?)>
+
+<!ELEMENT summary (#PCDATA|ref)*>
+<!ELEMENT description (#PCDATA|para|example)*>
+<!ELEMENT errors (error)*>
+<!ELEMENT permission (#PCDATA|ref|para)*>
+<!ELEMENT since EMPTY>
+<!ATTLIST since version CDATA #REQUIRED>
+<!ELEMENT deprecated (#PCDATA|ref)>
+<!ATTLIST deprecated version CDATA #REQUIRED>
+<!ATTLIST deprecated instead CDATA #REQUIRED>
+<!ELEMENT seealso (ref+)>
+
+<!ELEMENT error (#PCDATA|para)*>
+<!ATTLIST error name CDATA #REQUIRED>
+<!ELEMENT para (#PCDATA|example|code|list|ref)*>
+<!ELEMENT example (#PCDATA|para|code|ref)*>
+<!ATTLIST language (c|glib|python|shell) #REQUIRED>
+<!ATTLIST title CDATA #IMPLIED>
+<!ELEMENT list (item*)>
+<!ATTLIST list type (bullet|number) #REQUIRED>
+<!ELEMENT item (term|definition)*>
+<!ELEMENT term (#PCDATA|ref)*>
+<!ELEMENT definition (#PCDATA|para)*>
+
+<!ELEMENT code (#PCDATA)>
+<!ATTLIST code lang CDATA #IMPLIED>
+<!ELEMENT ref CDATA>
+<!ATTLIST ref type (parameter|arg|signal|method|interface) #REQUIRED>
+<!ATTLIST ref to CDATA #REQUIRED>
diff --git a/doc/dbus/spec-to-docbook.xsl b/doc/dbus/spec-to-docbook.xsl
new file mode 100644
index 0000000..1864414
--- /dev/null
+++ b/doc/dbus/spec-to-docbook.xsl
@@ -0,0 +1,543 @@
+<?xml version='1.0'?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd"
+ exclude-result-prefixes="doc">
+<!--
+ Convert D-Bus Glib xml into DocBook refentries
+ Copyright (C) 2007 William Jon McCann
+ License: GPL
+-->
+<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
+
+<xsl:template match="/">
+
+<xsl:variable name="interface" select="//interface/@name"/>
+<xsl:variable name="basename">
+ <xsl:call-template name="interface-basename">
+ <xsl:with-param name="str" select="$interface"/>
+ </xsl:call-template>
+</xsl:variable>
+
+<refentry><xsl:attribute name="id"><xsl:value-of select="$basename"/></xsl:attribute>
+ <refmeta>
+ <refentrytitle role="top_of_page"><xsl:value-of select="//interface/@name"/></refentrytitle>
+ </refmeta>
+
+ <refnamediv>
+ <refname><xsl:value-of select="//interface/@name"/></refname>
+ <refpurpose><xsl:value-of select="$basename"/> interface</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv role="synopsis">
+ <title role="synopsis.title">Methods</title>
+ <synopsis>
+ <xsl:call-template name="methods-synopsis">
+ <xsl:with-param name="basename" select="$basename"/>
+ </xsl:call-template>
+ </synopsis>
+ </refsynopsisdiv>
+
+ <xsl:choose>
+ <xsl:when test="count(///signal) > 0">
+ <refsect1 role="signal_proto">
+ <title role="signal_proto.title">Signals</title>
+ <synopsis>
+ <xsl:call-template name="signals-synopsis">
+ <xsl:with-param name="basename" select="$basename"/>
+ </xsl:call-template>
+ </synopsis>
+ </refsect1>
+ </xsl:when>
+ </xsl:choose>
+
+ <refsect1 role="impl_interfaces">
+ <title role="impl_interfaces.title">Implemented Interfaces</title>
+ <para>
+ Objects implementing <xsl:value-of select="$interface"/> also implements
+ org.freedesktop.DBus.Introspectable,
+ org.freedesktop.DBus.Properties
+ </para>
+ </refsect1>
+
+ <xsl:choose>
+ <xsl:when test="count(///property) > 0">
+ <refsect1 role="properties">
+ <title role="properties.title">Properties</title>
+ <synopsis>
+ <xsl:call-template name="properties-synopsis">
+ <xsl:with-param name="basename" select="$basename"/>
+ </xsl:call-template>
+ </synopsis>
+ </refsect1>
+ </xsl:when>
+ </xsl:choose>
+
+ <refsect1 role="desc">
+ <title role="desc.title">Description</title>
+ <para>
+ <xsl:apply-templates select="//interface/doc:doc"/>
+ </para>
+ </refsect1>
+
+ <refsect1 role="details">
+ <title role="details.title">Details</title>
+ <xsl:call-template name="method-details">
+ <xsl:with-param name="basename" select="$basename"/>
+ </xsl:call-template>
+ </refsect1>
+
+ <xsl:choose>
+ <xsl:when test="count(///signal) > 0">
+ <refsect1 role="signals">
+ <title role="signals.title">Signal Details</title>
+ <xsl:call-template name="signal-details">
+ <xsl:with-param name="basename" select="$basename"/>
+ </xsl:call-template>
+ </refsect1>
+ </xsl:when>
+ </xsl:choose>
+
+ <xsl:choose>
+ <xsl:when test="count(///property) > 0">
+ <refsect1 role="property_details">
+ <title role="property_details.title">Property Details</title>
+ <xsl:call-template name="property-details">
+ <xsl:with-param name="basename" select="$basename"/>
+ </xsl:call-template>
+ </refsect1>
+ </xsl:when>
+ </xsl:choose>
+
+</refentry>
+</xsl:template>
+
+
+<xsl:template name="property-doc">
+ <xsl:apply-templates select="doc:doc/doc:description"/>
+
+ <variablelist role="params">
+ <xsl:for-each select="arg">
+<varlistentry><term><parameter><xsl:value-of select="@name"/></parameter>:</term>
+<listitem><simpara><xsl:value-of select="doc:doc/doc:summary"/></simpara></listitem>
+</varlistentry>
+ </xsl:for-each>
+ </variablelist>
+
+ <xsl:apply-templates select="doc:doc/doc:since"/>
+ <xsl:apply-templates select="doc:doc/doc:deprecated"/>
+ <xsl:apply-templates select="doc:doc/doc:permission"/>
+ <xsl:apply-templates select="doc:doc/doc:seealso"/>
+</xsl:template>
+
+
+<xsl:template name="property-details">
+ <xsl:param name="basename"/>
+ <xsl:variable name="longest">
+ <xsl:call-template name="find-longest">
+ <xsl:with-param name="set" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:for-each select="///property">
+ <refsect2>
+ <title><anchor role="function"><xsl:attribute name="id"><xsl:value-of select="$basename"/>:<xsl:value-of select="@name"/></xsl:attribute></anchor>The "<xsl:value-of select="@name"/>" property</title>
+<indexterm><primary><xsl:value-of select="@name"/></primary><secondary><xsl:value-of select="$basename"/></secondary></indexterm>
+<programlisting>'<xsl:value-of select="@name"/>'<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="2"/></xsl:call-template>
+<xsl:call-template name="property-args"><xsl:with-param name="indent" select="string-length(@name) + 2"/></xsl:call-template></programlisting>
+ </refsect2>
+
+ <xsl:call-template name="property-doc"/>
+
+ </xsl:for-each>
+</xsl:template>
+
+<xsl:template name="signal-doc">
+ <xsl:apply-templates select="doc:doc/doc:description"/>
+
+ <variablelist role="params">
+ <xsl:for-each select="arg">
+<varlistentry><term><parameter><xsl:value-of select="@name"/></parameter>:</term>
+<listitem><simpara><xsl:value-of select="doc:doc/doc:summary"/></simpara></listitem>
+</varlistentry>
+ </xsl:for-each>
+ </variablelist>
+
+ <xsl:apply-templates select="doc:doc/doc:since"/>
+ <xsl:apply-templates select="doc:doc/doc:deprecated"/>
+ <xsl:apply-templates select="doc:doc/doc:permission"/>
+ <xsl:apply-templates select="doc:doc/doc:seealso"/>
+</xsl:template>
+
+<xsl:template name="signal-details">
+ <xsl:param name="basename"/>
+ <xsl:variable name="longest">
+ <xsl:call-template name="find-longest">
+ <xsl:with-param name="set" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:for-each select="///signal">
+ <refsect2>
+ <title><anchor role="function"><xsl:attribute name="id"><xsl:value-of select="$basename"/>::<xsl:value-of select="@name"/></xsl:attribute></anchor>The <xsl:value-of select="@name"/> signal</title>
+<indexterm><primary><xsl:value-of select="@name"/></primary><secondary><xsl:value-of select="$basename"/></secondary></indexterm>
+<programlisting><xsl:value-of select="@name"/> (<xsl:call-template name="signal-args"><xsl:with-param name="indent" select="string-length(@name) + 2"/><xsl:with-param name="prefix" select="."/></xsl:call-template>)</programlisting>
+ </refsect2>
+
+ <xsl:call-template name="signal-doc"/>
+
+ </xsl:for-each>
+</xsl:template>
+
+<xsl:template match="doc:code">
+<programlisting>
+<xsl:apply-templates />
+</programlisting>
+</xsl:template>
+
+<xsl:template match="doc:tt">
+ <literal>
+ <xsl:apply-templates />
+ </literal>
+</xsl:template>
+
+<xsl:template match="doc:i">
+ <emphasis>
+ <xsl:apply-templates />
+ </emphasis>
+</xsl:template>
+
+<xsl:template match="doc:b">
+ <emphasis role="bold">
+ <xsl:apply-templates />
+ </emphasis>
+</xsl:template>
+
+<xsl:template match="doc:ulink">
+ <ulink>
+ <xsl:attribute name="url"><xsl:value-of select="@url"/></xsl:attribute>
+ <xsl:value-of select="."/>
+ </ulink>
+</xsl:template>
+
+<xsl:template match="doc:summary">
+ <xsl:apply-templates />
+</xsl:template>
+
+<xsl:template match="doc:example">
+<informalexample>
+<xsl:apply-templates />
+</informalexample>
+</xsl:template>
+
+<xsl:template name="listitems-do-term">
+ <xsl:param name="str"/>
+ <xsl:choose>
+ <xsl:when test="string-length($str) > 0">
+ <emphasis role="bold"><xsl:value-of select="$str"/>: </emphasis>
+ </xsl:when>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template name="do-listitems">
+ <xsl:for-each select="doc:item">
+ <listitem>
+ <xsl:call-template name="listitems-do-term"><xsl:with-param name="str" select="doc:term"/></xsl:call-template>
+ <xsl:apply-templates select="doc:definition"/>
+ </listitem>
+ </xsl:for-each>
+</xsl:template>
+
+<xsl:template match="doc:list">
+ <para>
+ <xsl:choose>
+ <xsl:when test="contains(@type,'number')">
+ <orderedlist>
+ <xsl:call-template name="do-listitems"/>
+ </orderedlist>
+ </xsl:when>
+ <xsl:otherwise>
+ <itemizedlist>
+ <xsl:call-template name="do-listitems"/>
+ </itemizedlist>
+ </xsl:otherwise>
+ </xsl:choose>
+ </para>
+</xsl:template>
+
+<xsl:template match="doc:para">
+<para>
+<xsl:apply-templates />
+</para>
+</xsl:template>
+
+<xsl:template match="doc:description">
+<xsl:apply-templates />
+</xsl:template>
+
+<xsl:template match="doc:since">
+<para role="since">Since <xsl:value-of select="@version"/>
+</para>
+</xsl:template>
+
+<xsl:template match="doc:deprecated">
+ <xsl:variable name="name" select="../../@name"/>
+ <xsl:variable name="parent">
+ <xsl:call-template name="interface-basename">
+ <xsl:with-param name="str" select="../../../@name"/>/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="type" select="name(../..)"/>
+
+ <para role="deprecated">
+ <warning><para><literal><xsl:value-of select="$name"/></literal> is deprecated since version <xsl:value-of select="@version"/> and should not be used in newly-written code. Use
+
+ <xsl:variable name="to">
+ <xsl:choose>
+ <xsl:when test="contains($type,'property')">
+ <xsl:value-of select="$parent"/>:<xsl:value-of select="@instead"/>
+ </xsl:when>
+ <xsl:when test="contains($type,'signal')">
+ <xsl:value-of select="$parent"/>::<xsl:value-of select="@instead"/>
+ </xsl:when>
+ <xsl:when test="contains($type,'method')">
+ <xsl:value-of select="$parent"/>.<xsl:value-of select="@instead"/>
+ </xsl:when>
+ <xsl:when test="contains($type,'interface')">
+ <xsl:value-of select="@instead"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@instead"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:call-template name="create-link">
+ <xsl:with-param name="type" select="$type"/>
+ <xsl:with-param name="to" select="$to"/>
+ <xsl:with-param name="val" select="@instead"/>
+ </xsl:call-template>
+instead.</para></warning>
+</para>
+</xsl:template>
+
+<xsl:template match="doc:permission">
+<para role="permission">
+<xsl:apply-templates />
+</para>
+</xsl:template>
+
+<xsl:template match="doc:errors">
+<para role="errors">
+<xsl:apply-templates />
+</para>
+</xsl:template>
+
+<xsl:template match="doc:seealso">
+<para>
+See also:
+<xsl:apply-templates />
+
+</para>
+</xsl:template>
+
+<xsl:template name="create-link">
+ <xsl:param name="type"/>
+ <xsl:param name="to"/>
+ <xsl:param name="val"/>
+
+ <xsl:choose>
+ <xsl:when test="contains($type,'property')">
+ <link><xsl:attribute name="linkend"><xsl:value-of select="$to"/></xsl:attribute><literal><xsl:value-of select="$val"/></literal></link>
+ </xsl:when>
+ <xsl:when test="contains($type,'signal')">
+ <link><xsl:attribute name="linkend"><xsl:value-of select="$to"/></xsl:attribute><literal><xsl:value-of select="$val"/></literal></link>
+ </xsl:when>
+ <xsl:when test="contains($type,'method')">
+ <link><xsl:attribute name="linkend"><xsl:value-of select="$to"/></xsl:attribute><function><xsl:value-of select="$val"/></function></link>
+ </xsl:when>
+ <xsl:when test="contains($type,'interface')">
+ <link><xsl:attribute name="linkend"><xsl:value-of select="$to"/></xsl:attribute><xsl:value-of select="$val"/></link>
+ </xsl:when>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template match="doc:ref">
+ <xsl:call-template name="create-link">
+ <xsl:with-param name="type" select="@type"/>
+ <xsl:with-param name="to" select="@to"/>
+ <xsl:with-param name="val" select="."/>
+ </xsl:call-template>
+</xsl:template>
+
+<xsl:template name="method-doc">
+ <xsl:apply-templates select="doc:doc/doc:description"/>
+
+ <variablelist role="params">
+ <xsl:for-each select="arg">
+<varlistentry><term><parameter><xsl:value-of select="@name"/></parameter>:</term>
+<listitem><simpara><xsl:apply-templates select="doc:doc/doc:summary"/></simpara></listitem>
+</varlistentry>
+ </xsl:for-each>
+ </variablelist>
+
+ <xsl:apply-templates select="doc:doc/doc:since"/>
+ <xsl:apply-templates select="doc:doc/doc:deprecated"/>
+
+ <xsl:choose>
+ <xsl:when test="count(doc:doc/doc:errors) > 0">
+ <refsect3>
+ <title>Errors</title>
+ <variablelist role="errors">
+ <xsl:for-each select="doc:doc/doc:errors/doc:error">
+ <varlistentry>
+ <term><parameter><xsl:value-of select="@name"/></parameter>:</term>
+ <listitem><simpara><xsl:apply-templates select="."/></simpara></listitem>
+ </varlistentry>
+ </xsl:for-each>
+ </variablelist>
+ </refsect3>
+ </xsl:when>
+ </xsl:choose>
+
+ <xsl:choose>
+ <xsl:when test="count(doc:doc/doc:permission) > 0">
+ <refsect3>
+ <title>Permissions</title>
+ <xsl:apply-templates select="doc:doc/doc:permission"/>
+ </refsect3>
+ </xsl:when>
+ </xsl:choose>
+
+ <xsl:apply-templates select="doc:doc/doc:seealso"/>
+</xsl:template>
+
+<xsl:template name="method-details">
+ <xsl:param name="basename"/>
+ <xsl:variable name="longest">
+ <xsl:call-template name="find-longest">
+ <xsl:with-param name="set" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:for-each select="///method">
+ <refsect2>
+ <title><anchor role="function"><xsl:attribute name="id"><xsl:value-of select="$basename"/>.<xsl:value-of select="@name"/></xsl:attribute></anchor><xsl:value-of select="@name"/> ()</title>
+<indexterm><primary><xsl:value-of select="@name"/></primary><secondary><xsl:value-of select="$basename"/></secondary></indexterm>
+<programlisting><xsl:value-of select="@name"/> (<xsl:call-template name="method-args"><xsl:with-param name="indent" select="string-length(@name) + 2"/><xsl:with-param name="prefix" select="."/></xsl:call-template>)</programlisting>
+ </refsect2>
+
+ <xsl:call-template name="method-doc"/>
+
+ </xsl:for-each>
+</xsl:template>
+
+
+<xsl:template name="properties-synopsis">
+ <xsl:param name="basename"/>
+ <xsl:variable name="longest">
+ <xsl:call-template name="find-longest">
+ <xsl:with-param name="set" select="///property/@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:for-each select="///property">
+<link><xsl:attribute name="linkend"><xsl:value-of select="$basename"/>:<xsl:value-of select="@name"/></xsl:attribute>'<xsl:value-of select="@name"/>'</link><xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$longest - string-length(@name) + 1"/></xsl:call-template> <xsl:call-template name="property-args"><xsl:with-param name="indent" select="$longest + 2"/></xsl:call-template>
+</xsl:for-each>
+</xsl:template>
+
+
+<xsl:template name="signals-synopsis">
+ <xsl:param name="basename"/>
+ <xsl:variable name="longest">
+ <xsl:call-template name="find-longest">
+ <xsl:with-param name="set" select="///signal/@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:for-each select="///signal">
+<link><xsl:attribute name="linkend"><xsl:value-of select="$basename"/>::<xsl:value-of select="@name"/></xsl:attribute><xsl:value-of select="@name"/></link><xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$longest - string-length(@name) + 1"/></xsl:call-template>(<xsl:call-template name="signal-args"><xsl:with-param name="indent" select="$longest + 2"/><xsl:with-param name="prefix" select="///signal"/></xsl:call-template>)
+</xsl:for-each>
+</xsl:template>
+
+
+<xsl:template name="methods-synopsis">
+ <xsl:param name="basename"/>
+ <xsl:variable name="longest">
+ <xsl:call-template name="find-longest">
+ <xsl:with-param name="set" select="///method/@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:for-each select="///method">
+<link><xsl:attribute name="linkend"><xsl:value-of select="$basename"/>.<xsl:value-of select="@name"/></xsl:attribute><xsl:value-of select="@name"/></link><xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$longest - string-length(@name) + 1"/></xsl:call-template>(<xsl:call-template name="method-args"><xsl:with-param name="indent" select="$longest + 2"/><xsl:with-param name="prefix" select="///method"/></xsl:call-template>)
+</xsl:for-each>
+</xsl:template>
+
+
+<xsl:template name="method-args"><xsl:param name="indent"/><xsl:param name="prefix"/><xsl:variable name="longest"><xsl:call-template name="find-longest"><xsl:with-param name="set" select="$prefix/arg/@type"/></xsl:call-template></xsl:variable><xsl:for-each select="arg"><xsl:value-of select="@direction"/>
+<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="4 - string-length(@direction)"/></xsl:call-template>'<xsl:value-of select="@type"/>'<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$longest - string-length(@type) + 1"/></xsl:call-template>
+<xsl:value-of select="@name"/><xsl:if test="not(position() = last())">,
+<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$indent"/></xsl:call-template></xsl:if>
+</xsl:for-each>
+</xsl:template>
+
+
+<xsl:template name="signal-args"><xsl:param name="indent"/><xsl:param name="prefix"/><xsl:variable name="longest"><xsl:call-template name="find-longest"><xsl:with-param name="set" select="$prefix/arg/@type"/></xsl:call-template></xsl:variable><xsl:for-each select="arg">'<xsl:value-of select="@type"/>'<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$longest - string-length(@type) + 1"/></xsl:call-template>
+<xsl:value-of select="@name"/><xsl:if test="not(position() = last())">,
+<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$indent"/></xsl:call-template></xsl:if>
+</xsl:for-each>
+</xsl:template>
+
+
+<xsl:template name="property-args"><xsl:param name="indent"/>
+<xsl:value-of select="@access"/><xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="9 - string-length(@access) + 1"/></xsl:call-template>'<xsl:value-of select="@type"/>'
+</xsl:template>
+
+
+<xsl:template name="pad-spaces">
+ <xsl:param name="width"/>
+ <xsl:variable name="spaces" xml:space="preserve"> </xsl:variable>
+ <xsl:value-of select="substring($spaces,1,$width)"/>
+</xsl:template>
+
+
+<xsl:template name="find-longest">
+ <xsl:param name="set"/>
+ <xsl:param name="index" select="1"/>
+ <xsl:param name="longest" select="0"/>
+
+ <xsl:choose>
+ <xsl:when test="$index > count($set)">
+ <!--finished looking-->
+ <xsl:value-of select="$longest"/>
+ </xsl:when>
+ <xsl:when test="string-length($set[$index])>$longest">
+ <!--found new longest-->
+ <xsl:call-template name="find-longest">
+ <xsl:with-param name="set" select="$set"/>
+ <xsl:with-param name="index" select="$index + 1"/>
+ <xsl:with-param name="longest" select="string-length($set[$index])"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!--this isn't any longer-->
+ <xsl:call-template name="find-longest">
+ <xsl:with-param name="set" select="$set"/>
+ <xsl:with-param name="index" select="$index + 1"/>
+ <xsl:with-param name="longest" select="$longest"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+
+<xsl:template name="interface-basename">
+ <xsl:param name="str"/>
+ <xsl:choose>
+ <xsl:when test="contains($str,'.')">
+ <xsl:call-template name="interface-basename">
+ <xsl:with-param name="str" select="substring-after($str,'.')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$str"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/doc/devkit-power-docs.xml b/doc/devkit-power-docs.xml
new file mode 100644
index 0000000..6af1211
--- /dev/null
+++ b/doc/devkit-power-docs.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
+<!ENTITY version SYSTEM "version.xml">
+]>
+<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
+ <bookinfo>
+ <title>DeviceKit-power Reference Manual</title>
+ <releaseinfo>Version &version;</releaseinfo>
+ <authorgroup>
+ <author>
+ <firstname>David</firstname>
+ <surname>Zeuthen</surname>
+ <affiliation>
+ <address>
+ <email>david@fubar.dk</email>
+ </address>
+ </affiliation>
+ </author>
+ </authorgroup>
+
+ <copyright>
+ <year>2008</year>
+ <holder>The DeviceKit-power Authors</holder>
+ </copyright>
+
+ <legalnotice>
+ <para>
+ Permission is granted to copy, distribute and/or modify this
+ document under the terms of the <citetitle>GNU Free
+ Documentation License</citetitle>, Version 1.1 or any later
+ version published by the Free Software Foundation with no
+ Invariant Sections, no Front-Cover Texts, and no Back-Cover
+ Texts. You may obtain a copy of the <citetitle>GNU Free
+ Documentation License</citetitle> from the Free Software
+ Foundation by visiting <ulink type="http"
+ url="http://www.fsf.org">their Web site</ulink> or by writing
+ to:
+
+ <address>
+ The Free Software Foundation, Inc.,
+ <street>59 Temple Place</street> - Suite 330,
+ <city>Boston</city>, <state>MA</state> <postcode>02111-1307</postcode>,
+ <country>USA</country>
+ </address>
+ </para>
+
+ <para>
+ Many of the names used by companies to distinguish their
+ products and services are claimed as trademarks. Where those
+ names appear in any GNOME documentation, and those trademarks
+ are made aware to the members of the GNOME Documentation
+ Project, the names have been printed in caps or initial caps.
+ </para>
+ </legalnotice>
+ </bookinfo>
+
+ <reference id="ref-dbus">
+ <title>D-Bus API Reference</title>
+ <partintro>
+ <para>
+ This part documents the D-Bus interface used to access the
+ DeviceKit-power daemon.
+ </para>
+ </partintro>
+ <xi:include href="dbus/org.freedesktop.DeviceKit.Power.ref.xml"/>
+ <xi:include href="dbus/org.freedesktop.DeviceKit.Power.Source.ref.xml"/>
+ </reference>
+
+ <reference id="tools-fileformats">
+ <title>Manual Pages</title>
+ <partintro>
+ <para>
+ This part contains the manual pages distributed with DeviceKit-power.
+ </para>
+ </partintro>
+ <xi:include href="man/DeviceKit-power.xml"/>
+ <xi:include href="man/devkit-power-daemon.xml"/>
+ <xi:include href="man/devkit-power.xml"/>
+ </reference>
+
+ <index>
+ <title>Index</title>
+ </index>
+
+ <!-- License -->
+
+ <appendix id="license">
+ <title>License</title>
+ <para>
+<programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="../COPYING" parse="text"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
+ </para>
+ </appendix>
+</book>
diff --git a/doc/man/DeviceKit-power.xml b/doc/man/DeviceKit-power.xml
new file mode 100644
index 0000000..8f5ab6d
--- /dev/null
+++ b/doc/man/DeviceKit-power.xml
@@ -0,0 +1,64 @@
+<refentry id="DeviceKit-power.7">
+ <refentryinfo>
+ <title>DeviceKit-power</title>
+ <date>March 2008</date>
+ <productname>DeviceKit-power</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>DeviceKit-power</refentrytitle>
+ <manvolnum>7</manvolnum>
+ <refmiscinfo class="version"></refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>DeviceKit-power</refname>
+ <refpurpose>System-wide Power Management</refpurpose>
+ </refnamediv>
+
+ <refsect1><title>DESCRIPTION</title>
+ <para>
+ DeviceKit-power provides an interface to enumerate power sources
+ on the system and control system-wide power management. Any
+ application can access
+ the <emphasis>org.freedesktop.DeviceKit.Power</emphasis> service
+ on the system message bus. Some operations (such as suspending
+ the system) is restricted using PolicyKit.
+ </para>
+ </refsect1>
+
+ <refsect1><title>AUTHOR</title>
+ <para>
+ Written by David Zeuthen <email>david@fubar.dk</email> with
+ a lot of help from many others.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>BUGS</title>
+ <para>
+ Please send bug reports to either the distribution or the
+ hal mailing list,
+ see <ulink url="http://lists.freedesktop.org/mailman/listinfo/hal"/>.
+ to subscribe.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para>
+ <citerefentry>
+ <refentrytitle>DeviceKit</refentrytitle><manvolnum>7</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>PolicyKit</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>devkit-power-daemon</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>devkit-power</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>
+ </para>
+ </refsect1>
+</refentry>
diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
new file mode 100644
index 0000000..f49dde9
--- /dev/null
+++ b/doc/man/Makefile.am
@@ -0,0 +1,24 @@
+
+NULL =
+
+if MAN_PAGES_ENABLED
+
+man_MANS = \
+ devkit-power.1 \
+ devkit-power-daemon.8 \
+ DeviceKit-power.7 \
+ $(NULL)
+
+%.1 %.7 %.8 : %.xml
+ $(XSLTPROC) -nonet http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
+
+endif # MAN_PAGES_ENABLED
+
+EXTRA_DIST= \
+ devkit-power.xml \
+ devkit-power-daemon.xml \
+ DeviceKit-power.xml \
+ $(NULL)
+
+clean-local:
+ rm -f *~ *.[178]
diff --git a/doc/man/devkit-power-daemon.xml b/doc/man/devkit-power-daemon.xml
new file mode 100644
index 0000000..e969586
--- /dev/null
+++ b/doc/man/devkit-power-daemon.xml
@@ -0,0 +1,84 @@
+<refentry id="devkit-power-daemon.8">
+ <refentryinfo>
+ <title>devkit-power-daemon</title>
+ <date>April 2008</date>
+ <productname>devkit-power-daemon</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>devkit-power-daemon</refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo class="version"></refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>devkit-power-daemon</refname>
+ <refpurpose>DeviceKit-power Daemon</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>devkit-power-daemon</command>
+ <arg><option>--help</option></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+
+ <refsect1><title>DESCRIPTION</title>
+ <para>
+ <emphasis><refentrytitle>devkit-power-daemon</refentrytitle></emphasis> provides
+ the <emphasis>org.freedesktop.DeviceKit.Power</emphasis> service on the
+ system message bus. Users or administrators should never need to
+ start this daemon as it will be automatically started by
+ <citerefentry><refentrytitle>dbus-daemon</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ whenever an application calls into the <emphasis>org.freedesktop.DeviceKit.Power</emphasis>
+ service.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>OPTIONS</title>
+ <variablelist>
+ <varlistentry>
+ <term><option>--help</option></term>
+ <listitem>
+ <para>
+ Show help options.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1><title>AUTHOR</title>
+ <para>
+ Written by David Zeuthen <email>david@fubar.dk</email> with
+ a lot of help from many others.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>BUGS</title>
+ <para>
+ Please send bug reports to either the distribution or the
+ hal mailing list,
+ see <ulink url="http://lists.freedesktop.org/mailman/listinfo/hal"/>
+ on how to subscribe.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para>
+ <citerefentry>
+ <refentrytitle>DeviceKit-power</refentrytitle><manvolnum>7</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>devkit-power</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dbus-daemon</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>,
+ </para>
+ </refsect1>
+</refentry>
diff --git a/doc/man/devkit-power.xml b/doc/man/devkit-power.xml
new file mode 100644
index 0000000..fd25a79
--- /dev/null
+++ b/doc/man/devkit-power.xml
@@ -0,0 +1,99 @@
+<refentry id="devkit-power.1">
+ <refentryinfo>
+ <title>devkit-power</title>
+ <date>April 2008</date>
+ <productname>devkit-power</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>devkit-power</refentrytitle>
+ <manvolnum>1</manvolnum>
+ <refmiscinfo class="version"></refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>devkit-power</refname>
+ <refpurpose>DeviceKit-power command line tool</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>devkit-power</command>
+ <arg><option>--enumerate</option></arg>
+ <arg><option>--monitor</option></arg>
+ <arg><option>--monitor-detail</option></arg>
+ <arg><option>--help</option></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+
+ <refsect1><title>DESCRIPTION</title>
+ <para>
+ <emphasis><refentrytitle>devkit-power</refentrytitle></emphasis> is a
+ simple command line client for the
+ <citerefentry><refentrytitle>DeviceKit-power</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ daemon. TODO: not fully documented.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>OPTIONS</title>
+ <variablelist>
+ <varlistentry>
+ <term><option>--monitor</option></term>
+ <listitem>
+ <para>
+ Connect to the DeviceKit-power daemon and print a line
+ every time a power source is added, removed or changed.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--monitor-detail</option></term>
+ <listitem>
+ <para>
+ Like <option>--monitor</option> but prints the full
+ details of the power source whenever an event happens.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--help</option></term>
+ <listitem>
+ <para>
+ Show help options.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1><title>AUTHOR</title>
+ <para>
+ Written by David Zeuthen <email>david@fubar.dk</email> with
+ a lot of help from many others.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>BUGS</title>
+ <para>
+ Please send bug reports to either the distribution or the
+ hal mailing list,
+ see <ulink url="http://lists.freedesktop.org/mailman/listinfo/hal"/>
+ on how to subscribe.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para>
+ <citerefentry>
+ <refentrytitle>devkit-power-daemon</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>DeviceKit-power</refentrytitle><manvolnum>7</manvolnum>
+ </citerefentry>,
+ </para>
+ </refsect1>
+</refentry>
diff --git a/doc/version.xml b/doc/version.xml
new file mode 100644
index 0000000..5325a8d
--- /dev/null
+++ b/doc/version.xml
@@ -0,0 +1 @@
+001
diff --git a/gtk-doc.make b/gtk-doc.make
new file mode 100644
index 0000000..3c3e39a
--- /dev/null
+++ b/gtk-doc.make
@@ -0,0 +1,159 @@
+# -*- mode: makefile -*-
+
+####################################
+# Everything below here is generic #
+####################################
+
+if GTK_DOC_USE_LIBTOOL
+GTKDOC_CC = $(LIBTOOL) --mode=compile $(CC) $(INCLUDES) $(AM_CFLAGS) $(CFLAGS)
+GTKDOC_LD = $(LIBTOOL) --mode=link $(CC) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS)
+else
+GTKDOC_CC = $(CC) $(INCLUDES) $(AM_CFLAGS) $(CFLAGS)
+GTKDOC_LD = $(CC) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS)
+endif
+
+# We set GPATH here; this gives us semantics for GNU make
+# which are more like other make's VPATH, when it comes to
+# whether a source that is a target of one rule is then
+# searched for in VPATH/GPATH.
+#
+GPATH = $(srcdir)
+
+TARGET_DIR=$(HTML_DIR)/$(DOC_MODULE)
+
+EXTRA_DIST = \
+ $(content_files) \
+ $(HTML_IMAGES) \
+ $(DOC_MAIN_SGML_FILE) \
+ $(DOC_MODULE)-sections.txt \
+ $(DOC_MODULE)-overrides.txt
+
+DOC_STAMPS=scan-build.stamp tmpl-build.stamp sgml-build.stamp html-build.stamp \
+ $(srcdir)/tmpl.stamp $(srcdir)/sgml.stamp $(srcdir)/html.stamp
+
+SCANOBJ_FILES = \
+ $(DOC_MODULE).args \
+ $(DOC_MODULE).hierarchy \
+ $(DOC_MODULE).interfaces \
+ $(DOC_MODULE).prerequisites \
+ $(DOC_MODULE).signals
+
+CLEANFILES = $(SCANOBJ_FILES) $(DOC_MODULE)-unused.txt $(DOC_STAMPS)
+
+if ENABLE_GTK_DOC
+all-local: html-build.stamp
+else
+all-local:
+endif
+
+docs: html-build.stamp
+
+#### scan ####
+
+scan-build.stamp: $(HFILE_GLOB) $(CFILE_GLOB)
+ @echo 'gtk-doc: Scanning header files'
+ @-chmod -R u+w $(srcdir)
+ cd $(srcdir) && \
+ gtkdoc-scan --module=$(DOC_MODULE) --source-dir=$(DOC_SOURCE_DIR) --ignore-headers="$(IGNORE_HFILES)" $(SCAN_OPTIONS) $(EXTRA_HFILES)
+ if grep -l '^..*$$' $(srcdir)/$(DOC_MODULE).types > /dev/null 2>&1 ; then \
+ CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" CFLAGS="$(GTKDOC_CFLAGS)" LDFLAGS="$(GTKDOC_LIBS)" gtkdoc-scangobj $(SCANGOBJ_OPTIONS) --module=$(DOC_MODULE) --output-dir=$(srcdir) ; \
+ else \
+ cd $(srcdir) ; \
+ for i in $(SCANOBJ_FILES) ; do \
+ test -f $$i || touch $$i ; \
+ done \
+ fi
+ touch scan-build.stamp
+
+$(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp
+ @true
+
+#### templates ####
+
+tmpl-build.stamp: $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt
+ @echo 'gtk-doc: Rebuilding template files'
+ @-chmod -R u+w $(srcdir)
+ cd $(srcdir) && gtkdoc-mktmpl --module=$(DOC_MODULE) $(MKTMPL_OPTIONS)
+ touch tmpl-build.stamp
+
+tmpl.stamp: tmpl-build.stamp
+ @true
+
+tmpl/*.sgml:
+ @true
+
+
+#### xml ####
+
+sgml-build.stamp: tmpl.stamp $(HFILE_GLOB) $(CFILE_GLOB) $(DOC_MODULE)-sections.txt $(srcdir)/tmpl/*.sgml $(expand_content_files)
+ @echo 'gtk-doc: Building XML'
+ @-chmod -R u+w $(srcdir)
+ cd $(srcdir) && \
+ gtkdoc-mkdb --module=$(DOC_MODULE) --source-dir=$(DOC_SOURCE_DIR) --output-format=xml --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) $(MKDB_OPTIONS)
+ touch sgml-build.stamp
+
+sgml.stamp: sgml-build.stamp
+ @true
+
+#### html ####
+
+html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files)
+ @echo 'gtk-doc: Building HTML'
+ @-chmod -R u+w $(srcdir)
+ rm -rf $(srcdir)/html
+ mkdir $(srcdir)/html
+ cd $(srcdir)/html && gtkdoc-mkhtml $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE)
+ test "x$(HTML_IMAGES)" = "x" || ( cd $(srcdir) && cp $(HTML_IMAGES) html )
+ @echo 'gtk-doc: Fixing cross-references'
+ cd $(srcdir) && gtkdoc-fixxref --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS)
+ touch html-build.stamp
+
+##############
+
+clean-local:
+ rm -f *~ *.bak
+ rm -rf .libs
+
+maintainer-clean-local: clean
+ cd $(srcdir) && rm -rf xml html $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt
+
+install-data-local:
+ installfiles=`echo $(srcdir)/html/*`; \
+ if test "$$installfiles" = '$(srcdir)/html/*'; \
+ then echo '-- Nothing to install' ; \
+ else \
+ $(mkinstalldirs) $(DESTDIR)$(TARGET_DIR); \
+ for i in $$installfiles; do \
+ echo '-- Installing '$$i ; \
+ $(INSTALL_DATA) $$i $(DESTDIR)$(TARGET_DIR); \
+ done; \
+ echo '-- Installing $(srcdir)/html/index.sgml' ; \
+ $(INSTALL_DATA) $(srcdir)/html/index.sgml $(DESTDIR)$(TARGET_DIR) || :; \
+ fi
+
+uninstall-local:
+ rm -f $(DESTDIR)$(TARGET_DIR)/*
+
+#
+# Require gtk-doc when making dist
+#
+if ENABLE_GTK_DOC
+dist-check-gtkdoc:
+else
+dist-check-gtkdoc:
+ @echo "*** gtk-doc must be installed and enabled in order to make dist"
+ @false
+endif
+
+dist-hook: dist-check-gtkdoc dist-hook-local
+ mkdir $(distdir)/tmpl
+ mkdir $(distdir)/xml
+ mkdir $(distdir)/html
+ -cp $(srcdir)/tmpl/*.sgml $(distdir)/tmpl
+ -cp $(srcdir)/xml/*.xml $(distdir)/xml
+ cp $(srcdir)/html/* $(distdir)/html
+ if test -f $(srcdir)/$(DOC_MODULE).types; then \
+ cp $(srcdir)/$(DOC_MODULE).types $(distdir)/$(DOC_MODULE).types; \
+ fi
+
+.PHONY : dist-hook-local docs
diff --git a/mkinstalldirs b/mkinstalldirs
new file mode 100755
index 0000000..d2d5f21
--- /dev/null
+++ b/mkinstalldirs
@@ -0,0 +1,111 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+errstatus=0
+dirmode=""
+
+usage="\
+Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..."
+
+# process command line arguments
+while test $# -gt 0 ; do
+ case $1 in
+ -h | --help | --h*) # -h for help
+ echo "$usage" 1>&2
+ exit 0
+ ;;
+ -m) # -m PERM arg
+ shift
+ test $# -eq 0 && { echo "$usage" 1>&2; exit 1; }
+ dirmode=$1
+ shift
+ ;;
+ --) # stop option processing
+ shift
+ break
+ ;;
+ -*) # unknown option
+ echo "$usage" 1>&2
+ exit 1
+ ;;
+ *) # first non-opt arg
+ break
+ ;;
+ esac
+done
+
+for file
+do
+ if test -d "$file"; then
+ shift
+ else
+ break
+ fi
+done
+
+case $# in
+ 0) exit 0 ;;
+esac
+
+case $dirmode in
+ '')
+ if mkdir -p -- . 2>/dev/null; then
+ echo "mkdir -p -- $*"
+ exec mkdir -p -- "$@"
+ fi
+ ;;
+ *)
+ if mkdir -m "$dirmode" -p -- . 2>/dev/null; then
+ echo "mkdir -m $dirmode -p -- $*"
+ exec mkdir -m "$dirmode" -p -- "$@"
+ fi
+ ;;
+esac
+
+for file
+do
+ set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+ shift
+
+ pathcomp=
+ for d
+ do
+ pathcomp="$pathcomp$d"
+ case $pathcomp in
+ -*) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp"
+
+ mkdir "$pathcomp" || lasterr=$?
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ else
+ if test ! -z "$dirmode"; then
+ echo "chmod $dirmode $pathcomp"
+ lasterr=""
+ chmod "$dirmode" "$pathcomp" || lasterr=$?
+
+ if test ! -z "$lasterr"; then
+ errstatus=$lasterr
+ fi
+ fi
+ fi
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# End:
+# mkinstalldirs ends here
diff --git a/po/ChangeLog b/po/ChangeLog
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/po/ChangeLog
diff --git a/po/LINGUAS b/po/LINGUAS
new file mode 100644
index 0000000..b72d517
--- /dev/null
+++ b/po/LINGUAS
@@ -0,0 +1,4 @@
+# please keep this list sorted alphabetically
+#
+
+
diff --git a/po/POTFILES.in b/po/POTFILES.in
new file mode 100644
index 0000000..e769d2d
--- /dev/null
+++ b/po/POTFILES.in
@@ -0,0 +1,4 @@
+# List of source files containing translatable strings.
+# Please keep this file sorted alphabetically.
+[encoding: UTF-8]
+policy/org.freedesktop.devicekit.power.policy.in
diff --git a/policy/Makefile.am b/policy/Makefile.am
new file mode 100644
index 0000000..e03f095
--- /dev/null
+++ b/policy/Makefile.am
@@ -0,0 +1,17 @@
+
+devkit_policydir = $(datadir)/PolicyKit/policy
+
+dist_devkit_policy_DATA = \
+ org.freedesktop.devicekit.power.policy
+
+@INTLTOOL_POLICY_RULE@
+
+check:
+ polkit-policy-file-validate $(dist_devkit_policy_DATA)
+
+clean-local :
+ rm -f *~
+
+DISTCLEANFILES = $(dist_devkit_policy_DATA)
+
+EXTRA_DIST = $(dist_devkit_policy_DATA:.policy=.policy.in)
diff --git a/policy/org.freedesktop.devicekit.power.policy.in b/policy/org.freedesktop.devicekit.power.policy.in
new file mode 100644
index 0000000..759b747
--- /dev/null
+++ b/policy/org.freedesktop.devicekit.power.policy.in
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!DOCTYPE policyconfig PUBLIC
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
+
+<!--
+Policy definitions for DeviceKit-power
+
+Copyright (c) 2008 David Zeuthen <david@fubar.dk>
+
+NOTE: If you make changes to this file, make sure to validate the file
+using the polkit-policy-file-validate(1) tool. Changes made to this
+file are instantly applied.
+-->
+
+<policyconfig>
+ <vendor>The DeviceKit-power Project</vendor>
+ <vendor_url>http://hal.freedesktop.org/docs/DeviceKit-power/</vendor_url>
+ <icon_name>system-suspend</icon_name>
+
+ <action id="org.freedesktop.devicekit.power.suspend">
+ <_description>Suspend the system to RAM</_description>
+ <_message>Authentication is required to suspend to system</_message>
+ <defaults>
+ <allow_any>no</allow_any>
+ <allow_inactive>no</allow_inactive>
+ <allow_active>yes</allow_active>
+ </defaults>
+ </action>
+
+</policyconfig>
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..1db6572
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,82 @@
+## Process this file with automake to produce Makefile.in
+
+INCLUDES = \
+ -I$(top_builddir)/src -I$(top_srcdir)/src \
+ -DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\" \
+ -DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \
+ -DPACKAGE_DATA_DIR=\""$(datadir)"\" \
+ -DPACKAGE_BIN_DIR=\""$(bindir)"\" \
+ -DPACKAGE_LOCALSTATE_DIR=\""$(localstatedir)"\" \
+ -DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \
+ -DPACKAGE_LIB_DIR=\""$(libdir)"\" \
+ -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT \
+ $(DBUS_GLIB_CFLAGS) \
+ $(POLKIT_DBUS_CFLAGS) \
+ $(DEVKIT_CFLAGS) \
+ $(GLIB_CFLAGS)
+
+BUILT_SOURCES = \
+ devkit-power-daemon-glue.h \
+ devkit-power-source-glue.h \
+ devkit-power-marshal.h devkit-power-marshal.c
+
+devkit-power-marshal.h: devkit-power-marshal.list
+ glib-genmarshal $< --prefix=devkit_power_marshal --header > $@
+
+devkit-power-marshal.c: devkit-power-marshal.list
+ echo "#include \"devkit-power-marshal.h\"" > $@ && glib-genmarshal $< --prefix=devkit_power_marshal --body >> $@
+
+devkit-power-daemon-glue.h: org.freedesktop.DeviceKit.Power.xml Makefile.am
+ dbus-binding-tool --prefix=devkit_power_daemon --mode=glib-server --output=devkit-power-daemon-glue.h org.freedesktop.DeviceKit.Power.xml
+
+devkit-power-source-glue.h: org.freedesktop.DeviceKit.Power.Source.xml Makefile.am
+ dbus-binding-tool --prefix=devkit_power_source --mode=glib-server --output=devkit-power-source-glue.h org.freedesktop.DeviceKit.Power.Source.xml
+
+libexec_PROGRAMS = devkit-power-daemon
+
+dbusifdir = $(datadir)/dbus-1/interfaces
+dbusif_DATA = org.freedesktop.DeviceKit.Power.xml org.freedesktop.DeviceKit.Power.Source.xml
+
+devkit_power_daemon_SOURCES = \
+ devkit-power-daemon.h devkit-power-daemon.c \
+ devkit-power-device.h devkit-power-device.c \
+ devkit-power-source.h devkit-power-source.c \
+ sysfs-utils.h sysfs-utils.c \
+ main.c \
+ $(BUILT_SOURCES)
+
+devkit_power_daemon_CPPFLAGS = \
+ -I$(top_srcdir)/src \
+ -DG_LOG_DOMAIN=\"devkit-power-daemon\" \
+ $(DISABLE_DEPRECATED) \
+ $(AM_CPPFLAGS)
+
+devkit_power_daemon_LDADD = \
+ $(DBUS_GLIB_LIBS) \
+ $(POLKIT_DBUS_LIBS) \
+ $(DEVKIT_LIBS)
+
+servicedir = $(datadir)/dbus-1/system-services
+service_in_files = org.freedesktop.DeviceKit.Power.service.in
+service_DATA = $(service_in_files:.service.in=.service)
+
+$(service_DATA): $(service_in_files) Makefile
+ @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
+
+dbusconfdir = $(sysconfdir)/dbus-1/system.d
+dbusconf_in_files = org.freedesktop.DeviceKit.Power.conf.in
+dbusconf_DATA = $(dbusconf_in_files:.conf.in=.conf)
+
+$(dbusconf_DATA): $(dbusconf_in_files) Makefile
+ cp $< $@
+
+CLEANFILES = $(BUILT_SOURCES)
+
+EXTRA_DIST = org.freedesktop.DeviceKit.Power.xml \
+ org.freedesktop.DeviceKit.Power.Source.xml \
+ devkit-power-marshal.list \
+ $(service_in_files) \
+ $(dbusconf_in_files)
+
+clean-local :
+ rm -f *~ $(service_DATA) $(dbusconf_DATA)
diff --git a/src/devkit-power-daemon.c b/src/devkit-power-daemon.c
new file mode 100644
index 0000000..453ff0b
--- /dev/null
+++ b/src/devkit-power-daemon.c
@@ -0,0 +1,631 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+
+#include <glib.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 "devkit-power-daemon.h"
+#include "devkit-power-device.h"
+
+#include "devkit-power-daemon-glue.h"
+#include "devkit-power-marshal.h"
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+enum
+{
+ DEVICE_ADDED_SIGNAL,
+ DEVICE_REMOVED_SIGNAL,
+ DEVICE_CHANGED_SIGNAL,
+ LAST_SIGNAL,
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+struct DevkitPowerDaemonPrivate
+{
+ DBusGConnection *system_bus_connection;
+ DBusGProxy *system_bus_proxy;
+ PolKitContext *pk_context;
+ PolKitTracker *pk_tracker;
+
+ GHashTable *map_native_path_to_device;
+
+ DevkitClient *devkit_client;
+};
+
+static void devkit_power_daemon_class_init (DevkitPowerDaemonClass *klass);
+static void devkit_power_daemon_init (DevkitPowerDaemon *seat);
+static void devkit_power_daemon_finalize (GObject *object);
+
+G_DEFINE_TYPE (DevkitPowerDaemon, devkit_power_daemon, G_TYPE_OBJECT)
+
+#define DEVKIT_POWER_DAEMON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DEVKIT_TYPE_POWER_DAEMON, DevkitPowerDaemonPrivate))
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+GQuark
+devkit_power_daemon_error_quark (void)
+{
+ static GQuark ret = 0;
+
+ if (ret == 0) {
+ ret = g_quark_from_static_string ("devkit_power_daemon_error");
+ }
+
+ return ret;
+}
+
+
+#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
+
+GType
+devkit_power_daemon_error_get_type (void)
+{
+ static GType etype = 0;
+
+ if (etype == 0)
+ {
+ static const GEnumValue values[] =
+ {
+ ENUM_ENTRY (DEVKIT_POWER_DAEMON_ERROR_GENERAL, "GeneralError"),
+ ENUM_ENTRY (DEVKIT_POWER_DAEMON_ERROR_NOT_SUPPORTED, "NotSupported"),
+ ENUM_ENTRY (DEVKIT_POWER_DAEMON_ERROR_NO_SUCH_DEVICE, "NoSuchDevice"),
+ { 0, 0, 0 }
+ };
+ g_assert (DEVKIT_POWER_DAEMON_NUM_ERRORS == G_N_ELEMENTS (values) - 1);
+ etype = g_enum_register_static ("DevkitPowerDaemonError", values);
+ }
+ return etype;
+}
+
+
+static GObject *
+devkit_power_daemon_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ DevkitPowerDaemon *daemon;
+ DevkitPowerDaemonClass *klass;
+
+ klass = DEVKIT_POWER_DAEMON_CLASS (g_type_class_peek (DEVKIT_TYPE_POWER_DAEMON));
+
+ daemon = DEVKIT_POWER_DAEMON (
+ G_OBJECT_CLASS (devkit_power_daemon_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+ return G_OBJECT (daemon);
+}
+
+static void
+devkit_power_daemon_class_init (DevkitPowerDaemonClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructor = devkit_power_daemon_constructor;
+ object_class->finalize = devkit_power_daemon_finalize;
+
+ g_type_class_add_private (klass, sizeof (DevkitPowerDaemonPrivate));
+
+ signals[DEVICE_ADDED_SIGNAL] =
+ g_signal_new ("device-added",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1, G_TYPE_STRING);
+
+ signals[DEVICE_REMOVED_SIGNAL] =
+ g_signal_new ("device-removed",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1, G_TYPE_STRING);
+
+ signals[DEVICE_CHANGED_SIGNAL] =
+ g_signal_new ("device-changed",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1, G_TYPE_STRING);
+
+ dbus_g_object_type_install_info (DEVKIT_TYPE_POWER_DAEMON, &dbus_glib_devkit_power_daemon_object_info);
+
+ dbus_g_error_domain_register (DEVKIT_POWER_DAEMON_ERROR,
+ NULL,
+ DEVKIT_POWER_DAEMON_TYPE_ERROR);
+}
+
+static void
+devkit_power_daemon_init (DevkitPowerDaemon *daemon)
+{
+ daemon->priv = DEVKIT_POWER_DAEMON_GET_PRIVATE (daemon);
+ daemon->priv->map_native_path_to_device = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ NULL);
+}
+
+static void
+devkit_power_daemon_finalize (GObject *object)
+{
+ DevkitPowerDaemon *daemon;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (DEVKIT_IS_POWER_DAEMON (object));
+
+ daemon = DEVKIT_POWER_DAEMON (object);
+
+ g_return_if_fail (daemon->priv != NULL);
+
+ if (daemon->priv->pk_context != NULL)
+ polkit_context_unref (daemon->priv->pk_context);
+
+ if (daemon->priv->pk_tracker != NULL)
+ polkit_tracker_unref (daemon->priv->pk_tracker);
+
+ if (daemon->priv->system_bus_proxy != NULL)
+ g_object_unref (daemon->priv->system_bus_proxy);
+
+ if (daemon->priv->system_bus_connection != NULL)
+ dbus_g_connection_unref (daemon->priv->system_bus_connection);
+
+ if (daemon->priv->devkit_client != NULL) {
+ g_object_unref (daemon->priv->devkit_client);
+ }
+
+ if (daemon->priv->map_native_path_to_device != NULL) {
+ g_hash_table_unref (daemon->priv->map_native_path_to_device);
+ }
+
+ G_OBJECT_CLASS (devkit_power_daemon_parent_class)->finalize (object);
+}
+
+static gboolean
+pk_io_watch_have_data (GIOChannel *channel, GIOCondition condition, gpointer user_data)
+{
+ int fd;
+ PolKitContext *pk_context = user_data;
+ fd = g_io_channel_unix_get_fd (channel);
+ polkit_context_io_func (pk_context, fd);
+ return TRUE;
+}
+
+static int
+pk_io_add_watch (PolKitContext *pk_context, int fd)
+{
+ guint id = 0;
+ GIOChannel *channel;
+ channel = g_io_channel_unix_new (fd);
+ if (channel == NULL)
+ goto out;
+ id = g_io_add_watch (channel, G_IO_IN, pk_io_watch_have_data, pk_context);
+ if (id == 0) {
+ g_io_channel_unref (channel);
+ goto out;
+ }
+ g_io_channel_unref (channel);
+out:
+ return id;
+}
+
+static void
+pk_io_remove_watch (PolKitContext *pk_context, int watch_id)
+{
+ g_source_remove (watch_id);
+}
+
+static DBusHandlerResult
+_filter (DBusConnection *connection, DBusMessage *message, void *user_data)
+{
+ DevkitPowerDaemon *daemon = DEVKIT_POWER_DAEMON (user_data);
+ const char *interface;
+
+ interface = dbus_message_get_interface (message);
+
+ if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
+ /* pass NameOwnerChanged signals from the bus to PolKitTracker */
+ polkit_tracker_dbus_func (daemon->priv->pk_tracker, message);
+ }
+
+ if (interface != NULL && g_str_has_prefix (interface, "org.freedesktop.ConsoleKit")) {
+ /* pass ConsoleKit signals to PolKitTracker */
+ polkit_tracker_dbus_func (daemon->priv->pk_tracker, message);
+ }
+
+ /* other filters might want to process this message too */
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static void device_add (DevkitPowerDaemon *daemon, DevkitDevice *d, gboolean emit_event);
+static void device_remove (DevkitPowerDaemon *daemon, DevkitDevice *d);
+
+static void
+device_changed (DevkitPowerDaemon *daemon, DevkitDevice *d, gboolean synthesized)
+{
+ DevkitPowerDevice *device;
+ const char *native_path;
+
+ native_path = devkit_device_get_native_path (d);
+ device = g_hash_table_lookup (daemon->priv->map_native_path_to_device, native_path);
+ if (device != NULL) {
+ if (!devkit_power_device_changed (device, d, synthesized)) {
+ g_print ("changed triggered remove on %s\n", native_path);
+ device_remove (daemon, d);
+ } else {
+ g_print ("changed %s\n", native_path);
+ }
+ } else {
+ g_print ("treating change event as add on %s\n", native_path);
+ device_add (daemon, d, TRUE);
+ }
+}
+
+static gboolean
+device_went_away_remove_cb (gpointer key, gpointer value, gpointer user_data)
+{
+ if (value == user_data) {
+ g_print ("removed %s\n", (char *) key);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void
+device_went_away (gpointer user_data, GObject *where_the_object_was)
+{
+ DevkitPowerDaemon *daemon = DEVKIT_POWER_DAEMON (user_data);
+
+ g_hash_table_foreach_remove (daemon->priv->map_native_path_to_device,
+ device_went_away_remove_cb,
+ where_the_object_was);
+}
+
+static void
+device_add (DevkitPowerDaemon *daemon, DevkitDevice *d, gboolean emit_event)
+{
+ DevkitPowerDevice *device;
+ const char *native_path;
+
+ native_path = devkit_device_get_native_path (d);
+ device = g_hash_table_lookup (daemon->priv->map_native_path_to_device, native_path);
+ if (device != NULL) {
+ /* we already have the device; treat as change event */
+ g_print ("treating add event as change event on %s\n", native_path);
+ device_changed (daemon, d, FALSE);
+ } else {
+ device = devkit_power_device_new (daemon, d);
+
+ if (device != NULL) {
+ /* 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.
+ */
+ g_object_weak_ref (G_OBJECT (device), device_went_away, daemon);
+ g_hash_table_insert (daemon->priv->map_native_path_to_device,
+ g_strdup (native_path),
+ device);
+ g_print ("added %s\n", native_path);
+ if (emit_event) {
+ g_signal_emit (daemon, signals[DEVICE_ADDED_SIGNAL], 0,
+ devkit_power_device_get_object_path (device));
+ }
+ } else {
+ g_print ("ignoring add event on %s\n", native_path);
+ }
+ }
+}
+
+static void
+device_remove (DevkitPowerDaemon *daemon, DevkitDevice *d)
+{
+ DevkitPowerDevice *device;
+ const char *native_path;
+
+ native_path = devkit_device_get_native_path (d);
+ device = g_hash_table_lookup (daemon->priv->map_native_path_to_device, native_path);
+ if (device == NULL) {
+ g_print ("ignoring remove event on %s\n", native_path);
+ } else {
+ devkit_power_device_removed (device);
+ g_signal_emit (daemon, signals[DEVICE_REMOVED_SIGNAL], 0,
+ devkit_power_device_get_object_path (device));
+ g_object_unref (device);
+ }
+}
+
+static void
+device_event_signal_handler (DevkitClient *client,
+ const char *action,
+ DevkitDevice *device,
+ gpointer user_data)
+{
+ DevkitPowerDaemon *daemon = DEVKIT_POWER_DAEMON (user_data);
+
+ if (strcmp (action, "add") == 0) {
+ device_add (daemon, device, TRUE);
+ } else if (strcmp (action, "remove") == 0) {
+ device_remove (daemon, device);
+ } else if (strcmp (action, "change") == 0) {
+ device_changed (daemon, device, FALSE);
+ } else {
+ g_warning ("unhandled action '%s' on %s", action, devkit_device_get_native_path (device));
+ }
+}
+
+static gboolean
+register_power_daemon (DevkitPowerDaemon *daemon)
+{
+ DBusConnection *connection;
+ DBusError dbus_error;
+ GError *error = NULL;
+ const char *subsystems[] = {"power_supply", NULL};
+
+ daemon->priv->pk_context = polkit_context_new ();
+ polkit_context_set_io_watch_functions (daemon->priv->pk_context, pk_io_add_watch, pk_io_remove_watch);
+ if (!polkit_context_init (daemon->priv->pk_context, NULL)) {
+ g_critical ("cannot initialize libpolkit");
+ goto error;
+ }
+
+ error = NULL;
+ daemon->priv->system_bus_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (daemon->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 (daemon->priv->system_bus_connection);
+
+ daemon->priv->pk_tracker = polkit_tracker_new ();
+ polkit_tracker_set_system_bus_connection (daemon->priv->pk_tracker, connection);
+ polkit_tracker_init (daemon->priv->pk_tracker);
+
+ dbus_g_connection_register_g_object (daemon->priv->system_bus_connection, "/",
+ G_OBJECT (daemon));
+
+ daemon->priv->system_bus_proxy = dbus_g_proxy_new_for_name (daemon->priv->system_bus_connection,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS);
+
+ /* TODO FIXME: I'm pretty sure dbus-glib blows in a way that
+ * we can't say we're interested in all signals from all
+ * members on all interfaces for a given service... So we do
+ * this..
+ */
+
+ dbus_error_init (&dbus_error);
+
+ /* need to listen to NameOwnerChanged */
+ dbus_bus_add_match (connection,
+ "type='signal'"
+ ",interface='"DBUS_INTERFACE_DBUS"'"
+ ",sender='"DBUS_SERVICE_DBUS"'"
+ ",member='NameOwnerChanged'",
+ &dbus_error);
+
+ if (dbus_error_is_set (&dbus_error)) {
+ g_warning ("Cannot add match rule: %s: %s", dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto error;
+ }
+
+ /* need to listen to ConsoleKit signals */
+ dbus_bus_add_match (connection,
+ "type='signal',sender='org.freedesktop.ConsoleKit'",
+ &dbus_error);
+
+ if (dbus_error_is_set (&dbus_error)) {
+ g_warning ("Cannot add match rule: %s: %s", dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto error;
+ }
+
+ if (!dbus_connection_add_filter (connection,
+ _filter,
+ daemon,
+ NULL)) {
+ g_warning ("Cannot add D-Bus filter: %s: %s", dbus_error.name, dbus_error.message);
+ goto error;
+ }
+
+ /* connect to the DeviceKit daemon */
+ daemon->priv->devkit_client = devkit_client_new (subsystems);
+ if (!devkit_client_connect (daemon->priv->devkit_client, &error)) {
+ g_warning ("Couldn't open connection to DeviceKit daemon: %s", error->message);
+ g_error_free (error);
+ goto error;
+ }
+ g_signal_connect (daemon->priv->devkit_client, "device-event",
+ G_CALLBACK (device_event_signal_handler), daemon);
+
+ return TRUE;
+error:
+ return FALSE;
+}
+
+
+DevkitPowerDaemon *
+devkit_power_daemon_new (void)
+{
+ DevkitPowerDaemon *daemon;
+ GError *error = NULL;
+ GList *devices;
+ GList *l;
+ const char *subsystems[] = {"power_supply", NULL};
+
+ daemon = DEVKIT_POWER_DAEMON (g_object_new (DEVKIT_TYPE_POWER_DAEMON, NULL));
+
+ if (!register_power_daemon (DEVKIT_POWER_DAEMON (daemon))) {
+ g_object_unref (daemon);
+ return NULL;
+ }
+
+
+ devices = devkit_client_enumerate_by_subsystem (daemon->priv->devkit_client,
+ subsystems,
+ &error);
+ if (error != NULL) {
+ g_warning ("Cannot enumerate devices: %s", error->message);
+ g_error_free (error);
+ g_object_unref (daemon);
+ return NULL;
+ }
+ for (l = devices; l != NULL; l = l->next) {
+ DevkitDevice *device = l->data;
+ device_add (daemon, device, FALSE);
+ }
+ g_list_foreach (devices, (GFunc) g_object_unref, NULL);
+ g_list_free (devices);
+
+ return daemon;
+}
+
+PolKitCaller *
+devkit_power_damon_local_get_caller_for_context (DevkitPowerDaemon *daemon,
+ DBusGMethodInvocation *context)
+{
+ const char *sender;
+ GError *error;
+ DBusError dbus_error;
+ PolKitCaller *pk_caller;
+
+ sender = dbus_g_method_get_sender (context);
+ dbus_error_init (&dbus_error);
+ pk_caller = polkit_tracker_get_caller_from_dbus_name (daemon->priv->pk_tracker,
+ sender,
+ &dbus_error);
+ if (pk_caller == NULL) {
+ error = g_error_new (DEVKIT_POWER_DAEMON_ERROR,
+ DEVKIT_POWER_DAEMON_ERROR_GENERAL,
+ "Error getting information about caller: %s: %s",
+ dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return NULL;
+ }
+
+ return pk_caller;
+}
+
+gboolean
+devkit_power_damon_local_check_auth (DevkitPowerDaemon *daemon,
+ PolKitCaller *pk_caller,
+ const char *action_id,
+ DBusGMethodInvocation *context)
+{
+ gboolean ret;
+ GError *error;
+ DBusError d_error;
+ PolKitAction *pk_action;
+ PolKitResult pk_result;
+
+ ret = FALSE;
+
+ pk_action = polkit_action_new ();
+ polkit_action_set_action_id (pk_action, action_id);
+ pk_result = polkit_context_is_caller_authorized (daemon->priv->pk_context,
+ pk_action,
+ pk_caller,
+ TRUE,
+ NULL);
+ if (pk_result == POLKIT_RESULT_YES) {
+ ret = TRUE;
+ } else {
+
+ dbus_error_init (&d_error);
+ polkit_dbus_error_generate (pk_action, pk_result, &d_error);
+ error = NULL;
+ dbus_set_g_error (&error, &d_error);
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ dbus_error_free (&d_error);
+ }
+ polkit_action_unref (pk_action);
+ return ret;
+}
+
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+#if 0
+static gboolean
+throw_error (DBusGMethodInvocation *context, int error_code, const char *format, ...)
+{
+ GError *error;
+ va_list args;
+ char *message;
+
+ va_start (args, format);
+ message = g_strdup_vprintf (format, args);
+ va_end (args);
+
+ error = g_error_new (DEVKIT_POWER_DAEMON_ERROR,
+ error_code,
+ message);
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ g_free (message);
+ return TRUE;
+}
+#endif
+
+/*--------------------------------------------------------------------------------------------------------------*/
+/* exported methods */
+
+static void
+enumerate_cb (gpointer key, gpointer value, gpointer user_data)
+{
+ DevkitPowerDevice *device = DEVKIT_POWER_DEVICE (value);
+ GPtrArray *object_paths = user_data;
+ g_ptr_array_add (object_paths, g_strdup (devkit_power_device_get_object_path (device)));
+}
+
+gboolean
+devkit_power_daemon_enumerate_devices (DevkitPowerDaemon *daemon,
+ DBusGMethodInvocation *context)
+{
+ GPtrArray *object_paths;
+ object_paths = g_ptr_array_new ();
+ g_hash_table_foreach (daemon->priv->map_native_path_to_device, enumerate_cb, object_paths);
+ dbus_g_method_return (context, object_paths);
+ g_ptr_array_foreach (object_paths, (GFunc) g_free, NULL);
+ g_ptr_array_free (object_paths, TRUE);
+ return TRUE;
+}
diff --git a/src/devkit-power-daemon.h b/src/devkit-power-daemon.h
new file mode 100644
index 0000000..e877730
--- /dev/null
+++ b/src/devkit-power-daemon.h
@@ -0,0 +1,84 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; 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 __DEVKIT_POWER_DAEMON_H__
+#define __DEVKIT_POWER_DAEMON_H__
+
+#include <glib-object.h>
+#include <polkit-dbus/polkit-dbus.h>
+#include <dbus/dbus-glib.h>
+
+G_BEGIN_DECLS
+
+#define DEVKIT_TYPE_POWER_DAEMON (devkit_power_daemon_get_type ())
+#define DEVKIT_POWER_DAEMON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DEVKIT_TYPE_POWER_DAEMON, DevkitPowerDaemon))
+#define DEVKIT_POWER_DAEMON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), DEVKIT_TYPE_POWER_DAEMON, DevkitPowerDaemonClass))
+#define DEVKIT_IS_POWER_DAEMON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), DEVKIT_TYPE_POWER_DAEMON))
+#define DEVKIT_IS_POWER_DAEMON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DEVKIT_TYPE_POWER_DAEMON))
+#define DEVKIT_POWER_DAEMON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DEVKIT_TYPE_POWER_DAEMON, DevkitPowerDaemonClass))
+
+typedef struct DevkitPowerDaemonPrivate DevkitPowerDaemonPrivate;
+
+typedef struct
+{
+ GObject parent;
+ DevkitPowerDaemonPrivate *priv;
+} DevkitPowerDaemon;
+
+typedef struct
+{
+ GObjectClass parent_class;
+} DevkitPowerDaemonClass;
+
+typedef enum
+{
+ DEVKIT_POWER_DAEMON_ERROR_GENERAL,
+ DEVKIT_POWER_DAEMON_ERROR_NOT_SUPPORTED,
+ DEVKIT_POWER_DAEMON_ERROR_NO_SUCH_DEVICE,
+ DEVKIT_POWER_DAEMON_NUM_ERRORS
+} DevkitPowerDaemonError;
+
+#define DEVKIT_POWER_DAEMON_ERROR devkit_power_daemon_error_quark ()
+
+GType devkit_power_daemon_error_get_type (void);
+#define DEVKIT_POWER_DAEMON_TYPE_ERROR (devkit_power_daemon_error_get_type ())
+
+GQuark devkit_power_daemon_error_quark (void);
+GType devkit_power_daemon_get_type (void);
+DevkitPowerDaemon *devkit_power_daemon_new (void);
+
+/* local methods */
+
+PolKitCaller *devkit_power_damon_local_get_caller_for_context (DevkitPowerDaemon *daemon,
+ DBusGMethodInvocation *context);
+
+gboolean devkit_power_damon_local_check_auth (DevkitPowerDaemon *daemon,
+ PolKitCaller *pk_caller,
+ const char *action_id,
+ DBusGMethodInvocation *context);
+
+/* exported methods */
+
+gboolean devkit_power_daemon_enumerate_devices (DevkitPowerDaemon *daemon,
+ DBusGMethodInvocation *context);
+
+G_END_DECLS
+
+#endif /* __DEVKIT_POWER_DAEMON_H__ */
diff --git a/src/devkit-power-device.c b/src/devkit-power-device.c
new file mode 100644
index 0000000..0c6742d
--- /dev/null
+++ b/src/devkit-power-device.c
@@ -0,0 +1,92 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.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 "devkit-power-device.h"
+#include "devkit-power-source.h"
+
+static void devkit_power_device_class_init (DevkitPowerDeviceClass *klass);
+static void devkit_power_device_init (DevkitPowerDevice *seat);
+
+G_DEFINE_TYPE (DevkitPowerDevice, devkit_power_device, G_TYPE_OBJECT)
+
+#define DEVKIT_POWER_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DEVKIT_TYPE_POWER_DEVICE, DevkitPowerDevicePrivate))
+
+static void
+devkit_power_device_class_init (DevkitPowerDeviceClass *klass)
+{
+}
+
+static void
+devkit_power_device_init (DevkitPowerDevice *device)
+{
+}
+
+void
+devkit_power_device_removed (DevkitPowerDevice *device)
+{
+ DevkitPowerDeviceClass *klass = DEVKIT_POWER_DEVICE_GET_CLASS (device);
+ klass->removed (device);
+}
+
+DevkitPowerDevice *
+devkit_power_device_new (DevkitPowerDaemon *daemon, DevkitDevice *d)
+{
+ const char *subsys;
+ DevkitPowerDevice *device;
+
+ device = NULL;
+
+ subsys = devkit_device_get_subsystem (d);
+ if (strcmp (subsys, "power_supply") == 0) {
+ device = DEVKIT_POWER_DEVICE (devkit_power_source_new (daemon, d));
+ }
+
+ return device;
+}
+
+gboolean
+devkit_power_device_changed (DevkitPowerDevice *device, DevkitDevice *d, gboolean synthesized)
+{
+ DevkitPowerDeviceClass *klass = DEVKIT_POWER_DEVICE_GET_CLASS (device);
+ return (klass->changed (device, d, synthesized));
+}
+
+const char *
+devkit_power_device_get_object_path (DevkitPowerDevice *device)
+{
+ DevkitPowerDeviceClass *klass = DEVKIT_POWER_DEVICE_GET_CLASS (device);
+ return (klass->get_object_path (device));
+}
diff --git a/src/devkit-power-device.h b/src/devkit-power-device.h
new file mode 100644
index 0000000..3ddb3d3
--- /dev/null
+++ b/src/devkit-power-device.h
@@ -0,0 +1,68 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; 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 __DEVKIT_POWER_DEVICE_H__
+#define __DEVKIT_POWER_DEVICE_H__
+
+#include <glib-object.h>
+#include <polkit-dbus/polkit-dbus.h>
+#include <devkit-gobject.h>
+
+#include "devkit-power-daemon.h"
+
+G_BEGIN_DECLS
+
+#define DEVKIT_TYPE_POWER_DEVICE (devkit_power_device_get_type ())
+#define DEVKIT_POWER_DEVICE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DEVKIT_TYPE_POWER_DEVICE, DevkitPowerDevice))
+#define DEVKIT_POWER_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), DEVKIT_TYPE_POWER_DEVICE, DevkitPowerDeviceClass))
+#define DEVKIT_IS_POWER_DEVICE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), DEVKIT_TYPE_POWER_DEVICE))
+#define DEVKIT_IS_POWER_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DEVKIT_TYPE_POWER_DEVICE))
+#define DEVKIT_POWER_DEVICE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DEVKIT_TYPE_POWER_DEVICE, DevkitPowerDeviceClass))
+
+typedef struct
+{
+ GObject parent;
+} DevkitPowerDevice;
+
+typedef struct
+{
+ GObjectClass parent_class;
+
+ /* vtable */
+ gboolean (*changed) (DevkitPowerDevice *device,
+ DevkitDevice *d,
+ gboolean synthesized);
+ void (*removed) (DevkitPowerDevice *device);
+ const char *(*get_object_path) (DevkitPowerDevice *device);
+} DevkitPowerDeviceClass;
+
+GType devkit_power_device_get_type (void);
+DevkitPowerDevice *devkit_power_device_new (DevkitPowerDaemon *daemon,
+ DevkitDevice *d);
+gboolean devkit_power_device_changed (DevkitPowerDevice *device,
+ DevkitDevice *d,
+ gboolean synthesized);
+void devkit_power_device_removed (DevkitPowerDevice *device);
+
+const char *devkit_power_device_get_object_path (DevkitPowerDevice *device);
+
+G_END_DECLS
+
+#endif /* __DEVKIT_POWER_DEVICE_H__ */
diff --git a/src/devkit-power-marshal.list b/src/devkit-power-marshal.list
new file mode 100644
index 0000000..98218d7
--- /dev/null
+++ b/src/devkit-power-marshal.list
@@ -0,0 +1,2 @@
+VOID:BOOLEAN,STRING,BOOLEAN,INT,INT,STRING,DOUBLE
+VOID:STRING,BOOLEAN,STRING,BOOLEAN,INT,INT,STRING,DOUBLE
diff --git a/src/devkit-power-source.c b/src/devkit-power-source.c
new file mode 100644
index 0000000..9172c59
--- /dev/null
+++ b/src/devkit-power-source.c
@@ -0,0 +1,593 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; 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
+ *
+ */
+
+#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 "devkit-power-source.h"
+#include "devkit-power-marshal.h"
+
+/*--------------------------------------------------------------------------------------------------------------*/
+#include "devkit-power-source-glue.h"
+
+typedef enum {
+ DEVKIT_POWER_SOURCE_TYPE_LINE_POWER,
+ DEVKIT_POWER_SOURCE_TYPE_BATTERY,
+} DevkitPowerSourceType;
+
+struct DevkitPowerSourcePrivate
+{
+ DBusGConnection *system_bus_connection;
+ DBusGProxy *system_bus_proxy;
+ DevkitPowerDaemon *daemon;
+ DevkitDevice *d;
+
+ char *object_path;
+ char *native_path;
+
+ guint poll_timer_id;
+
+ char *vendor;
+ char *model;
+ char *serial;
+ GTimeVal update_time;
+ DevkitPowerSourceType type;
+
+ gboolean line_power_online;
+
+ double battery_energy;
+ double battery_energy_empty;
+ double battery_energy_empty_design;
+ double battery_energy_full;
+ double battery_energy_full_design;
+ double battery_energy_rate;
+ gint64 battery_time_to_empty;
+ gint64 battery_time_to_full;
+ double battery_percentage;
+ char *battery_technology;
+};
+
+static void devkit_power_source_class_init (DevkitPowerSourceClass *klass);
+static void devkit_power_source_init (DevkitPowerSource *seat);
+static void devkit_power_source_finalize (GObject *object);
+
+static gboolean update (DevkitPowerSource *source);
+
+enum
+{
+ PROP_0,
+ PROP_NATIVE_PATH,
+ PROP_VENDOR,
+ PROP_MODEL,
+ PROP_SERIAL,
+ PROP_UPDATE_TIME,
+ PROP_TYPE,
+ PROP_LINE_POWER_ONLINE,
+ PROP_BATTERY_ENERGY,
+ PROP_BATTERY_ENERGY_EMPTY,
+ PROP_BATTERY_ENERGY_EMPTY_DESIGN,
+ 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 (DevkitPowerSource, devkit_power_source, DEVKIT_TYPE_POWER_DEVICE)
+#define DEVKIT_POWER_SOURCE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DEVKIT_TYPE_POWER_SOURCE, DevkitPowerSourcePrivate))
+
+static const char *devkit_power_source_get_object_path (DevkitPowerDevice *device);
+static void devkit_power_source_removed (DevkitPowerDevice *device);
+static gboolean devkit_power_source_changed (DevkitPowerDevice *device,
+ DevkitDevice *d,
+ gboolean synthesized);
+
+static void
+get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ DevkitPowerSource *source = DEVKIT_POWER_SOURCE (object);
+
+ switch (prop_id) {
+ case PROP_NATIVE_PATH:
+ g_value_set_string (value, source->priv->native_path);
+ break;
+ case PROP_VENDOR:
+ g_value_set_string (value, source->priv->vendor);
+ break;
+ case PROP_MODEL:
+ g_value_set_string (value, source->priv->model);
+ break;
+ case PROP_SERIAL:
+ g_value_set_string (value, source->priv->serial);
+ break;
+ case PROP_UPDATE_TIME:
+ g_value_set_uint64 (value, source->priv->update_time.tv_sec);
+ break;
+ case PROP_TYPE:
+ g_value_set_string (value, source->priv->type == DEVKIT_POWER_SOURCE_TYPE_LINE_POWER
+ ? "line-power" : "battery");
+ break;
+
+ case PROP_LINE_POWER_ONLINE:
+ g_value_set_boolean (value, source->priv->line_power_online);
+ break;
+
+ case PROP_BATTERY_ENERGY:
+ g_value_set_double (value, source->priv->battery_energy);
+ break;
+ case PROP_BATTERY_ENERGY_EMPTY:
+ g_value_set_double (value, source->priv->battery_energy_empty);
+ break;
+ case PROP_BATTERY_ENERGY_EMPTY_DESIGN:
+ g_value_set_double (value, source->priv->battery_energy_empty_design);
+ break;
+ case PROP_BATTERY_ENERGY_FULL:
+ g_value_set_double (value, source->priv->battery_energy_full);
+ break;
+ case PROP_BATTERY_ENERGY_FULL_DESIGN:
+ g_value_set_double (value, source->priv->battery_energy_full_design);
+ break;
+ case PROP_BATTERY_ENERGY_RATE:
+ g_value_set_double (value, source->priv->battery_energy_rate);
+ break;
+ case PROP_BATTERY_TIME_TO_EMPTY:
+ g_value_set_int64 (value, source->priv->battery_time_to_empty);
+ break;
+ case PROP_BATTERY_TIME_TO_FULL:
+ g_value_set_int64 (value, source->priv->battery_time_to_full);
+ break;
+ case PROP_BATTERY_PERCENTAGE:
+ g_value_set_double (value, source->priv->battery_percentage);
+ break;
+
+ case PROP_BATTERY_TECHNOLOGY:
+ g_value_set_string (value, source->priv->battery_technology);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+
+static void
+devkit_power_source_class_init (DevkitPowerSourceClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ DevkitPowerDeviceClass *device_class = DEVKIT_POWER_DEVICE_CLASS (klass);
+
+ object_class->finalize = devkit_power_source_finalize;
+ object_class->get_property = get_property;
+ device_class->changed = devkit_power_source_changed;
+ device_class->removed = devkit_power_source_removed;
+ device_class->get_object_path = devkit_power_source_get_object_path;
+
+ g_type_class_add_private (klass, sizeof (DevkitPowerSourcePrivate));
+
+ 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 (DEVKIT_TYPE_POWER_SOURCE, &dbus_glib_devkit_power_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_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_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_EMPTY_DESIGN,
+ g_param_spec_double ("battery-energy-empty-design", 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));
+}
+
+static void
+devkit_power_source_init (DevkitPowerSource *source)
+{
+ source->priv = DEVKIT_POWER_SOURCE_GET_PRIVATE (source);
+ source->priv->battery_time_to_empty = -1;
+ source->priv->battery_time_to_full = -1;
+}
+
+static void
+devkit_power_source_finalize (GObject *object)
+{
+ DevkitPowerSource *source;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (DEVKIT_IS_POWER_SOURCE (object));
+
+ source = DEVKIT_POWER_SOURCE (object);
+ g_return_if_fail (source->priv != NULL);
+
+ g_object_unref (source->priv->d);
+ g_object_unref (source->priv->daemon);
+
+ g_free (source->priv->native_path);
+
+ g_free (source->priv->vendor);
+ g_free (source->priv->model);
+ g_free (source->priv->serial);
+
+ if (source->priv->poll_timer_id > 0)
+ g_source_remove (source->priv->poll_timer_id);
+
+ G_OBJECT_CLASS (devkit_power_source_parent_class)->finalize (object);
+}
+
+static char *
+compute_object_path_from_basename (const char *native_path_basename)
+{
+ char *basename;
+ char *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;
+}
+
+static char *
+compute_object_path (const char *native_path)
+{
+ char *basename;
+ char *object_path;
+
+ basename = g_path_get_basename (native_path);
+ object_path = compute_object_path_from_basename (basename);
+ g_free (basename);
+ return object_path;
+}
+
+static gboolean
+register_power_source (DevkitPowerSource *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 = compute_object_path (source->priv->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;
+}
+
+DevkitPowerSource *
+devkit_power_source_new (DevkitPowerDaemon *daemon, DevkitDevice *d)
+{
+ DevkitPowerSource *source;
+ const char *native_path;
+
+ source = NULL;
+ native_path = devkit_device_get_native_path (d);
+
+ source = DEVKIT_POWER_SOURCE (g_object_new (DEVKIT_TYPE_POWER_SOURCE, NULL));
+ source->priv->d = g_object_ref (d);
+ source->priv->daemon = g_object_ref (daemon);
+ source->priv->native_path = g_strdup (native_path);
+
+ if (sysfs_file_exists (native_path, "online")) {
+ source->priv->type = DEVKIT_POWER_SOURCE_TYPE_LINE_POWER;
+ } else {
+ source->priv->type = DEVKIT_POWER_SOURCE_TYPE_BATTERY;
+ }
+
+ if (!update (source)) {
+ g_object_unref (source);
+ source = NULL;
+ goto out;
+ }
+
+ if (! register_power_source (DEVKIT_POWER_SOURCE (source))) {
+ g_object_unref (source);
+ source = NULL;
+ goto out;
+ }
+
+out:
+ return source;
+}
+
+static void
+emit_changed (DevkitPowerSource *source)
+{
+ g_print ("emitting changed on %s\n", source->priv->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);
+}
+
+static gboolean
+devkit_power_source_changed (DevkitPowerDevice *device, DevkitDevice *d, gboolean synthesized)
+{
+ DevkitPowerSource *source = DEVKIT_POWER_SOURCE (device);
+ gboolean keep_source;
+
+ g_object_unref (source->priv->d);
+ source->priv->d = g_object_ref (d);
+
+ keep_source = update (source);
+
+ /* this 'change' event might prompt us to remove the source */
+ if (!keep_source)
+ goto out;
+
+ /* no, it's good .. keep it */
+ emit_changed (source);
+
+out:
+ return keep_source;
+}
+
+void
+devkit_power_source_removed (DevkitPowerDevice *device)
+{
+}
+
+static const char *
+devkit_power_source_get_object_path (DevkitPowerDevice *device)
+{
+ DevkitPowerSource *source = DEVKIT_POWER_SOURCE (device);
+ return source->priv->object_path;
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static gboolean
+update_line_power (DevkitPowerSource *source)
+{
+ source->priv->line_power_online = sysfs_get_int (source->priv->native_path, "online");
+ return TRUE;
+}
+
+static gboolean
+update_battery (DevkitPowerSource *source)
+{
+ char *status;
+ gboolean is_charging;
+ gboolean is_discharging;
+
+ /* TODO: this needs to handle lots of special cases when certain
+ * files exist, it needs to prefer _avg to _now etc. etc. etc.
+ *
+ * This is just a very quick hack for now.
+ */
+
+ status = g_strstrip (sysfs_get_string (source->priv->native_path, "status"));
+ is_charging = strcasecmp (status, "charging") == 0;
+ is_discharging = strcasecmp (status, "discharging") == 0;
+
+ source->priv->battery_energy =
+ sysfs_get_double (source->priv->native_path, "energy_now") / 1000000.0;
+ source->priv->battery_energy_full =
+ sysfs_get_double (source->priv->native_path, "energy_full") / 1000000.0;
+ source->priv->battery_energy_full_design =
+ sysfs_get_double (source->priv->native_path, "energy_full_design") / 1000000.0;
+ source->priv->battery_energy_rate =
+ fabs (sysfs_get_double (source->priv->native_path, "current_now") / 1000000.0);
+ if (is_charging)
+ source->priv->battery_energy_rate *= -1.0;
+
+ source->priv->battery_percentage = 100.0 * source->priv->battery_energy / source->priv->battery_energy_full;
+ if (source->priv->battery_percentage < 0)
+ source->priv->battery_percentage = 0;
+ if (source->priv->battery_percentage > 100.0)
+ source->priv->battery_percentage = 100.0;
+
+ g_free (status);
+ return TRUE;
+}
+
+static gboolean
+_poll_battery (DevkitPowerSource *source)
+{
+ g_warning ("No updates on source %s for 30 seconds; forcing update", source->priv->native_path);
+ source->priv->poll_timer_id = 0;
+ update (source);
+ emit_changed (source);
+ return FALSE;
+}
+
+static gboolean
+update (DevkitPowerSource *source)
+{
+ gboolean ret;
+
+ if (source->priv->poll_timer_id > 0) {
+ g_source_remove (source->priv->poll_timer_id);
+ source->priv->poll_timer_id = 0;
+ }
+
+ /* initial values */
+ if (source->priv->vendor == NULL) {
+ char *s;
+
+ s = g_strstrip (sysfs_get_string (source->priv->native_path, "technology"));
+ if (strcmp (s, "Unknown") != 0)
+ source->priv->battery_technology = s;
+ else
+ g_free (s);
+
+ source->priv->vendor = g_strstrip (sysfs_get_string (source->priv->native_path, "manufacturer"));
+ source->priv->model = g_strstrip (sysfs_get_string (source->priv->native_path, "model_name"));
+ source->priv->serial = g_strstrip (sysfs_get_string (source->priv->native_path, "serial_number"));
+ }
+
+ g_get_current_time (&(source->priv->update_time));
+
+ switch (source->priv->type) {
+ case DEVKIT_POWER_SOURCE_TYPE_LINE_POWER:
+ ret = update_line_power (source);
+ break;
+ case DEVKIT_POWER_SOURCE_TYPE_BATTERY:
+
+ ret = update_battery (source);
+
+ /* Seems that we don't get change uevents from the
+ * kernel; set up a timer to poll
+ *
+ * TODO: perhaps only do this if running on battery.
+ */
+ source->priv->poll_timer_id = g_timeout_add_seconds (30, (GSourceFunc) _poll_battery, source);
+
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ return ret;
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+gboolean
+devkit_power_source_refresh (DevkitPowerSource *power_source,
+ DBusGMethodInvocation *context)
+{
+ update (power_source);
+ dbus_g_method_return (context);
+ return TRUE;
+}
diff --git a/src/devkit-power-source.h b/src/devkit-power-source.h
new file mode 100644
index 0000000..23ea648
--- /dev/null
+++ b/src/devkit-power-source.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; 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 __DEVKIT_POWER_SOURCE_H__
+#define __DEVKIT_POWER_SOURCE_H__
+
+#include <glib-object.h>
+#include <polkit-dbus/polkit-dbus.h>
+#include <devkit-gobject.h>
+
+#include "devkit-power-daemon.h"
+#include "devkit-power-device.h"
+
+G_BEGIN_DECLS
+
+#define DEVKIT_TYPE_POWER_SOURCE (devkit_power_source_get_type ())
+#define DEVKIT_POWER_SOURCE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DEVKIT_TYPE_POWER_SOURCE, DevkitPowerSource))
+#define DEVKIT_POWER_SOURCE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), DEVKIT_TYPE_POWER_SOURCE, DevkitPowerSourceClass))
+#define DEVKIT_IS_POWER_SOURCE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), DEVKIT_TYPE_POWER_SOURCE))
+#define DEVKIT_IS_POWER_SOURCE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DEVKIT_TYPE_POWER_SOURCE))
+#define DEVKIT_POWER_SOURCE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DEVKIT_TYPE_POWER_SOURCE, DevkitPowerSourceClass))
+
+typedef struct DevkitPowerSourcePrivate DevkitPowerSourcePrivate;
+
+typedef struct
+{
+ DevkitPowerDevice parent;
+ DevkitPowerSourcePrivate *priv;
+} DevkitPowerSource;
+
+typedef struct
+{
+ DevkitPowerDeviceClass parent_class;
+} DevkitPowerSourceClass;
+
+GType devkit_power_source_get_type (void);
+DevkitPowerSource *devkit_power_source_new (DevkitPowerDaemon *daemon,
+ DevkitDevice *d);
+
+/* exported methods */
+
+gboolean devkit_power_source_refresh (DevkitPowerSource *power_source,
+ DBusGMethodInvocation *context);
+
+G_END_DECLS
+
+#endif /* __DEVKIT_POWER_SOURCE_H__ */
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..ee15b87
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,157 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 David Zeuthen <david@fubar.dk>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+
+#include <glib.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 "devkit-power-daemon.h"
+
+#define NAME_TO_CLAIM "org.freedesktop.DeviceKit.Power"
+
+static gboolean
+acquire_name_on_proxy (DBusGProxy *bus_proxy)
+{
+ GError *error;
+ guint result;
+ gboolean res;
+ gboolean ret;
+
+ ret = FALSE;
+
+ if (bus_proxy == NULL) {
+ goto out;
+ }
+
+ error = NULL;
+ res = dbus_g_proxy_call (bus_proxy,
+ "RequestName",
+ &error,
+ G_TYPE_STRING, NAME_TO_CLAIM,
+ G_TYPE_UINT, 0,
+ G_TYPE_INVALID,
+ G_TYPE_UINT, &result,
+ G_TYPE_INVALID);
+ if (! res) {
+ if (error != NULL) {
+ g_warning ("Failed to acquire %s: %s", NAME_TO_CLAIM, error->message);
+ g_error_free (error);
+ } else {
+ g_warning ("Failed to acquire %s", NAME_TO_CLAIM);
+ }
+ goto out;
+ }
+
+ if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+ if (error != NULL) {
+ g_warning ("Failed to acquire %s: %s", NAME_TO_CLAIM, error->message);
+ g_error_free (error);
+ } else {
+ g_warning ("Failed to acquire %s", NAME_TO_CLAIM);
+ }
+ goto out;
+ }
+
+ ret = TRUE;
+
+ out:
+ return ret;
+}
+
+int
+main (int argc, char **argv)
+{
+ GError *error;
+ GMainLoop *loop;
+ DevkitPowerDaemon *power_daemon;
+ GOptionContext *context;
+ DBusGProxy *bus_proxy;
+ DBusGConnection *bus;
+ int ret;
+ static GOptionEntry entries [] = {
+ { NULL }
+ };
+
+ ret = 1;
+
+ g_type_init ();
+
+ context = g_option_context_new ("DeviceKit Power Daemon");
+ g_option_context_add_main_entries (context, entries, NULL);
+ g_option_context_parse (context, &argc, &argv, NULL);
+ g_option_context_free (context);
+
+ error = NULL;
+ bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (bus == NULL) {
+ g_warning ("Couldn't connect to system bus: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ bus_proxy = dbus_g_proxy_new_for_name (bus,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS);
+ if (bus_proxy == NULL) {
+ g_warning ("Could not construct bus_proxy object; bailing out");
+ goto out;
+ }
+
+ if (!acquire_name_on_proxy (bus_proxy) ) {
+ g_warning ("Could not acquire name; bailing out");
+ goto out;
+ }
+
+ g_debug ("Starting devkit-power-daemon version %s", VERSION);
+
+ power_daemon = devkit_power_daemon_new ();
+
+ if (power_daemon == NULL) {
+ goto out;
+ }
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ g_main_loop_run (loop);
+
+ g_object_unref (power_daemon);
+ g_main_loop_unref (loop);
+ ret = 0;
+
+out:
+ return ret;
+}
diff --git a/src/org.freedesktop.DeviceKit.Power.Source.xml b/src/org.freedesktop.DeviceKit.Power.Source.xml
new file mode 100644
index 0000000..a98dbbd
--- /dev/null
+++ b/src/org.freedesktop.DeviceKit.Power.Source.xml
@@ -0,0 +1,228 @@
+<!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.Disks.Power.Source.GeneralError">
+]>
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+ <interface name="org.freedesktop.DeviceKit.Power.Source">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ TODO: some explanatory text etc. etc. Mention that we
+ collect history to provide more precise values of
+ battery-time-to-empty, battery-time-to-full. Go into detail
+ with the algorithms.
+ </doc:para>
+ <doc:para>
+ TODO: do we need to export voltage and other things? Do we need to export raw data?
+ </doc:para>
+ <doc:para>
+ Unless otherwise noted, an empty string or the value 0 in a
+ property means not set.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+
+
+ <!-- ************************************************************ -->
+
+ <method name="Refresh">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Refreshes the data collected from the power source.
+ </doc:para>
+ </doc:description>
+ <doc:permission>Callers need the org.freedesktop.devicekit.power.refresh-power-source authorization</doc:permission>
+ <doc:errors>
+ <doc:error name="&ERROR_GENERAL;">if an error occured while refreshing</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <signal name="Changed">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Some value on the power source changed.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <!-- ************************************************************ -->
+
+ <property name="native-path" type="s" access="read">
+ <doc:doc><doc:description><doc:para>
+ OS specific native path of the power source. On Linux this
+ is the sysfs path, for
+ example <doc:tt>/sys/devices/LNXSYSTM:00/device:00/PNP0C0A:00/power_supply/BAT0</doc:tt>. Is
+ blank if the device is being driven by a user space
+ driver.
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="vendor" type="s" access="read">
+ <doc:doc><doc:description><doc:para>
+ Name of the vendor of the battery.
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="model" type="s" access="read">
+ <doc:doc><doc:description><doc:para>
+ Name of the model of this battery.
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="serial" type="s" access="read">
+ <doc:doc><doc:description><doc:para>
+ Unique serial number of the battery.
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="update-time" type="t" access="read">
+ <doc:doc><doc:description><doc:para>
+ The point in time (seconds since the Epoch Jan 1, 1970
+ 0:00 UTC) that data was read from the power source.
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="type" type="s" access="read">
+ <doc:doc><doc:description><doc:para>
+ Type of power source. Known values are "battery" and "line-power".
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="line-power-online" type="b" access="read">
+ <doc:doc><doc:description><doc:para>
+ Whether power is currently being provided through line power.
+ This property is only valid if the property
+ <doc:ref type="property" to="Source:type">type</doc:ref>
+ has the value "line-power".
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="battery-energy" type="d" access="read">
+ <doc:doc><doc:description><doc:para>
+ Amount of energy (measured in Wh) currently available in
+ the power source.
+ </doc:para><doc:para>
+ This property is only valid if the property
+ <doc:ref type="property" to="Source:type">type</doc:ref>
+ has the value "battery".
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="battery-energy-empty" type="d" access="read">
+ <doc:doc><doc:description><doc:para>
+ Amount of energy (measured in Wh) in the power source when
+ it's considered to be empty.
+ </doc:para><doc:para>
+ This property is only valid if the property
+ <doc:ref type="property" to="Source:type">type</doc:ref>
+ has the value "battery".
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="battery-energy-empty-design" type="d" access="read">
+ <doc:doc><doc:description><doc:para>
+ Amount of energy (measured in Wh) the power source is
+ designed to hold when it's considered to be empty.
+ </doc:para><doc:para>
+ This property is only valid if the property
+ <doc:ref type="property" to="Source:type">type</doc:ref>
+ has the value "battery".
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="battery-energy-full" type="d" access="read">
+ <doc:doc><doc:description><doc:para>
+ Amount of energy (measured in Wh) in the power source when
+ it's considered full.
+ </doc:para><doc:para>
+ This property is only valid if the property
+ <doc:ref type="property" to="Source:type">type</doc:ref>
+ has the value "battery".
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="battery-energy-full-design" type="d" access="read">
+ <doc:doc><doc:description><doc:para>
+ Amount of energy (measured in Wh) the power source is
+ designed to hold when it's considered full.
+ </doc:para><doc:para>
+ This property is only valid if the property
+ <doc:ref type="property" to="Source:type">type</doc:ref>
+ has the value "battery".
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="battery-energy-rate" type="d" access="read">
+ <doc:doc><doc:description><doc:para>
+ Amount of energy being drained from the source, measured
+ in W. If positive, the source is being discharged, if
+ negative it's being charged.
+ </doc:para><doc:para>
+ This property is only valid if the property
+ <doc:ref type="property" to="Source:type">type</doc:ref>
+ has the value "battery".
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="battery-time-to-empty" type="x" access="read">
+ <doc:doc><doc:description><doc:para>
+ Number of seconds until the power source is considered empty.
+ Is set to -1 if unknown.
+ </doc:para><doc:para>
+ This property is only valid if the property
+ <doc:ref type="property" to="Source:type">type</doc:ref>
+ has the value "battery".
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="battery-time-to-full" type="x" access="read">
+ <doc:doc><doc:description><doc:para>
+ Number of seconds until the power source is considered full.
+ Is set to -1 if unknown.
+ </doc:para><doc:para>
+ This property is only valid if the property
+ <doc:ref type="property" to="Source:type">type</doc:ref>
+ has the value "battery".
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="battery-percentage" type="d" access="read">
+ <doc:doc><doc:description><doc:para>
+ The amount of energy left in the power source expressed as
+ a percentage between 0 and 100. Typically this is the same as
+ (<doc:ref type="property" to="Source:battery-energy">battery-energy</doc:ref> -
+ <doc:ref type="property" to="Source:battery-energy-empty">battery-energy-empty</doc:ref>) /
+ (<doc:ref type="property" to="Source:battery-energy-full">battery-energy-full</doc:ref> -
+ <doc:ref type="property" to="Source:battery-energy-empty">battery-energy-empty</doc:ref>).
+ However, some primitive power sources are capable of only
+ reporting percentages and in this case the battery-energy-*
+ properties will be unset while this property is set.
+ </doc:para><doc:para>
+ This property is only valid if the property
+ <doc:ref type="property" to="Source:type">type</doc:ref>
+ has the value "battery".
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="battery-technology" type="s" access="read">
+ <doc:doc><doc:description><doc:para>
+ Technology used in the battery; known values are "Li-ion".
+ </doc:para><doc:para>
+ This property is only valid if the property
+ <doc:ref type="property" to="Source:type">type</doc:ref>
+ has the value "battery".
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ </interface>
+
+</node>
diff --git a/src/org.freedesktop.DeviceKit.Power.xml b/src/org.freedesktop.DeviceKit.Power.xml
new file mode 100644
index 0000000..f206b56
--- /dev/null
+++ b/src/org.freedesktop.DeviceKit.Power.xml
@@ -0,0 +1,77 @@
+<!DOCTYPE node PUBLIC
+"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+
+ <interface name="org.freedesktop.DeviceKit.Power">
+
+ <!-- ************************************************************ -->
+
+ <method name="EnumerateDevices">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="devices" direction="out" type="ao">
+ <doc:doc><doc:summary>An array of object paths for devices.</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Enumerate all disks on the system.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <signal name="DeviceAdded">
+ <arg name="device" type="o">
+ <doc:doc><doc:summary>Object path of device that was added.</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Emitted when a device is added.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <!-- ************************************************************ -->
+
+ <signal name="DeviceRemoved">
+ <arg name="device" type="o">
+ <doc:doc><doc:summary>Object path of device that was removed.</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Emitted when a device is removed.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <!-- ************************************************************ -->
+
+ <signal name="DeviceChanged">
+ <arg name="device" type="o">
+ <doc:doc><doc:summary>Object path of device that was changed.</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Emitted when a device changed.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <!-- ************************************************************ -->
+
+ </interface>
+
+</node>
diff --git a/src/sysfs-utils.c b/src/sysfs-utils.c
new file mode 100644
index 0000000..0a06c2d
--- /dev/null
+++ b/src/sysfs-utils.c
@@ -0,0 +1,203 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <grp.h>
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+
+#include "sysfs-utils.h"
+
+double
+sysfs_get_double (const char *dir, const char *attribute)
+{
+ double result;
+ char *contents;
+ char *filename;
+
+ result = 0.0;
+ filename = g_build_filename (dir, attribute, NULL);
+ if (g_file_get_contents (filename, &contents, NULL, NULL)) {
+ result = atof (contents);
+ g_free (contents);
+ }
+ g_free (filename);
+
+
+ return result;
+}
+
+gboolean
+sysfs_file_contains (const char *dir, const char *attribute, const char *string)
+{
+ gboolean result;
+ char *filename;
+ char *s;
+
+ result = FALSE;
+
+ filename = g_build_filename (dir, attribute, NULL);
+ if (g_file_get_contents (filename, &s, NULL, NULL)) {
+ result = (strstr(s, string) != NULL);
+ g_free (s);
+ }
+ g_free (filename);
+
+ return result;
+}
+
+char *
+sysfs_get_string (const char *dir, const char *attribute)
+{
+ char *result;
+ char *filename;
+
+ result = NULL;
+ filename = g_build_filename (dir, attribute, NULL);
+ if (!g_file_get_contents (filename, &result, NULL, NULL)) {
+ result = g_strdup ("");
+ }
+ g_free (filename);
+
+ return result;
+}
+
+int
+sysfs_get_int (const char *dir, const char *attribute)
+{
+ int result;
+ char *contents;
+ char *filename;
+
+ result = 0;
+ filename = g_build_filename (dir, attribute, NULL);
+ if (g_file_get_contents (filename, &contents, NULL, NULL)) {
+ result = atoi (contents);
+ g_free (contents);
+ }
+ g_free (filename);
+
+
+ return result;
+}
+
+guint64
+sysfs_get_uint64 (const char *dir, const char *attribute)
+{
+ guint64 result;
+ char *contents;
+ char *filename;
+
+ result = 0;
+ filename = g_build_filename (dir, attribute, NULL);
+ if (g_file_get_contents (filename, &contents, NULL, NULL)) {
+ result = atoll (contents);
+ g_free (contents);
+ }
+ g_free (filename);
+
+
+ return result;
+}
+
+gboolean
+sysfs_file_exists (const char *dir, const char *attribute)
+{
+ gboolean result;
+ char *filename;
+
+ result = FALSE;
+ filename = g_build_filename (dir, attribute, NULL);
+ if (g_file_test (filename, G_FILE_TEST_EXISTS)) {
+ result = TRUE;
+ }
+ g_free (filename);
+
+ return result;
+}
+
+char *
+_dupv8 (const char *s)
+{
+ const char *end_valid;
+
+ if (!g_utf8_validate (s,
+ -1,
+ &end_valid)) {
+ g_warning ("The string '%s' is not valid UTF-8. Invalid characters begins at '%s'", s, end_valid);
+ return g_strndup (s, end_valid - s);
+ } else {
+ return g_strdup (s);
+ }
+}
+
+char *
+sysfs_resolve_link (const char *dir, const char *attribute)
+{
+ char *full_path;
+ char link_path[PATH_MAX];
+ char resolved_path[PATH_MAX];
+ ssize_t num;
+ gboolean found_it;
+
+ found_it = FALSE;
+
+ full_path = g_build_filename (dir, attribute, NULL);
+
+ //g_warning ("attribute='%s'", attribute);
+ //g_warning ("full_path='%s'", full_path);
+ num = readlink (full_path, link_path, sizeof (link_path) - 1);
+ if (num != -1) {
+ char *absolute_path;
+
+ link_path[num] = '\0';
+
+ //g_warning ("link_path='%s'", link_path);
+ absolute_path = g_build_filename (dir, link_path, NULL);
+ //g_warning ("absolute_path='%s'", absolute_path);
+ if (realpath (absolute_path, resolved_path) != NULL) {
+ //g_warning ("resolved_path='%s'", resolved_path);
+ found_it = TRUE;
+ }
+ g_free (absolute_path);
+ }
+ g_free (full_path);
+
+ if (found_it)
+ return g_strdup (resolved_path);
+ else
+ return NULL;
+}
diff --git a/src/sysfs-utils.h b/src/sysfs-utils.h
new file mode 100644
index 0000000..fc79137
--- /dev/null
+++ b/src/sysfs-utils.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; 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 __SYSFS_UTILS_H__
+#define __SYSFS_UTILS_H__
+
+#include <glib.h>
+
+double sysfs_get_double (const char *dir, const char *attribute);
+gboolean sysfs_file_contains (const char *dir, const char *attribute, const char *string);
+char *sysfs_get_string (const char *dir, const char *attribute);
+int sysfs_get_int (const char *dir, const char *attribute);
+guint64 sysfs_get_uint64 (const char *dir, const char *attribute);
+gboolean sysfs_file_exists (const char *dir, const char *attribute);
+char *sysfs_resolve_link (const char *dir, const char *attribute);
+
+char *_dupv8 (const char *s);
+
+#endif /* __SYSFS_UTILS_H__ */
diff --git a/tools/Makefile.am b/tools/Makefile.am
new file mode 100644
index 0000000..237c46b
--- /dev/null
+++ b/tools/Makefile.am
@@ -0,0 +1,49 @@
+## Process this file with automake to produce Makefile.in
+
+INCLUDES = \
+ -I$(top_builddir)/src -I$(top_srcdir)/src \
+ -DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\" \
+ -DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \
+ -DPACKAGE_DATA_DIR=\""$(datadir)"\" \
+ -DPACKAGE_BIN_DIR=\""$(bindir)"\" \
+ -DPACKAGE_LOCALSTATE_DIR=\""$(localstatedir)"\" \
+ -DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \
+ -DPACKAGE_LIB_DIR=\""$(libdir)"\" \
+ -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT \
+ $(DBUS_GLIB_CFLAGS) \
+ $(POLKIT_DBUS_CFLAGS) \
+ $(GLIB_CFLAGS)
+
+BUILT_SOURCES = \
+ devkit-power-daemon-glue.h \
+ devkit-power-marshal.h devkit-power-marshal.c
+
+devkit-power-marshal.h: $(top_srcdir)/src/devkit-power-marshal.list
+ glib-genmarshal $< --prefix=devkit_power_marshal --header > $@
+
+devkit-power-marshal.c: $(top_srcdir)/src/devkit-power-marshal.list
+ echo "#include \"devkit-power-marshal.h\"" > $@ && glib-genmarshal $< --prefix=devkit_power_marshal --body >> $@
+
+devkit-power-daemon-glue.h: $(top_srcdir)/src/org.freedesktop.DeviceKit.Power.xml Makefile.am
+ dbus-binding-tool --prefix=devkit_power_daemon --mode=glib-client --output=devkit-power-daemon-glue.h $(top_srcdir)/src/org.freedesktop.DeviceKit.Power.xml
+
+bin_PROGRAMS = devkit-power
+
+devkit_power_SOURCES = \
+ devkit-power.c \
+ $(BUILT_SOURCES)
+
+
+devkit_power_CPPFLAGS = \
+ -DG_LOG_DOMAIN=\"devkit-power\" \
+ $(DISABLE_DEPRECATED) \
+ $(AM_CPPFLAGS)
+
+devkit_power_LDADD = \
+ $(DBUS_GLIB_LIBS) \
+ $(POLKIT_DBUS_LIBS)
+
+CLEANFILES = $(BUILT_SOURCES)
+
+clean-local :
+ rm -f *~ $(service_DATA) $(dbusconf_DATA)
diff --git a/tools/devkit-power.c b/tools/devkit-power.c
new file mode 100644
index 0000000..de79957
--- /dev/null
+++ b/tools/devkit-power.c
@@ -0,0 +1,376 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <glib-object.h>
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include <polkit-dbus/polkit-dbus.h>
+
+#include "devkit-power-daemon-glue.h"
+#include "devkit-power-marshal.h"
+
+static DBusGConnection *bus = NULL;
+static DBusGProxy *power_proxy = NULL;
+static GMainLoop *loop;
+
+static gboolean opt_enumerate = FALSE;
+static gboolean opt_monitor = FALSE;
+static gboolean opt_monitor_detail = FALSE;
+static char *opt_show_info = FALSE;
+
+static gboolean do_monitor (void);
+static void do_show_info (const char *object_path);
+
+static gboolean
+polkit_dbus_gerror_parse (GError *error,
+ PolKitAction **action,
+ PolKitResult *result)
+{
+ gboolean ret;
+ const char *name;
+
+ ret = FALSE;
+ if (error->domain != DBUS_GERROR || error->code != DBUS_GERROR_REMOTE_EXCEPTION)
+ goto out;
+
+ name = dbus_g_error_get_name (error);
+
+ ret = polkit_dbus_error_parse_from_strings (name,
+ error->message,
+ action,
+ result);
+out:
+ return ret;
+}
+
+static void
+device_added_signal_handler (DBusGProxy *proxy, const char *object_path, gpointer user_data)
+{
+ g_print ("added: %s\n", object_path);
+ if (opt_monitor_detail) {
+ do_show_info (object_path);
+ g_print ("\n");
+ }
+}
+
+static void
+device_changed_signal_handler (DBusGProxy *proxy, const char *object_path, gpointer user_data)
+{
+ g_print ("changed: %s\n", object_path);
+ if (opt_monitor_detail) {
+ /* TODO: would be nice to just show the diff */
+ do_show_info (object_path);
+ g_print ("\n");
+ }
+}
+
+static void
+device_removed_signal_handler (DBusGProxy *proxy, const char *object_path, gpointer user_data)
+{
+ g_print ("removed: %s\n", object_path);
+}
+
+/* --- SUCKY CODE BEGIN --- */
+
+/* This totally sucks; dbus-bindings-tool and dbus-glib should be able
+ * to do this for us.
+ */
+
+typedef struct
+{
+ char *native_path;
+ char *vendor;
+ char *model;
+ char *serial;
+ guint64 update_time;
+ char *type;
+ gboolean line_power_online;
+ double battery_energy;
+ double battery_energy_empty;
+ double battery_energy_empty_design;
+ double battery_energy_full;
+ double battery_energy_full_design;
+ double battery_energy_rate;
+ gint64 battery_time_to_full;
+ gint64 battery_time_to_empty;
+ double battery_percentage;
+ char *battery_technology;
+} DeviceProperties;
+
+static void
+collect_props (const char *key, const GValue *value, DeviceProperties *props)
+{
+ gboolean handled = TRUE;
+
+ if (strcmp (key, "native-path") == 0)
+ props->native_path = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "vendor") == 0)
+ props->vendor = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "model") == 0)
+ props->model = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "serial") == 0)
+ props->serial = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "update-time") == 0)
+ props->update_time = g_value_get_uint64 (value);
+ else if (strcmp (key, "type") == 0)
+ props->type = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "line-power-online") == 0)
+ props->line_power_online = g_value_get_boolean (value);
+ else if (strcmp (key, "battery-energy") == 0)
+ props->battery_energy = g_value_get_double (value);
+ else if (strcmp (key, "battery-energy-empty") == 0)
+ props->battery_energy_empty = g_value_get_double (value);
+ else if (strcmp (key, "battery-energy-empty-design") == 0)
+ props->battery_energy_empty_design = g_value_get_double (value);
+ else if (strcmp (key, "battery-energy-full") == 0)
+ props->battery_energy_full = g_value_get_double (value);
+ else if (strcmp (key, "battery-energy-full-design") == 0)
+ props->battery_energy_full_design = g_value_get_double (value);
+ else if (strcmp (key, "battery-energy-rate") == 0)
+ props->battery_energy_rate = g_value_get_double (value);
+ else if (strcmp (key, "battery-time-to-full") == 0)
+ props->battery_time_to_full = g_value_get_int64 (value);
+ else if (strcmp (key, "battery-time-to-empty") == 0)
+ props->battery_time_to_empty = g_value_get_int64 (value);
+ else if (strcmp (key, "battery-percentage") == 0)
+ props->battery_percentage = g_value_get_double (value);
+ else if (strcmp (key, "battery-technology") == 0)
+ props->battery_technology = g_strdup (g_value_get_string (value));
+ else
+ handled = FALSE;
+
+ if (!handled)
+ g_warning ("unhandled property '%s'", key);
+}
+
+static DeviceProperties *
+device_properties_get (DBusGConnection *bus,
+ const char *object_path)
+{
+ DeviceProperties *props;
+ GError *error;
+ GHashTable *hash_table;
+ DBusGProxy *prop_proxy;
+ const char *ifname = "org.freedesktop.DeviceKit.Power.Device";
+
+ props = g_new0 (DeviceProperties, 1);
+
+ prop_proxy = dbus_g_proxy_new_for_name (bus,
+ "org.freedesktop.DeviceKit.Power",
+ object_path,
+ "org.freedesktop.DBus.Properties");
+ error = NULL;
+ if (!dbus_g_proxy_call (prop_proxy,
+ "GetAll",
+ &error,
+ G_TYPE_STRING,
+ ifname,
+ G_TYPE_INVALID,
+ dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
+ &hash_table,
+ G_TYPE_INVALID)) {
+ g_warning ("Couldn't call GetAll() to get properties for %s: %s", object_path, error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ g_hash_table_foreach (hash_table, (GHFunc) collect_props, props);
+
+ g_hash_table_unref (hash_table);
+
+out:
+ g_object_unref (prop_proxy);
+ return props;
+}
+
+static void
+device_properties_free (DeviceProperties *props)
+{
+ g_free (props->native_path);
+ g_free (props->vendor);
+ g_free (props->model);
+ g_free (props->serial);
+ g_free (props->type);
+ g_free (props->battery_technology);
+ g_free (props);
+}
+
+/* --- SUCKY CODE END --- */
+
+static gboolean
+do_monitor (void)
+{
+ GError *error;
+
+ g_print ("Monitoring activity from the power daemon. Press Ctrl+C to cancel.\n");
+
+ error = NULL;
+
+ dbus_g_proxy_connect_signal (power_proxy, "DeviceAdded",
+ G_CALLBACK (device_added_signal_handler), NULL, NULL);
+ dbus_g_proxy_connect_signal (power_proxy, "DeviceRemoved",
+ G_CALLBACK (device_removed_signal_handler), NULL, NULL);
+ dbus_g_proxy_connect_signal (power_proxy, "DeviceChanged",
+ G_CALLBACK (device_changed_signal_handler), NULL, NULL);
+ g_main_loop_run (loop);
+
+ return FALSE;
+}
+
+static void
+do_show_info (const char *object_path)
+{
+ DeviceProperties *props;
+ struct tm *time_tm;
+ time_t t;
+ char time_buf[256];
+
+ props = device_properties_get (bus, object_path);
+
+ t = (time_t) props->update_time;
+ time_tm = localtime (&t);
+ strftime (time_buf, sizeof time_buf, "%c", time_tm);
+
+ g_print ("Showing information for %s\n", object_path);
+ g_print (" native-path: %s\n", props->native_path);
+ g_print (" vendor: %s\n", props->vendor);
+ g_print (" model: %s\n", props->model);
+ g_print (" serial: %s\n", props->serial);
+ g_print (" updated: %s (%d seconds ago)\n", time_buf, (int) (time (NULL) - props->update_time));
+ if (strcmp (props->type, "battery") == 0) {
+ g_print (" battery\n");
+ g_print (" energy: %g Wh\n", props->battery_energy);
+ g_print (" energy-empty: %g Wh\n", props->battery_energy_empty);
+ g_print (" energy-empty-design: %g Wh\n", props->battery_energy_empty_design);
+ g_print (" energy-full: %g Wh\n", props->battery_energy_full);
+ g_print (" energy-full-design: %g Wh\n", props->battery_energy_full_design);
+ g_print (" energy-rate: %g W\n", props->battery_energy_rate);
+ g_print (" time to full: ");
+ if (props->battery_time_to_full >= 0)
+ g_print ("%d seconds\n", (int) props->battery_time_to_full);
+ else
+ g_print ("unknown\n");
+ g_print (" time to empty: ");
+ if (props->battery_time_to_empty >= 0)
+ g_print ("%d seconds\n", (int) props->battery_time_to_empty);
+ else
+ g_print ("unknown\n");
+ g_print (" percentage: %g%%\n", props->battery_percentage);
+ g_print (" technology: %s\n", props->battery_technology);
+ } else if (strcmp (props->type, "line-power") == 0) {
+ g_print (" line-power\n");
+ g_print (" online: %s\n", props->line_power_online ? "yes" : "no");
+ } else {
+ g_print (" unknown power source type '%s'\n", props->type);
+ }
+ device_properties_free (props);
+}
+
+int
+main (int argc, char **argv)
+{
+ int ret;
+ GOptionContext *context;
+ GError *error = NULL;
+ unsigned int n;
+ static GOptionEntry entries [] = {
+ { "enumerate", 0, 0, G_OPTION_ARG_NONE, &opt_enumerate, "Enumerate objects paths for devices", NULL },
+ { "monitor", 0, 0, G_OPTION_ARG_NONE, &opt_monitor, "Monitor activity from the disk daemon", NULL },
+ { "monitor-detail", 0, 0, G_OPTION_ARG_NONE, &opt_monitor_detail, "Monitor with detail", NULL },
+ { "show-info", 0, 0, G_OPTION_ARG_STRING, &opt_show_info, "Show information about object path", NULL },
+ { NULL }
+ };
+
+ ret = 1;
+
+ g_type_init ();
+
+ context = g_option_context_new ("DeviceKit-power tool");
+ g_option_context_add_main_entries (context, entries, NULL);
+ g_option_context_parse (context, &argc, &argv, NULL);
+ g_option_context_free (context);
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (bus == NULL) {
+ g_warning ("Couldn't connect to system bus: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ power_proxy = dbus_g_proxy_new_for_name (bus,
+ "org.freedesktop.DeviceKit.Power",
+ "/",
+ "org.freedesktop.DeviceKit.Power");
+ dbus_g_proxy_add_signal (power_proxy, "DeviceAdded", G_TYPE_STRING, G_TYPE_INVALID);
+ dbus_g_proxy_add_signal (power_proxy, "DeviceRemoved", G_TYPE_STRING, G_TYPE_INVALID);
+ dbus_g_proxy_add_signal (power_proxy, "DeviceChanged", G_TYPE_STRING, G_TYPE_INVALID);
+
+ if (opt_enumerate) {
+ GPtrArray *devices;
+ if (!org_freedesktop_DeviceKit_Power_enumerate_devices (power_proxy, &devices, &error)) {
+ g_warning ("Couldn't enumerate devices: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+ for (n = 0; n < devices->len; n++) {
+ char *object_path = devices->pdata[n];
+ g_print ("%s\n", object_path);
+ }
+ g_ptr_array_foreach (devices, (GFunc) g_free, NULL);
+ g_ptr_array_free (devices, TRUE);
+ } else if (opt_monitor || opt_monitor_detail) {
+ if (!do_monitor ())
+ goto out;
+ } else if (opt_show_info != NULL) {
+ do_show_info (opt_show_info);
+ }
+
+ ret = 0;
+
+out:
+ if (power_proxy != NULL)
+ g_object_unref (power_proxy);
+ if (bus != NULL)
+ dbus_g_connection_unref (bus);
+
+ return ret;
+}