summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2011-04-07 17:35:42 +0200
committerMarcel Holtmann <marcel@holtmann.org>2011-10-20 23:12:22 -0700
commit691a38d5a9ff5529c7b30aba878a60598e68b9c9 (patch)
treee42009b3ccd2a6a0fa766eaa0e9f1b1412b47fa6
downloadneard-691a38d5a9ff5529c7b30aba878a60598e68b9c9.tar.gz
neard-691a38d5a9ff5529c7b30aba878a60598e68b9c9.tar.bz2
neard-691a38d5a9ff5529c7b30aba878a60598e68b9c9.zip
Initial revision
-rw-r--r--AUTHORS2
-rw-r--r--COPYING340
-rw-r--r--ChangeLog0
-rw-r--r--HACKING87
-rw-r--r--INSTALL236
-rw-r--r--Makefile.am58
-rw-r--r--NEWS0
-rw-r--r--README21
-rw-r--r--TODO10
-rw-r--r--acinclude.m427
-rwxr-xr-xbootstrap7
-rwxr-xr-xbootstrap-configure10
-rw-r--r--configure.ac76
-rw-r--r--doc/adapter-api.txt64
-rw-r--r--doc/manager-api.txt40
-rw-r--r--doc/target-api.txt38
-rw-r--r--gdbus/gdbus.h177
-rw-r--r--gdbus/mainloop.c383
-rw-r--r--gdbus/object.c868
-rw-r--r--gdbus/polkit.c202
-rw-r--r--gdbus/watch.c748
-rw-r--r--include/dbus.h132
-rw-r--r--src/adapter.c62
-rw-r--r--src/dbus.c294
-rw-r--r--src/error.c185
-rwxr-xr-xsrc/genbuiltin17
-rw-r--r--src/log.c138
-rw-r--r--src/log.h47
-rw-r--r--src/main.c160
-rw-r--r--src/manager.c101
-rw-r--r--src/near.h60
-rw-r--r--src/types.h31
32 files changed, 4621 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..3e4813c
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,2 @@
+Samuel Ortiz <sameo@linux.intel.com>
+Marcel Holtmann <marcel@holtmann.org>
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..6d45519
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+ 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.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ChangeLog
diff --git a/HACKING b/HACKING
new file mode 100644
index 0000000..478653c
--- /dev/null
+++ b/HACKING
@@ -0,0 +1,87 @@
+Hacking on Near Field Communication manager
+*******************************************
+
+
+Build tools requirements
+========================
+
+When building and testing directly from the repository it is important to
+have at least automake version 1.10 or later installed. All modern
+distributions should default to the latest version, but it seems that
+Debian's default is still an earlier version:
+
+ Check version
+ # dpkg -l '*automake*'
+
+ Install new version
+ # apt-get install automake1.10
+ # update-alternatives --config automake
+
+
+Working with the source code repository
+=======================================
+
+The repository contains two extra scripts that accomplish the bootstrap
+process. One is called "bootstrap" which is the basic scripts that uses the
+autotools scripts to create the needed files for building and installing.
+It makes sure to call the right programs depending on the usage of shared or
+static libraries or translations etc.
+
+The second program is called "bootstrap-configure". This program will make
+sure to properly clean the repository, call the "bootstrap" script and then
+call configure with proper settings for development. It will use the best
+options and pass them over to configure. These options normally include
+the enabling the maintainer mode and the debugging features.
+
+So while in a normal source project the call "./configure ..." is used to
+configure the project with its settings like prefix and extra options. In
+case of bare repositories call "./bootstrap-configure" and it will bootstrap
+the repository and calls configure with all the correct options to make
+development easier.
+
+In case of preparing for a release with "make distcheck", don't use
+bootstrap-configure since it could export development specific settings.
+
+So the normal steps to checkout, build and install such a repository is
+like this:
+
+ Checkout repository
+ # git clone git://git.kernel.org/pub/scm/network/.../neard.git
+ # cd neard
+
+ Configure and build
+ # ./bootstrap-configure
+ # make
+
+ Check installation
+ # make install DESTDIR=$PWD/x
+ # find x
+ # rm -rf x
+
+ Check distribution
+ # make distcheck
+
+ Final installation
+ # sudo make install
+
+ Remove autogenerated files
+ # make maintainer-clean
+
+
+Running from within the source code repository
+==============================================
+
+When using "./configure --enable-maintainer-mode" the automake scripts will
+use the plugins directly from within the repository. This removes the need
+to use "make install" when testing "neard". The "bootstrap-configure"
+automatically includes this option.
+
+ Run daemon in foreground with debugging
+ # ./src/neard -n -d 'src/*'
+
+For production installations or distribution packaging it is important that
+the "--enable-maintainer-mode" option is NOT used.
+
+The debugging option -d takes an argument. This argument can be a comma
+separated list of file names like 'src/main.c,src/manager.c' to enable debugs
+in these files. Simple glob style pattern matching is supported in this list.
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..56b077d
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,236 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free
+Software Foundation, Inc.
+
+This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. (Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.)
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You only need
+`configure.ac' if you want to change it or regenerate `configure' using
+a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes awhile. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about. Run `./configure --help' for
+details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here
+is an example:
+
+ ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not support the `VPATH'
+variable, you have to compile the package for one architecture at a
+time in the source code directory. After you have installed the
+package for one architecture, use `make distclean' before reconfiguring
+for another architecture.
+
+Installation Names
+==================
+
+By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc. You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PREFIX'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PREFIX', the package will
+use PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the `--target=TYPE' option to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+If you want to set default values for `configure' scripts to share, you
+can create a site shell script called `config.site' that gives default
+values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script). Here is a another example:
+
+ /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent
+configuration-related scripts to be executed by `/bin/bash'.
+
+`configure' Invocation
+======================
+
+`configure' recognizes the following options to control how it operates.
+
+`--help'
+`-h'
+ Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..a2e0b92
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,58 @@
+
+AM_MAKEFLAGS = --no-print-directory
+
+includedir = @includedir@/near
+
+noinst_HEADERS = include/dbus.h
+
+local_headers = $(foreach file,$(include_HEADERS) $(nodist_include_HEADERS) \
+ $(noinst_HEADERS), include/near/$(notdir $(file)))
+
+gdbus_sources = gdbus/gdbus.h gdbus/mainloop.c gdbus/watch.c \
+ gdbus/object.c gdbus/polkit.c
+
+builtin_modules =
+builtin_sources =
+builtin_cflags =
+builtin_libadd =
+
+libexec_PROGRAMS = src/neard
+
+src_neard_SOURCES = $(gdbus_sources) $(gweb_sources) $(builtin_sources) \
+ src/main.c src/error.c src/near.h src/types.h \
+ src/log.h src/log.c src/dbus.c src/manager.c \
+ src/adapter.c
+
+src_neard_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ -lresolv -ldl
+
+src_neard_LDFLAGS = -Wl,--export-dynamic
+
+nodist_src_neard_SOURCES = src/builtin.h
+
+src/builtin.h: src/genbuiltin $(builtin_sources)
+ $(AM_V_GEN)$(srcdir)/src/genbuiltin $(builtin_modules) > $@
+
+AM_CFLAGS = @GLIB_CFLAGS@ @DBUS_CFLAGS@ $(builtin_cflags) \
+ -DMMS_PLUGIN_BUILTIN \
+ -DPLUGINDIR=\""$(plugindir)"\"
+
+INCLUDES = -I$(builddir)/include -I$(builddir)/src -I$(srcdir)/gdbus
+
+CLEANFILES = src/builtin.h $(local_headers)
+
+doc_files = doc/manager-api.txt doc/target-api.txt doc/adapter-api.txt
+
+EXTRA_DIST = src/genbuiltin $(test_scripts) $(doc_files)
+
+MAINTAINERCLEANFILES = Makefile.in \
+ aclocal.m4 configure config.h.in config.sub config.guess \
+ ltmain.sh depcomp compile missing install-sh mkinstalldirs
+
+$(src_neard_OBJECTS) $(plugin_objects): $(local_headers)
+
+include/near/%.h: include/%.h
+ $(AM_V_at)$(MKDIR_P) include/near
+ $(AM_V_GEN)$(LN_S) $(abs_top_srcdir)/$< $@
+
+clean-local:
+ @$(RM) -rf include/near
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/NEWS
diff --git a/README b/README
new file mode 100644
index 0000000..7126385
--- /dev/null
+++ b/README
@@ -0,0 +1,21 @@
+Near Field Communication manager
+********************************
+
+Copyright (C) 2011 Intel Corporation. All rights reserved.
+
+
+Compilation and installation
+============================
+
+In order to compile proxy daemon you need following software packages:
+ - GCC compiler
+ - D-Bus library
+ - GLib library
+
+To configure run:
+ ./configure --prefix=/usr
+
+Configure automatically searches for all required components and packages.
+
+To compile and install run:
+ make && make install
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..05dbe98
--- /dev/null
+++ b/TODO
@@ -0,0 +1,10 @@
+Background
+==========
+
+- Priority scale: High, Medium and Low
+
+- Complexity scale: C1, C2, C4 and C8.
+ The complexity scale is exponential, with complexity 1 being the
+ lowest complexity. Complexity is a function of both task 'complexity'
+ and task 'scope'.
+
diff --git a/acinclude.m4 b/acinclude.m4
new file mode 100644
index 0000000..329c6a9
--- /dev/null
+++ b/acinclude.m4
@@ -0,0 +1,27 @@
+AC_DEFUN([AC_PROG_CC_PIE], [
+ AC_CACHE_CHECK([whether ${CC-cc} accepts -fPIE], ac_cv_prog_cc_pie, [
+ echo 'void f(){}' > conftest.c
+ if test -z "`${CC-cc} -fPIE -pie -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_pie=yes
+ else
+ ac_cv_prog_cc_pie=no
+ fi
+ rm -rf conftest*
+ ])
+])
+
+AC_DEFUN([COMPILER_FLAGS], [
+ if (test "${CFLAGS}" = ""); then
+ CFLAGS="-Wall -O2 -D_FORTIFY_SOURCE=2"
+ fi
+ if (test "$USE_MAINTAINER_MODE" = "yes"); then
+ CFLAGS+=" -Werror -Wextra"
+ CFLAGS+=" -Wno-unused-parameter"
+ CFLAGS+=" -Wno-missing-field-initializers"
+ CFLAGS+=" -Wdeclaration-after-statement"
+ CFLAGS+=" -Wmissing-declarations"
+ CFLAGS+=" -Wredundant-decls"
+ CFLAGS+=" -Wcast-align"
+ CFLAGS+=" -DG_DISABLE_DEPRECATED"
+ fi
+])
diff --git a/bootstrap b/bootstrap
new file mode 100755
index 0000000..91756f9
--- /dev/null
+++ b/bootstrap
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+aclocal && \
+ autoheader && \
+ libtoolize --automake --copy --force && \
+ automake --add-missing --copy && \
+ autoconf
diff --git a/bootstrap-configure b/bootstrap-configure
new file mode 100755
index 0000000..7d35d71
--- /dev/null
+++ b/bootstrap-configure
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+if [ -f config.status ]; then
+ make maintainer-clean
+fi
+
+./bootstrap && \
+ ./configure --enable-maintainer-mode \
+ --enable-debug \
+ --prefix=/usr $*
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..d908a5e
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,76 @@
+AC_PREREQ(2.60)
+AC_INIT(neard, 0.0)
+
+AM_INIT_AUTOMAKE([foreign subdir-objects color-tests])
+AM_CONFIG_HEADER(config.h)
+
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+AM_MAINTAINER_MODE
+
+AC_PREFIX_DEFAULT(/usr/local)
+
+if (test "${libdir}" = '${exec_prefix}/lib'); then
+ libdir="${prefix}/lib"
+fi
+
+plugindir="${libdir}/near/plugins"
+
+PKG_PROG_PKG_CONFIG
+
+COMPILER_FLAGS
+
+AC_LANG_C
+
+AC_PROG_CC
+AC_PROG_CC_PIE
+AC_PROG_INSTALL
+
+m4_define([_LT_AC_TAGCONFIG], [])
+m4_ifdef([AC_LIBTOOL_TAGS], [AC_LIBTOOL_TAGS([])])
+
+AC_DISABLE_STATIC
+AC_PROG_LIBTOOL
+
+AC_ARG_ENABLE(optimization, AC_HELP_STRING([--disable-optimization],
+ [disable code optimization through compiler]), [
+ if (test "${enableval}" = "no"); then
+ CFLAGS="$CFLAGS -O0"
+ fi
+])
+
+AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug],
+ [enable compiling with debugging information]), [
+ if (test "${enableval}" = "yes" &&
+ test "${ac_cv_prog_cc_g}" = "yes"); then
+ CFLAGS="$CFLAGS -g"
+ fi
+])
+
+AC_ARG_ENABLE(pie, AC_HELP_STRING([--enable-pie],
+ [enable position independent executables flag]), [
+ if (test "${enableval}" = "yes" &&
+ test "${ac_cv_prog_cc_pie}" = "yes"); then
+ CFLAGS="$CFLAGS -fPIE"
+ LDFLAGS="$LDFLAGS -pie"
+ fi
+])
+
+AC_CHECK_LIB(dl, dlopen, dummy=yes,
+ AC_MSG_ERROR(dynamic linking loader is required))
+
+PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16, dummy=yes,
+ AC_MSG_ERROR(GLib >= 2.16 is required))
+AC_SUBST(GLIB_CFLAGS)
+AC_SUBST(GLIB_LIBS)
+
+PKG_CHECK_MODULES(DBUS, dbus-1 >= 1.0, dummy=yes,
+ AC_MSG_ERROR(D-Bus >= 1.0 is required))
+AC_CHECK_LIB(dbus-1, dbus_watch_get_unix_fd, dummy=yes,
+ AC_DEFINE(NEED_DBUS_WATCH_GET_UNIX_FD, 1,
+ [Define to 1 if you need the dbus_watch_get_unix_fd() function.]
+))
+AC_SUBST(DBUS_CFLAGS)
+AC_SUBST(DBUS_LIBS)
+
+AC_OUTPUT(Makefile)
diff --git a/doc/adapter-api.txt b/doc/adapter-api.txt
new file mode 100644
index 0000000..39cdca9
--- /dev/null
+++ b/doc/adapter-api.txt
@@ -0,0 +1,64 @@
+Adapter hierarchy
+=================
+
+Service org.neard
+Interface org.neard.Adapter
+Object path [variable prefix]/{nfc0,nfc1,...}
+
+Methods: dict GetProperties()
+
+ Returns all properties for the device. See the
+ properties section for available properties.
+
+ Possible Errors: org.neard.Error.DoesNotExist
+
+ void SetProperty(string name, variant value)
+
+ Changes the value of the specified property. Only
+ properties that are listed a read-write are changeable.
+ On success this will emit a PropertyChanged signal.
+
+ Possible Errors: org.neard.Error.DoesNotExist
+ org.neard.Error.InvalidArguments
+
+
+Signals PropertyChanged(string name, variant value)
+
+ This signal indicates a changed value of the given
+ property.
+
+ TargetFound(string address, dict values)
+
+ This signal is sent whenever an NFC target is found,
+ as a result of a probe response reception.
+
+ The dictionary contains basically the same values
+ that are returned by the GetProperties method
+ from the org.neard.Target interface.
+
+ TargetLost(string address)
+
+ This signal is sent whenever the NFC target is no longer
+ in sight, or when it's been de-activated.
+
+
+Properties: string Mode [readwrite]
+
+ The adapter mode.
+
+ Valid types are "initiator" and "target".
+ The default value for the adapter mode is "target".
+
+ string CommunicationMode [readwrite]
+
+ The adapter communication mode.
+
+ Valid types are "passive" and "active". In passive mode, the
+ initiator never turns its RF field off.
+ The default value for the adapter communication mode
+ is "passive".
+
+ string Powered [readwrite]
+
+ Switch an adapter on or off.
+
diff --git a/doc/manager-api.txt b/doc/manager-api.txt
new file mode 100644
index 0000000..7d13f01
--- /dev/null
+++ b/doc/manager-api.txt
@@ -0,0 +1,40 @@
+Manager hierarchy
+=================
+
+Service org.neard
+Interface org.neard.Manager
+Object path /
+
+Methods dict GetProperties()
+
+ Returns all properties for the device. See the
+ properties section for available properties.
+
+ Possible Errors: org.neard.Error.DoesNotExist
+
+ void SetProperty(string name, variant value)
+
+ Changes the value of the specified property. Only
+ properties that are listed a read-write are changeable.
+ On success this will emit a PropertyChanged signal.
+
+ Possible Errors: org.neard.Error.DoesNotExist
+ org.neard.Error.InvalidArguments
+
+
+Signals PropertyChanged(string name, variant value)
+
+ This signal indicates a changed value of the given
+ property.
+
+ AdapterAdded(object adapter)
+
+ Parameter is the object path of added adapter.
+
+ AdapterRemoved(object adapter)
+
+ Parameter is the object path of removed adapter.
+
+Properties array{object} Adapters [readonly]
+
+ List of adapter object paths.
diff --git a/doc/target-api.txt b/doc/target-api.txt
new file mode 100644
index 0000000..3172b78
--- /dev/null
+++ b/doc/target-api.txt
@@ -0,0 +1,38 @@
+Target hierarchy
+================
+
+Service org.neard
+Interface org.neard.Target
+Object path [variable prefix]/{nfc0,nfc1,...}/target_UID
+
+Method dict GetProperties()
+
+ Returns all properties for the device. See the
+ properties section for available properties.
+
+ Possible Errors: org.neard.Error.DoesNotExist
+
+ void SetProperty(string name, variant value)
+
+ Changes the value of the specified property. Only
+ properties that are listed a read-write are changeable.
+ On success this will emit a PropertyChanged signal.
+
+ Possible Errors: org.neard.Error.DoesNotExist
+ org.neard.Error.InvalidArguments
+
+Signals PropertyChanged(string name, variant value)
+
+ This signal indicates a changed value of the given
+ property.
+
+Properties string Type [readonly]
+
+ The NFC target type.
+
+ Valid types are "tag" and "device".
+
+ array{dict} Records [readwrite]
+
+ List of NDEF records.
+ This is only valid for tag type targets.
diff --git a/gdbus/gdbus.h b/gdbus/gdbus.h
new file mode 100644
index 0000000..a0583e6
--- /dev/null
+++ b/gdbus/gdbus.h
@@ -0,0 +1,177 @@
+/*
+ *
+ * D-Bus helper library
+ *
+ * Copyright (C) 2004-2011 Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ * 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 __GDBUS_H
+#define __GDBUS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <dbus/dbus.h>
+#include <glib.h>
+
+typedef void (* GDBusWatchFunction) (DBusConnection *connection,
+ void *user_data);
+
+typedef gboolean (* GDBusSignalFunction) (DBusConnection *connection,
+ DBusMessage *message, void *user_data);
+
+DBusConnection *g_dbus_setup_bus(DBusBusType type, const char *name,
+ DBusError *error);
+
+DBusConnection *g_dbus_setup_private(DBusBusType type, const char *name,
+ DBusError *error);
+
+gboolean g_dbus_request_name(DBusConnection *connection, const char *name,
+ DBusError *error);
+
+gboolean g_dbus_set_disconnect_function(DBusConnection *connection,
+ GDBusWatchFunction function,
+ void *user_data, DBusFreeFunction destroy);
+
+typedef void (* GDBusDestroyFunction) (void *user_data);
+
+typedef DBusMessage * (* GDBusMethodFunction) (DBusConnection *connection,
+ DBusMessage *message, void *user_data);
+
+typedef guint32 GDBusPendingReply;
+
+typedef void (* GDBusSecurityFunction) (DBusConnection *connection,
+ const char *action,
+ gboolean interaction,
+ GDBusPendingReply pending);
+
+typedef enum {
+ G_DBUS_METHOD_FLAG_DEPRECATED = (1 << 0),
+ G_DBUS_METHOD_FLAG_NOREPLY = (1 << 1),
+ G_DBUS_METHOD_FLAG_ASYNC = (1 << 2),
+} GDBusMethodFlags;
+
+typedef enum {
+ G_DBUS_SIGNAL_FLAG_DEPRECATED = (1 << 0),
+} GDBusSignalFlags;
+
+typedef enum {
+ G_DBUS_PROPERTY_FLAG_DEPRECATED = (1 << 0),
+} GDBusPropertyFlags;
+
+typedef enum {
+ G_DBUS_SECURITY_FLAG_DEPRECATED = (1 << 0),
+ G_DBUS_SECURITY_FLAG_BUILTIN = (1 << 1),
+ G_DBUS_SECURITY_FLAG_ALLOW_INTERACTION = (1 << 2),
+} GDBusSecurityFlags;
+
+typedef struct {
+ const char *name;
+ const char *signature;
+ const char *reply;
+ GDBusMethodFunction function;
+ GDBusMethodFlags flags;
+ unsigned int privilege;
+} GDBusMethodTable;
+
+typedef struct {
+ const char *name;
+ const char *signature;
+ GDBusSignalFlags flags;
+} GDBusSignalTable;
+
+typedef struct {
+ const char *name;
+ const char *type;
+ GDBusPropertyFlags flags;
+} GDBusPropertyTable;
+
+typedef struct {
+ unsigned int privilege;
+ const char *action;
+ GDBusSecurityFlags flags;
+ GDBusSecurityFunction function;
+} GDBusSecurityTable;
+
+gboolean g_dbus_register_interface(DBusConnection *connection,
+ const char *path, const char *name,
+ const GDBusMethodTable *methods,
+ const GDBusSignalTable *signals,
+ const GDBusPropertyTable *properties,
+ void *user_data,
+ GDBusDestroyFunction destroy);
+gboolean g_dbus_unregister_interface(DBusConnection *connection,
+ const char *path, const char *name);
+
+gboolean g_dbus_register_security(const GDBusSecurityTable *security);
+gboolean g_dbus_unregister_security(const GDBusSecurityTable *security);
+
+void g_dbus_pending_success(DBusConnection *connection,
+ GDBusPendingReply pending);
+void g_dbus_pending_error(DBusConnection *connection,
+ GDBusPendingReply pending,
+ const char *name, const char *format, ...)
+ __attribute__((format(printf, 4, 5)));
+void g_dbus_pending_error_valist(DBusConnection *connection,
+ GDBusPendingReply pending, const char *name,
+ const char *format, va_list args);
+
+DBusMessage *g_dbus_create_error(DBusMessage *message, const char *name,
+ const char *format, ...)
+ __attribute__((format(printf, 3, 4)));
+DBusMessage *g_dbus_create_error_valist(DBusMessage *message, const char *name,
+ const char *format, va_list args);
+DBusMessage *g_dbus_create_reply(DBusMessage *message, int type, ...);
+DBusMessage *g_dbus_create_reply_valist(DBusMessage *message,
+ int type, va_list args);
+
+gboolean g_dbus_send_message(DBusConnection *connection, DBusMessage *message);
+gboolean g_dbus_send_reply(DBusConnection *connection,
+ DBusMessage *message, int type, ...);
+gboolean g_dbus_send_reply_valist(DBusConnection *connection,
+ DBusMessage *message, int type, va_list args);
+
+gboolean g_dbus_emit_signal(DBusConnection *connection,
+ const char *path, const char *interface,
+ const char *name, int type, ...);
+gboolean g_dbus_emit_signal_valist(DBusConnection *connection,
+ const char *path, const char *interface,
+ const char *name, int type, va_list args);
+
+guint g_dbus_add_service_watch(DBusConnection *connection, const char *name,
+ GDBusWatchFunction connect,
+ GDBusWatchFunction disconnect,
+ void *user_data, GDBusDestroyFunction destroy);
+guint g_dbus_add_disconnect_watch(DBusConnection *connection, const char *name,
+ GDBusWatchFunction function,
+ void *user_data, GDBusDestroyFunction destroy);
+guint g_dbus_add_signal_watch(DBusConnection *connection,
+ const char *sender, const char *path,
+ const char *interface, const char *member,
+ GDBusSignalFunction function, void *user_data,
+ GDBusDestroyFunction destroy);
+gboolean g_dbus_remove_watch(DBusConnection *connection, guint tag);
+void g_dbus_remove_all_watches(DBusConnection *connection);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GDBUS_H */
diff --git a/gdbus/mainloop.c b/gdbus/mainloop.c
new file mode 100644
index 0000000..8718da0
--- /dev/null
+++ b/gdbus/mainloop.c
@@ -0,0 +1,383 @@
+/*
+ *
+ * D-Bus helper library
+ *
+ * Copyright (C) 2004-2011 Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ * 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 <glib.h>
+#include <dbus/dbus.h>
+
+#ifdef NEED_DBUS_WATCH_GET_UNIX_FD
+#define dbus_watch_get_unix_fd dbus_watch_get_fd
+#endif
+
+#include "gdbus.h"
+
+#define DISPATCH_TIMEOUT 0
+
+#define info(fmt...)
+#define error(fmt...)
+#define debug(fmt...)
+
+struct timeout_handler {
+ guint id;
+ DBusTimeout *timeout;
+};
+
+struct watch_info {
+ guint id;
+ DBusWatch *watch;
+ DBusConnection *conn;
+};
+
+struct disconnect_data {
+ GDBusWatchFunction function;
+ void *user_data;
+};
+
+static gboolean disconnected_signal(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ struct disconnect_data *dc_data = data;
+
+ error("Got disconnected from the system message bus");
+
+ dc_data->function(conn, dc_data->user_data);
+
+ dbus_connection_unref(conn);
+
+ return TRUE;
+}
+
+static gboolean message_dispatch(void *data)
+{
+ DBusConnection *conn = data;
+
+ dbus_connection_ref(conn);
+
+ /* Dispatch messages */
+ while (dbus_connection_dispatch(conn) == DBUS_DISPATCH_DATA_REMAINS);
+
+ dbus_connection_unref(conn);
+
+ return FALSE;
+}
+
+static inline void queue_dispatch(DBusConnection *conn,
+ DBusDispatchStatus status)
+{
+ if (status == DBUS_DISPATCH_DATA_REMAINS)
+ g_timeout_add(DISPATCH_TIMEOUT, message_dispatch, conn);
+}
+
+static gboolean watch_func(GIOChannel *chan, GIOCondition cond, gpointer data)
+{
+ struct watch_info *info = data;
+ unsigned int flags = 0;
+ DBusDispatchStatus status;
+
+ dbus_connection_ref(info->conn);
+
+ if (cond & G_IO_IN) flags |= DBUS_WATCH_READABLE;
+ if (cond & G_IO_OUT) flags |= DBUS_WATCH_WRITABLE;
+ if (cond & G_IO_HUP) flags |= DBUS_WATCH_HANGUP;
+ if (cond & G_IO_ERR) flags |= DBUS_WATCH_ERROR;
+
+ dbus_watch_handle(info->watch, flags);
+
+ status = dbus_connection_get_dispatch_status(info->conn);
+ queue_dispatch(info->conn, status);
+
+ dbus_connection_unref(info->conn);
+
+ return TRUE;
+}
+
+static void watch_info_free(void *data)
+{
+ struct watch_info *info = data;
+
+ if (info->id > 0) {
+ g_source_remove(info->id);
+ info->id = 0;
+ }
+
+ dbus_connection_unref(info->conn);
+
+ g_free(info);
+}
+
+static dbus_bool_t add_watch(DBusWatch *watch, void *data)
+{
+ DBusConnection *conn = data;
+ GIOCondition cond = G_IO_HUP | G_IO_ERR;
+ GIOChannel *chan;
+ struct watch_info *info;
+ unsigned int flags;
+ int fd;
+
+ if (!dbus_watch_get_enabled(watch))
+ return TRUE;
+
+ info = g_new0(struct watch_info, 1);
+
+ fd = dbus_watch_get_unix_fd(watch);
+ chan = g_io_channel_unix_new(fd);
+
+ info->watch = watch;
+ info->conn = dbus_connection_ref(conn);
+
+ dbus_watch_set_data(watch, info, watch_info_free);
+
+ flags = dbus_watch_get_flags(watch);
+
+ if (flags & DBUS_WATCH_READABLE) cond |= G_IO_IN;
+ if (flags & DBUS_WATCH_WRITABLE) cond |= G_IO_OUT;
+
+ info->id = g_io_add_watch(chan, cond, watch_func, info);
+
+ g_io_channel_unref(chan);
+
+ return TRUE;
+}
+
+static void remove_watch(DBusWatch *watch, void *data)
+{
+ if (dbus_watch_get_enabled(watch))
+ return;
+
+ /* will trigger watch_info_free() */
+ dbus_watch_set_data(watch, NULL, NULL);
+}
+
+static void watch_toggled(DBusWatch *watch, void *data)
+{
+ /* Because we just exit on OOM, enable/disable is
+ * no different from add/remove */
+ if (dbus_watch_get_enabled(watch))
+ add_watch(watch, data);
+ else
+ remove_watch(watch, data);
+}
+
+static gboolean timeout_handler_dispatch(gpointer data)
+{
+ struct timeout_handler *handler = data;
+
+ handler->id = 0;
+
+ /* if not enabled should not be polled by the main loop */
+ if (!dbus_timeout_get_enabled(handler->timeout))
+ return FALSE;
+
+ dbus_timeout_handle(handler->timeout);
+
+ return FALSE;
+}
+
+static void timeout_handler_free(void *data)
+{
+ struct timeout_handler *handler = data;
+
+ if (handler->id > 0) {
+ g_source_remove(handler->id);
+ handler->id = 0;
+ }
+
+ g_free(handler);
+}
+
+static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data)
+{
+ int interval = dbus_timeout_get_interval(timeout);
+ struct timeout_handler *handler;
+
+ if (!dbus_timeout_get_enabled(timeout))
+ return TRUE;
+
+ handler = g_new0(struct timeout_handler, 1);
+
+ handler->timeout = timeout;
+
+ dbus_timeout_set_data(timeout, handler, timeout_handler_free);
+
+ handler->id = g_timeout_add(interval, timeout_handler_dispatch,
+ handler);
+
+ return TRUE;
+}
+
+static void remove_timeout(DBusTimeout *timeout, void *data)
+{
+ /* will trigger timeout_handler_free() */
+ dbus_timeout_set_data(timeout, NULL, NULL);
+}
+
+static void timeout_toggled(DBusTimeout *timeout, void *data)
+{
+ if (dbus_timeout_get_enabled(timeout))
+ add_timeout(timeout, data);
+ else
+ remove_timeout(timeout, data);
+}
+
+static void dispatch_status(DBusConnection *conn,
+ DBusDispatchStatus status, void *data)
+{
+ if (!dbus_connection_get_is_connected(conn))
+ return;
+
+ queue_dispatch(conn, status);
+}
+
+static inline void setup_dbus_with_main_loop(DBusConnection *conn)
+{
+ dbus_connection_set_watch_functions(conn, add_watch, remove_watch,
+ watch_toggled, conn, NULL);
+
+ dbus_connection_set_timeout_functions(conn, add_timeout, remove_timeout,
+ timeout_toggled, NULL, NULL);
+
+ dbus_connection_set_dispatch_status_function(conn, dispatch_status,
+ NULL, NULL);
+}
+
+static gboolean setup_bus(DBusConnection *conn, const char *name,
+ DBusError *error)
+{
+ gboolean result;
+ DBusDispatchStatus status;
+
+ if (name != NULL) {
+ result = g_dbus_request_name(conn, name, error);
+
+ if (error != NULL) {
+ if (dbus_error_is_set(error) == TRUE)
+ return FALSE;
+ }
+
+ if (result == FALSE)
+ return FALSE;
+ }
+
+ setup_dbus_with_main_loop(conn);
+
+ status = dbus_connection_get_dispatch_status(conn);
+ queue_dispatch(conn, status);
+
+ return TRUE;
+}
+
+DBusConnection *g_dbus_setup_bus(DBusBusType type, const char *name,
+ DBusError *error)
+{
+ DBusConnection *conn;
+
+ conn = dbus_bus_get(type, error);
+
+ if (error != NULL) {
+ if (dbus_error_is_set(error) == TRUE)
+ return NULL;
+ }
+
+ if (conn == NULL)
+ return NULL;
+
+ if (setup_bus(conn, name, error) == FALSE) {
+ dbus_connection_unref(conn);
+ return NULL;
+ }
+
+ return conn;
+}
+
+DBusConnection *g_dbus_setup_private(DBusBusType type, const char *name,
+ DBusError *error)
+{
+ DBusConnection *conn;
+
+ conn = dbus_bus_get_private(type, error);
+
+ if (error != NULL) {
+ if (dbus_error_is_set(error) == TRUE)
+ return NULL;
+ }
+
+ if (conn == NULL)
+ return NULL;
+
+ if (setup_bus(conn, name, error) == FALSE) {
+ dbus_connection_unref(conn);
+ return NULL;
+ }
+
+ return conn;
+}
+
+gboolean g_dbus_request_name(DBusConnection *connection, const char *name,
+ DBusError *error)
+{
+ int result;
+
+ result = dbus_bus_request_name(connection, name,
+ DBUS_NAME_FLAG_DO_NOT_QUEUE, error);
+
+ if (error != NULL) {
+ if (dbus_error_is_set(error) == TRUE)
+ return FALSE;
+ }
+
+ if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+ if (error != NULL)
+ dbus_set_error(error, name, "Name already in use");
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean g_dbus_set_disconnect_function(DBusConnection *connection,
+ GDBusWatchFunction function,
+ void *user_data, DBusFreeFunction destroy)
+{
+ struct disconnect_data *dc_data;
+
+ dc_data = g_new0(struct disconnect_data, 1);
+
+ dc_data->function = function;
+ dc_data->user_data = user_data;
+
+ dbus_connection_set_exit_on_disconnect(connection, FALSE);
+
+ if (g_dbus_add_signal_watch(connection, NULL, NULL,
+ DBUS_INTERFACE_LOCAL, "Disconnected",
+ disconnected_signal, dc_data, g_free) == 0) {
+ error("Failed to add watch for D-Bus Disconnected signal");
+ g_free(dc_data);
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/gdbus/object.c b/gdbus/object.c
new file mode 100644
index 0000000..d17a101
--- /dev/null
+++ b/gdbus/object.c
@@ -0,0 +1,868 @@
+/*
+ *
+ * D-Bus helper library
+ *
+ * Copyright (C) 2004-2011 Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ * 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 <stdio.h>
+#include <string.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+
+#include "gdbus.h"
+
+#define info(fmt...)
+#define error(fmt...)
+#define debug(fmt...)
+
+struct generic_data {
+ unsigned int refcount;
+ GSList *interfaces;
+ char *introspect;
+};
+
+struct interface_data {
+ char *name;
+ const GDBusMethodTable *methods;
+ const GDBusSignalTable *signals;
+ const GDBusPropertyTable *properties;
+ void *user_data;
+ GDBusDestroyFunction destroy;
+};
+
+struct security_data {
+ GDBusPendingReply pending;
+ DBusMessage *message;
+ const GDBusMethodTable *method;
+ void *iface_user_data;
+};
+
+static void print_arguments(GString *gstr, const char *sig,
+ const char *direction)
+{
+ int i;
+
+ for (i = 0; sig[i]; i++) {
+ char type[32];
+ int struct_level, dict_level;
+ unsigned int len;
+ gboolean complete;
+
+ complete = FALSE;
+ struct_level = dict_level = 0;
+ memset(type, 0, sizeof(type));
+
+ /* Gather enough data to have a single complete type */
+ for (len = 0; len < (sizeof(type) - 1) && sig[i]; len++, i++) {
+ switch (sig[i]){
+ case '(':
+ struct_level++;
+ break;
+ case ')':
+ struct_level--;
+ if (struct_level <= 0 && dict_level <= 0)
+ complete = TRUE;
+ break;
+ case '{':
+ dict_level++;
+ break;
+ case '}':
+ dict_level--;
+ if (struct_level <= 0 && dict_level <= 0)
+ complete = TRUE;
+ break;
+ case 'a':
+ break;
+ default:
+ if (struct_level <= 0 && dict_level <= 0)
+ complete = TRUE;
+ break;
+ }
+
+ type[len] = sig[i];
+
+ if (complete)
+ break;
+ }
+
+
+ if (direction)
+ g_string_append_printf(gstr,
+ "\t\t\t<arg type=\"%s\" direction=\"%s\"/>\n",
+ type, direction);
+ else
+ g_string_append_printf(gstr,
+ "\t\t\t<arg type=\"%s\"/>\n",
+ type);
+ }
+}
+
+static void generate_interface_xml(GString *gstr, struct interface_data *iface)
+{
+ const GDBusMethodTable *method;
+ const GDBusSignalTable *signal;
+
+ for (method = iface->methods; method && method->name; method++) {
+ if (!strlen(method->signature) && !strlen(method->reply))
+ g_string_append_printf(gstr, "\t\t<method name=\"%s\"/>\n",
+ method->name);
+ else {
+ g_string_append_printf(gstr, "\t\t<method name=\"%s\">\n",
+ method->name);
+ print_arguments(gstr, method->signature, "in");
+ print_arguments(gstr, method->reply, "out");
+ g_string_append_printf(gstr, "\t\t</method>\n");
+ }
+ }
+
+ for (signal = iface->signals; signal && signal->name; signal++) {
+ if (!strlen(signal->signature))
+ g_string_append_printf(gstr, "\t\t<signal name=\"%s\"/>\n",
+ signal->name);
+ else {
+ g_string_append_printf(gstr, "\t\t<signal name=\"%s\">\n",
+ signal->name);
+ print_arguments(gstr, signal->signature, NULL);
+ g_string_append_printf(gstr, "\t\t</signal>\n");
+ }
+ }
+}
+
+static void generate_introspection_xml(DBusConnection *conn,
+ struct generic_data *data, const char *path)
+{
+ GSList *list;
+ GString *gstr;
+ char **children;
+ int i;
+
+ g_free(data->introspect);
+
+ gstr = g_string_new(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE);
+
+ g_string_append_printf(gstr, "<node>\n");
+
+ for (list = data->interfaces; list; list = list->next) {
+ struct interface_data *iface = list->data;
+
+ g_string_append_printf(gstr, "\t<interface name=\"%s\">\n",
+ iface->name);
+
+ generate_interface_xml(gstr, iface);
+
+ g_string_append_printf(gstr, "\t</interface>\n");
+ }
+
+ if (!dbus_connection_list_registered(conn, path, &children))
+ goto done;
+
+ for (i = 0; children[i]; i++)
+ g_string_append_printf(gstr, "\t<node name=\"%s\"/>\n",
+ children[i]);
+
+ dbus_free_string_array(children);
+
+done:
+ g_string_append_printf(gstr, "</node>\n");
+
+ data->introspect = g_string_free(gstr, FALSE);
+}
+
+static DBusMessage *introspect(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ struct generic_data *data = user_data;
+ DBusMessage *reply;
+
+ if (!dbus_message_has_signature(message, DBUS_TYPE_INVALID_AS_STRING)) {
+ error("Unexpected signature to introspect call");
+ return NULL;
+ }
+
+ if (data->introspect == NULL)
+ generate_introspection_xml(connection, data,
+ dbus_message_get_path(message));
+
+ reply = dbus_message_new_method_return(message);
+ if (reply == NULL)
+ return NULL;
+
+ dbus_message_append_args(reply, DBUS_TYPE_STRING, &data->introspect,
+ DBUS_TYPE_INVALID);
+
+ return reply;
+}
+
+static DBusHandlerResult process_message(DBusConnection *connection,
+ DBusMessage *message, const GDBusMethodTable *method,
+ void *iface_user_data)
+{
+ DBusMessage *reply;
+
+ reply = method->function(connection, message, iface_user_data);
+
+ if (method->flags & G_DBUS_METHOD_FLAG_NOREPLY) {
+ if (reply != NULL)
+ dbus_message_unref(reply);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ if (method->flags & G_DBUS_METHOD_FLAG_ASYNC) {
+ if (reply == NULL)
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ if (reply == NULL)
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+ dbus_connection_send(connection, reply, NULL);
+ dbus_message_unref(reply);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static GDBusPendingReply next_pending = 1;
+static GSList *pending_security = NULL;
+
+static const GDBusSecurityTable *security_table = NULL;
+
+void g_dbus_pending_success(DBusConnection *connection,
+ GDBusPendingReply pending)
+{
+ GSList *list;
+
+ for (list = pending_security; list; list = list->next) {
+ struct security_data *secdata = list->data;
+
+ if (secdata->pending != pending)
+ continue;
+
+ pending_security = g_slist_remove(pending_security, secdata);
+
+ process_message(connection, secdata->message,
+ secdata->method, secdata->iface_user_data);
+
+ dbus_message_unref(secdata->message);
+ g_free(secdata);
+ return;
+ }
+}
+
+void g_dbus_pending_error_valist(DBusConnection *connection,
+ GDBusPendingReply pending, const char *name,
+ const char *format, va_list args)
+{
+ GSList *list;
+
+ for (list = pending_security; list; list = list->next) {
+ struct security_data *secdata = list->data;
+ DBusMessage *reply;
+
+ if (secdata->pending != pending)
+ continue;
+
+ pending_security = g_slist_remove(pending_security, secdata);
+
+ reply = g_dbus_create_error_valist(secdata->message,
+ name, format, args);
+ if (reply != NULL) {
+ dbus_connection_send(connection, reply, NULL);
+ dbus_message_unref(reply);
+ }
+
+ dbus_message_unref(secdata->message);
+ g_free(secdata);
+ return;
+ }
+}
+
+void g_dbus_pending_error(DBusConnection *connection,
+ GDBusPendingReply pending,
+ const char *name, const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+
+ g_dbus_pending_error_valist(connection, pending, name, format, args);
+
+ va_end(args);
+}
+
+int polkit_check_authorization(DBusConnection *conn,
+ const char *action, gboolean interaction,
+ void (*function) (dbus_bool_t authorized,
+ void *user_data),
+ void *user_data, int timeout);
+
+struct builtin_security_data {
+ DBusConnection *conn;
+ GDBusPendingReply pending;
+};
+
+static void builtin_security_result(dbus_bool_t authorized, void *user_data)
+{
+ struct builtin_security_data *data = user_data;
+
+ if (authorized == TRUE)
+ g_dbus_pending_success(data->conn, data->pending);
+ else
+ g_dbus_pending_error(data->conn, data->pending,
+ DBUS_ERROR_AUTH_FAILED, NULL);
+
+ g_free(data);
+}
+
+static void builtin_security_function(DBusConnection *conn,
+ const char *action,
+ gboolean interaction,
+ GDBusPendingReply pending)
+{
+ struct builtin_security_data *data;
+
+ data = g_new0(struct builtin_security_data, 1);
+ data->conn = conn;
+ data->pending = pending;
+
+ if (polkit_check_authorization(conn, action, interaction,
+ builtin_security_result, data, 30000) < 0)
+ g_dbus_pending_error(conn, pending, NULL, NULL);
+}
+
+static gboolean check_privilege(DBusConnection *conn, DBusMessage *msg,
+ const GDBusMethodTable *method, void *iface_user_data)
+{
+ const GDBusSecurityTable *security;
+
+ for (security = security_table; security && security->privilege;
+ security++) {
+ struct security_data *secdata;
+ gboolean interaction;
+
+ if (security->privilege != method->privilege)
+ continue;
+
+ secdata = g_new(struct security_data, 1);
+ secdata->pending = next_pending++;
+ secdata->message = dbus_message_ref(msg);
+ secdata->method = method;
+ secdata->iface_user_data = iface_user_data;
+
+ pending_security = g_slist_prepend(pending_security, secdata);
+
+ if (security->flags & G_DBUS_SECURITY_FLAG_ALLOW_INTERACTION)
+ interaction = TRUE;
+ else
+ interaction = FALSE;
+
+ if (!(security->flags & G_DBUS_SECURITY_FLAG_BUILTIN) &&
+ security->function)
+ security->function(conn, security->action,
+ interaction, secdata->pending);
+ else
+ builtin_security_function(conn, security->action,
+ interaction, secdata->pending);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void generic_unregister(DBusConnection *connection, void *user_data)
+{
+ struct generic_data *data = user_data;
+
+ g_free(data->introspect);
+ g_free(data);
+}
+
+static struct interface_data *find_interface(GSList *interfaces,
+ const char *name)
+{
+ GSList *list;
+
+ if (name == NULL)
+ return NULL;
+
+ for (list = interfaces; list; list = list->next) {
+ struct interface_data *iface = list->data;
+ if (!strcmp(name, iface->name))
+ return iface;
+ }
+
+ return NULL;
+}
+
+static DBusHandlerResult generic_message(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ struct generic_data *data = user_data;
+ struct interface_data *iface;
+ const GDBusMethodTable *method;
+ const char *interface;
+
+ interface = dbus_message_get_interface(message);
+
+ iface = find_interface(data->interfaces, interface);
+ if (iface == NULL)
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ for (method = iface->methods; method &&
+ method->name && method->function; method++) {
+ if (dbus_message_is_method_call(message, iface->name,
+ method->name) == FALSE)
+ continue;
+
+ if (dbus_message_has_signature(message,
+ method->signature) == FALSE)
+ continue;
+
+ if (check_privilege(connection, message, method,
+ iface->user_data) == TRUE)
+ return DBUS_HANDLER_RESULT_HANDLED;
+
+ return process_message(connection, message, method,
+ iface->user_data);
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static DBusObjectPathVTable generic_table = {
+ .unregister_function = generic_unregister,
+ .message_function = generic_message,
+};
+
+static void invalidate_parent_data(DBusConnection *conn, const char *child_path)
+{
+ struct generic_data *data = NULL;
+ char *parent_path, *slash;
+
+ parent_path = g_strdup(child_path);
+ slash = strrchr(parent_path, '/');
+ if (slash == NULL)
+ goto done;
+
+ if (slash == parent_path && parent_path[1] != '\0')
+ parent_path[1] = '\0';
+ else
+ *slash = '\0';
+
+ if (!strlen(parent_path))
+ goto done;
+
+ if (dbus_connection_get_object_path_data(conn, parent_path,
+ (void *) &data) == FALSE) {
+ goto done;
+ }
+
+ invalidate_parent_data(conn, parent_path);
+
+ if (data == NULL)
+ goto done;
+
+ g_free(data->introspect);
+ data->introspect = NULL;
+
+done:
+ g_free(parent_path);
+}
+
+static GDBusMethodTable introspect_methods[] = {
+ { "Introspect", "", "s", introspect },
+ { }
+};
+
+static void add_interface(struct generic_data *data, const char *name,
+ const GDBusMethodTable *methods,
+ const GDBusSignalTable *signals,
+ const GDBusPropertyTable *properties,
+ void *user_data,
+ GDBusDestroyFunction destroy)
+{
+ struct interface_data *iface;
+
+ iface = g_new0(struct interface_data, 1);
+ iface->name = g_strdup(name);
+ iface->methods = methods;
+ iface->signals = signals;
+ iface->properties = properties;
+ iface->user_data = user_data;
+ iface->destroy = destroy;
+
+ data->interfaces = g_slist_append(data->interfaces, iface);
+}
+
+static struct generic_data *object_path_ref(DBusConnection *connection,
+ const char *path)
+{
+ struct generic_data *data;
+
+ if (dbus_connection_get_object_path_data(connection, path,
+ (void *) &data) == TRUE) {
+ if (data != NULL) {
+ data->refcount++;
+ return data;
+ }
+ }
+
+ data = g_new0(struct generic_data, 1);
+ data->refcount = 1;
+
+ data->introspect = g_strdup(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE "<node></node>");
+
+ if (!dbus_connection_register_object_path(connection, path,
+ &generic_table, data)) {
+ g_free(data->introspect);
+ g_free(data);
+ return NULL;
+ }
+
+ invalidate_parent_data(connection, path);
+
+ add_interface(data, DBUS_INTERFACE_INTROSPECTABLE,
+ introspect_methods, NULL, NULL, data, NULL);
+
+ return data;
+}
+
+static gboolean remove_interface(struct generic_data *data, const char *name)
+{
+ struct interface_data *iface;
+
+ iface = find_interface(data->interfaces, name);
+ if (iface == NULL)
+ return FALSE;
+
+ data->interfaces = g_slist_remove(data->interfaces, iface);
+
+ if (iface->destroy)
+ iface->destroy(iface->user_data);
+
+ g_free(iface->name);
+ g_free(iface);
+
+ return TRUE;
+}
+
+static void object_path_unref(DBusConnection *connection, const char *path)
+{
+ struct generic_data *data = NULL;
+
+ if (dbus_connection_get_object_path_data(connection, path,
+ (void *) &data) == FALSE)
+ return;
+
+ if (data == NULL)
+ return;
+
+ data->refcount--;
+
+ if (data->refcount > 0)
+ return;
+
+ remove_interface(data, DBUS_INTERFACE_INTROSPECTABLE);
+
+ invalidate_parent_data(connection, path);
+
+ dbus_connection_unregister_object_path(connection, path);
+}
+
+static gboolean check_signal(DBusConnection *conn, const char *path,
+ const char *interface, const char *name,
+ const char **args)
+{
+ struct generic_data *data = NULL;
+ struct interface_data *iface;
+ const GDBusSignalTable *signal;
+
+ *args = NULL;
+ if (!dbus_connection_get_object_path_data(conn, path,
+ (void *) &data) || data == NULL) {
+ error("dbus_connection_emit_signal: path %s isn't registered",
+ path);
+ return FALSE;
+ }
+
+ iface = find_interface(data->interfaces, interface);
+ if (iface == NULL) {
+ error("dbus_connection_emit_signal: %s does not implement %s",
+ path, interface);
+ return FALSE;
+ }
+
+ for (signal = iface->signals; signal && signal->name; signal++) {
+ if (!strcmp(signal->name, name)) {
+ *args = signal->signature;
+ break;
+ }
+ }
+
+ if (*args == NULL) {
+ error("No signal named %s on interface %s", name, interface);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static dbus_bool_t emit_signal_valist(DBusConnection *conn,
+ const char *path,
+ const char *interface,
+ const char *name,
+ int first,
+ va_list var_args)
+{
+ DBusMessage *signal;
+ dbus_bool_t ret;
+ const char *signature, *args;
+
+ if (!check_signal(conn, path, interface, name, &args))
+ return FALSE;
+
+ signal = dbus_message_new_signal(path, interface, name);
+ if (signal == NULL) {
+ error("Unable to allocate new %s.%s signal", interface, name);
+ return FALSE;
+ }
+
+ ret = dbus_message_append_args_valist(signal, first, var_args);
+ if (!ret)
+ goto fail;
+
+ signature = dbus_message_get_signature(signal);
+ if (strcmp(args, signature) != 0) {
+ error("%s.%s: expected signature'%s' but got '%s'",
+ interface, name, args, signature);
+ ret = FALSE;
+ goto fail;
+ }
+
+ ret = dbus_connection_send(conn, signal, NULL);
+
+fail:
+ dbus_message_unref(signal);
+
+ return ret;
+}
+
+gboolean g_dbus_register_interface(DBusConnection *connection,
+ const char *path, const char *name,
+ const GDBusMethodTable *methods,
+ const GDBusSignalTable *signals,
+ const GDBusPropertyTable *properties,
+ void *user_data,
+ GDBusDestroyFunction destroy)
+{
+ struct generic_data *data;
+
+ data = object_path_ref(connection, path);
+ if (data == NULL)
+ return FALSE;
+
+ if (find_interface(data->interfaces, name)) {
+ object_path_unref(connection, path);
+ return FALSE;
+ }
+
+ add_interface(data, name, methods, signals,
+ properties, user_data, destroy);
+
+ g_free(data->introspect);
+ data->introspect = NULL;
+
+ return TRUE;
+}
+
+gboolean g_dbus_unregister_interface(DBusConnection *connection,
+ const char *path, const char *name)
+{
+ struct generic_data *data = NULL;
+
+ if (path == NULL)
+ return FALSE;
+
+ if (dbus_connection_get_object_path_data(connection, path,
+ (void *) &data) == FALSE)
+ return FALSE;
+
+ if (data == NULL)
+ return FALSE;
+
+ if (remove_interface(data, name) == FALSE)
+ return FALSE;
+
+ g_free(data->introspect);
+ data->introspect = NULL;
+
+ object_path_unref(connection, path);
+
+ return TRUE;
+}
+
+gboolean g_dbus_register_security(const GDBusSecurityTable *security)
+{
+ if (security_table != NULL)
+ return FALSE;
+
+ security_table = security;
+
+ return TRUE;
+}
+
+gboolean g_dbus_unregister_security(const GDBusSecurityTable *security)
+{
+ security_table = NULL;
+
+ return TRUE;
+}
+
+DBusMessage *g_dbus_create_error_valist(DBusMessage *message, const char *name,
+ const char *format, va_list args)
+{
+ char str[1024];
+
+ vsnprintf(str, sizeof(str), format, args);
+
+ return dbus_message_new_error(message, name, str);
+}
+
+DBusMessage *g_dbus_create_error(DBusMessage *message, const char *name,
+ const char *format, ...)
+{
+ va_list args;
+ DBusMessage *reply;
+
+ va_start(args, format);
+
+ reply = g_dbus_create_error_valist(message, name, format, args);
+
+ va_end(args);
+
+ return reply;
+}
+
+DBusMessage *g_dbus_create_reply_valist(DBusMessage *message,
+ int type, va_list args)
+{
+ DBusMessage *reply;
+
+ reply = dbus_message_new_method_return(message);
+ if (reply == NULL)
+ return NULL;
+
+ if (dbus_message_append_args_valist(reply, type, args) == FALSE) {
+ dbus_message_unref(reply);
+ return NULL;
+ }
+
+ return reply;
+}
+
+DBusMessage *g_dbus_create_reply(DBusMessage *message, int type, ...)
+{
+ va_list args;
+ DBusMessage *reply;
+
+ va_start(args, type);
+
+ reply = g_dbus_create_reply_valist(message, type, args);
+
+ va_end(args);
+
+ return reply;
+}
+
+gboolean g_dbus_send_message(DBusConnection *connection, DBusMessage *message)
+{
+ dbus_bool_t result;
+
+ if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
+ dbus_message_set_no_reply(message, TRUE);
+
+ result = dbus_connection_send(connection, message, NULL);
+
+ dbus_message_unref(message);
+
+ return result;
+}
+
+gboolean g_dbus_send_reply_valist(DBusConnection *connection,
+ DBusMessage *message, int type, va_list args)
+{
+ DBusMessage *reply;
+
+ reply = dbus_message_new_method_return(message);
+ if (reply == NULL)
+ return FALSE;
+
+ if (dbus_message_append_args_valist(reply, type, args) == FALSE) {
+ dbus_message_unref(reply);
+ return FALSE;
+ }
+
+ return g_dbus_send_message(connection, reply);
+}
+
+gboolean g_dbus_send_reply(DBusConnection *connection,
+ DBusMessage *message, int type, ...)
+{
+ va_list args;
+ gboolean result;
+
+ va_start(args, type);
+
+ result = g_dbus_send_reply_valist(connection, message, type, args);
+
+ va_end(args);
+
+ return result;
+}
+
+gboolean g_dbus_emit_signal(DBusConnection *connection,
+ const char *path, const char *interface,
+ const char *name, int type, ...)
+{
+ va_list args;
+ gboolean result;
+
+ va_start(args, type);
+
+ result = emit_signal_valist(connection, path, interface,
+ name, type, args);
+
+ va_end(args);
+
+ return result;
+}
+
+gboolean g_dbus_emit_signal_valist(DBusConnection *connection,
+ const char *path, const char *interface,
+ const char *name, int type, va_list args)
+{
+ return emit_signal_valist(connection, path, interface,
+ name, type, args);
+}
diff --git a/gdbus/polkit.c b/gdbus/polkit.c
new file mode 100644
index 0000000..9e95fa3
--- /dev/null
+++ b/gdbus/polkit.c
@@ -0,0 +1,202 @@
+/*
+ *
+ * D-Bus helper library
+ *
+ * Copyright (C) 2004-2011 Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ * 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 <errno.h>
+
+#include <dbus/dbus.h>
+
+#include <glib.h>
+
+int polkit_check_authorization(DBusConnection *conn,
+ const char *action, gboolean interaction,
+ void (*function) (dbus_bool_t authorized,
+ void *user_data),
+ void *user_data, int timeout);
+
+static void add_dict_with_string_value(DBusMessageIter *iter,
+ const char *key, const char *str)
+{
+ DBusMessageIter dict, entry, value;
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+ dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
+ NULL, &entry);
+
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+
+ dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
+ DBUS_TYPE_STRING_AS_STRING, &value);
+ dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &str);
+ dbus_message_iter_close_container(&entry, &value);
+
+ dbus_message_iter_close_container(&dict, &entry);
+ dbus_message_iter_close_container(iter, &dict);
+}
+
+static void add_empty_string_dict(DBusMessageIter *iter)
+{
+ DBusMessageIter dict;
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_STRING_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+ dbus_message_iter_close_container(iter, &dict);
+}
+
+static void add_arguments(DBusConnection *conn, DBusMessageIter *iter,
+ const char *action, dbus_uint32_t flags)
+{
+ const char *busname = dbus_bus_get_unique_name(conn);
+ const char *kind = "system-bus-name";
+ const char *cancel = "";
+ DBusMessageIter subject;
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT,
+ NULL, &subject);
+ dbus_message_iter_append_basic(&subject, DBUS_TYPE_STRING, &kind);
+ add_dict_with_string_value(&subject, "name", busname);
+ dbus_message_iter_close_container(iter, &subject);
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &action);
+ add_empty_string_dict(iter);
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &flags);
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &cancel);
+}
+
+static dbus_bool_t parse_result(DBusMessageIter *iter)
+{
+ DBusMessageIter result;
+ dbus_bool_t authorized, challenge;
+
+ dbus_message_iter_recurse(iter, &result);
+
+ dbus_message_iter_get_basic(&result, &authorized);
+ dbus_message_iter_get_basic(&result, &challenge);
+
+ return authorized;
+}
+
+struct authorization_data {
+ void (*function) (dbus_bool_t authorized, void *user_data);
+ void *user_data;
+};
+
+static void authorization_reply(DBusPendingCall *call, void *user_data)
+{
+ struct authorization_data *data = user_data;
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ dbus_bool_t authorized = FALSE;
+
+ reply = dbus_pending_call_steal_reply(call);
+
+ if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
+ goto done;
+
+ if (dbus_message_has_signature(reply, "(bba{ss})") == FALSE)
+ goto done;
+
+ dbus_message_iter_init(reply, &iter);
+
+ authorized = parse_result(&iter);
+
+done:
+ if (data->function != NULL)
+ data->function(authorized, data->user_data);
+
+ dbus_message_unref(reply);
+
+ dbus_pending_call_unref(call);
+}
+
+#define AUTHORITY_DBUS "org.freedesktop.PolicyKit1"
+#define AUTHORITY_INTF "org.freedesktop.PolicyKit1.Authority"
+#define AUTHORITY_PATH "/org/freedesktop/PolicyKit1/Authority"
+
+int polkit_check_authorization(DBusConnection *conn,
+ const char *action, gboolean interaction,
+ void (*function) (dbus_bool_t authorized,
+ void *user_data),
+ void *user_data, int timeout)
+{
+ struct authorization_data *data;
+ DBusMessage *msg;
+ DBusMessageIter iter;
+ DBusPendingCall *call;
+ dbus_uint32_t flags = 0x00000000;
+
+ if (conn == NULL)
+ return -EINVAL;
+
+ data = dbus_malloc0(sizeof(*data));
+ if (data == NULL)
+ return -ENOMEM;
+
+ msg = dbus_message_new_method_call(AUTHORITY_DBUS, AUTHORITY_PATH,
+ AUTHORITY_INTF, "CheckAuthorization");
+ if (msg == NULL) {
+ dbus_free(data);
+ return -ENOMEM;
+ }
+
+ if (interaction == TRUE)
+ flags |= 0x00000001;
+
+ if (action == NULL)
+ action = "org.freedesktop.policykit.exec";
+
+ dbus_message_iter_init_append(msg, &iter);
+ add_arguments(conn, &iter, action, flags);
+
+ if (dbus_connection_send_with_reply(conn, msg,
+ &call, timeout) == FALSE) {
+ dbus_message_unref(msg);
+ dbus_free(data);
+ return -EIO;
+ }
+
+ if (call == NULL) {
+ dbus_message_unref(msg);
+ dbus_free(data);
+ return -EIO;
+ }
+
+ data->function = function;
+ data->user_data = user_data;
+
+ dbus_pending_call_set_notify(call, authorization_reply,
+ data, dbus_free);
+
+ dbus_message_unref(msg);
+
+ return 0;
+}
diff --git a/gdbus/watch.c b/gdbus/watch.c
new file mode 100644
index 0000000..fba58c3
--- /dev/null
+++ b/gdbus/watch.c
@@ -0,0 +1,748 @@
+/*
+ *
+ * D-Bus helper library
+ *
+ * Copyright (C) 2004-2011 Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ * 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 <stdio.h>
+#include <string.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+
+#include "gdbus.h"
+
+#define info(fmt...)
+#define error(fmt...)
+#define debug(fmt...)
+
+static DBusHandlerResult message_filter(DBusConnection *connection,
+ DBusMessage *message, void *user_data);
+
+static guint listener_id = 0;
+static GSList *listeners = NULL;
+
+struct service_data {
+ DBusConnection *conn;
+ DBusPendingCall *call;
+ char *name;
+ const char *owner;
+ guint id;
+ struct filter_callback *callback;
+};
+
+struct filter_callback {
+ GDBusWatchFunction conn_func;
+ GDBusWatchFunction disc_func;
+ GDBusSignalFunction signal_func;
+ GDBusDestroyFunction destroy_func;
+ struct service_data *data;
+ void *user_data;
+ guint id;
+};
+
+struct filter_data {
+ DBusConnection *connection;
+ DBusHandleMessageFunction handle_func;
+ char *name;
+ char *owner;
+ char *path;
+ char *interface;
+ char *member;
+ char *argument;
+ GSList *callbacks;
+ GSList *processed;
+ guint name_watch;
+ gboolean lock;
+ gboolean registered;
+};
+
+static struct filter_data *filter_data_find(DBusConnection *connection,
+ const char *name,
+ const char *owner,
+ const char *path,
+ const char *interface,
+ const char *member,
+ const char *argument)
+{
+ GSList *current;
+
+ for (current = listeners;
+ current != NULL; current = current->next) {
+ struct filter_data *data = current->data;
+
+ if (connection != data->connection)
+ continue;
+
+ if (name && data->name &&
+ g_str_equal(name, data->name) == FALSE)
+ continue;
+
+ if (owner && data->owner &&
+ g_str_equal(owner, data->owner) == FALSE)
+ continue;
+
+ if (path && data->path &&
+ g_str_equal(path, data->path) == FALSE)
+ continue;
+
+ if (interface && data->interface &&
+ g_str_equal(interface, data->interface) == FALSE)
+ continue;
+
+ if (member && data->member &&
+ g_str_equal(member, data->member) == FALSE)
+ continue;
+
+ if (argument && data->argument &&
+ g_str_equal(argument, data->argument) == FALSE)
+ continue;
+
+ return data;
+ }
+
+ return NULL;
+}
+
+static void format_rule(struct filter_data *data, char *rule, size_t size)
+{
+ const char *sender;
+ int offset;
+
+ offset = snprintf(rule, size, "type='signal'");
+ sender = data->name ? : data->owner;
+
+ if (sender)
+ offset += snprintf(rule + offset, size - offset,
+ ",sender='%s'", sender);
+ if (data->path)
+ offset += snprintf(rule + offset, size - offset,
+ ",path='%s'", data->path);
+ if (data->interface)
+ offset += snprintf(rule + offset, size - offset,
+ ",interface='%s'", data->interface);
+ if (data->member)
+ offset += snprintf(rule + offset, size - offset,
+ ",member='%s'", data->member);
+ if (data->argument)
+ snprintf(rule + offset, size - offset,
+ ",arg0='%s'", data->argument);
+}
+
+static gboolean add_match(struct filter_data *data,
+ DBusHandleMessageFunction filter)
+{
+ DBusError err;
+ char rule[DBUS_MAXIMUM_MATCH_RULE_LENGTH];
+
+ format_rule(data, rule, sizeof(rule));
+ dbus_error_init(&err);
+
+ dbus_bus_add_match(data->connection, rule, &err);
+ if (dbus_error_is_set(&err)) {
+ error("Adding match rule \"%s\" failed: %s", rule,
+ err.message);
+ dbus_error_free(&err);
+ return FALSE;
+ }
+
+ data->handle_func = filter;
+ data->registered = TRUE;
+
+ return TRUE;
+}
+
+static gboolean remove_match(struct filter_data *data)
+{
+ DBusError err;
+ char rule[DBUS_MAXIMUM_MATCH_RULE_LENGTH];
+
+ format_rule(data, rule, sizeof(rule));
+
+ dbus_error_init(&err);
+
+ dbus_bus_remove_match(data->connection, rule, &err);
+ if (dbus_error_is_set(&err)) {
+ error("Removing owner match rule for %s failed: %s",
+ rule, err.message);
+ dbus_error_free(&err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static struct filter_data *filter_data_get(DBusConnection *connection,
+ DBusHandleMessageFunction filter,
+ const char *sender,
+ const char *path,
+ const char *interface,
+ const char *member,
+ const char *argument)
+{
+ struct filter_data *data;
+ const char *name = NULL, *owner = NULL;
+
+ if (filter_data_find(connection, NULL, NULL, NULL, NULL, NULL, NULL) == NULL) {
+ if (!dbus_connection_add_filter(connection,
+ message_filter, NULL, NULL)) {
+ error("dbus_connection_add_filter() failed");
+ return NULL;
+ }
+ }
+
+ if (sender == NULL)
+ goto proceed;
+
+ if (sender[0] == ':')
+ owner = sender;
+ else
+ name = sender;
+
+proceed:
+ data = filter_data_find(connection, name, owner, path, interface,
+ member, argument);
+ if (data)
+ return data;
+
+ data = g_new0(struct filter_data, 1);
+
+ data->connection = dbus_connection_ref(connection);
+ data->name = name ? g_strdup(name) : NULL;
+ data->owner = owner ? g_strdup(owner) : NULL;
+ data->path = g_strdup(path);
+ data->interface = g_strdup(interface);
+ data->member = g_strdup(member);
+ data->argument = g_strdup(argument);
+
+ if (!add_match(data, filter)) {
+ g_free(data);
+ return NULL;
+ }
+
+ listeners = g_slist_append(listeners, data);
+
+ return data;
+}
+
+static struct filter_callback *filter_data_find_callback(
+ struct filter_data *data,
+ guint id)
+{
+ GSList *l;
+
+ for (l = data->callbacks; l; l = l->next) {
+ struct filter_callback *cb = l->data;
+ if (cb->id == id)
+ return cb;
+ }
+ for (l = data->processed; l; l = l->next) {
+ struct filter_callback *cb = l->data;
+ if (cb->id == id)
+ return cb;
+ }
+
+ return NULL;
+}
+
+static void filter_data_free(struct filter_data *data)
+{
+ GSList *l;
+
+ for (l = data->callbacks; l != NULL; l = l->next)
+ g_free(l->data);
+
+ g_slist_free(data->callbacks);
+ g_dbus_remove_watch(data->connection, data->name_watch);
+ g_free(data->name);
+ g_free(data->owner);
+ g_free(data->path);
+ g_free(data->interface);
+ g_free(data->member);
+ g_free(data->argument);
+ dbus_connection_unref(data->connection);
+ g_free(data);
+}
+
+static void filter_data_call_and_free(struct filter_data *data)
+{
+ GSList *l;
+
+ for (l = data->callbacks; l != NULL; l = l->next) {
+ struct filter_callback *cb = l->data;
+ if (cb->disc_func)
+ cb->disc_func(data->connection, cb->user_data);
+ if (cb->destroy_func)
+ cb->destroy_func(cb->user_data);
+ g_free(cb);
+ }
+
+ filter_data_free(data);
+}
+
+static struct filter_callback *filter_data_add_callback(
+ struct filter_data *data,
+ GDBusWatchFunction connect,
+ GDBusWatchFunction disconnect,
+ GDBusSignalFunction signal,
+ GDBusDestroyFunction destroy,
+ void *user_data)
+{
+ struct filter_callback *cb = NULL;
+
+ cb = g_new0(struct filter_callback, 1);
+
+ cb->conn_func = connect;
+ cb->disc_func = disconnect;
+ cb->signal_func = signal;
+ cb->destroy_func = destroy;
+ cb->user_data = user_data;
+ cb->id = ++listener_id;
+
+ if (data->lock)
+ data->processed = g_slist_append(data->processed, cb);
+ else
+ data->callbacks = g_slist_append(data->callbacks, cb);
+
+ return cb;
+}
+
+static void service_data_free(struct service_data *data)
+{
+ struct filter_callback *callback = data->callback;
+
+ dbus_connection_unref(data->conn);
+
+ if (data->call)
+ dbus_pending_call_unref(data->call);
+
+ if (data->id)
+ g_source_remove(data->id);
+
+ g_free(data->name);
+ g_free(data);
+
+ callback->data = NULL;
+}
+
+static gboolean filter_data_remove_callback(struct filter_data *data,
+ struct filter_callback *cb)
+{
+ DBusConnection *connection;
+
+ data->callbacks = g_slist_remove(data->callbacks, cb);
+ data->processed = g_slist_remove(data->processed, cb);
+
+ /* Cancel pending operations */
+ if (cb->data) {
+ if (cb->data->call)
+ dbus_pending_call_cancel(cb->data->call);
+ service_data_free(cb->data);
+ }
+
+ if (cb->destroy_func)
+ cb->destroy_func(cb->user_data);
+
+ g_free(cb);
+
+ /* Don't remove the filter if other callbacks exist or data is lock
+ * processing callbacks */
+ if (data->callbacks || data->lock)
+ return TRUE;
+
+ if (data->registered && !remove_match(data))
+ return FALSE;
+
+ connection = dbus_connection_ref(data->connection);
+ listeners = g_slist_remove(listeners, data);
+ filter_data_free(data);
+
+ /* Remove filter if there are no listeners left for the connection */
+ data = filter_data_find(connection, NULL, NULL, NULL, NULL, NULL,
+ NULL);
+ if (data == NULL)
+ dbus_connection_remove_filter(connection, message_filter,
+ NULL);
+
+ dbus_connection_unref(connection);
+
+ return TRUE;
+}
+
+static DBusHandlerResult signal_filter(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ struct filter_data *data = user_data;
+ struct filter_callback *cb;
+
+ while (data->callbacks) {
+ cb = data->callbacks->data;
+
+ if (cb->signal_func && !cb->signal_func(connection, message,
+ cb->user_data)) {
+ filter_data_remove_callback(data, cb);
+ continue;
+ }
+
+ /* Check if the watch was removed/freed by the callback
+ * function */
+ if (!g_slist_find(data->callbacks, cb))
+ continue;
+
+ data->callbacks = g_slist_remove(data->callbacks, cb);
+ data->processed = g_slist_append(data->processed, cb);
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static void update_name_cache(const char *name, const char *owner)
+{
+ GSList *l;
+
+ for (l = listeners; l != NULL; l = l->next) {
+ struct filter_data *data = l->data;
+
+ if (g_strcmp0(data->name, name) != 0)
+ continue;
+
+ g_free(data->owner);
+ data->owner = g_strdup(owner);
+ }
+}
+
+static const char *check_name_cache(const char *name)
+{
+ GSList *l;
+
+ for (l = listeners; l != NULL; l = l->next) {
+ struct filter_data *data = l->data;
+
+ if (g_strcmp0(data->name, name) != 0)
+ continue;
+
+ return data->owner;
+ }
+
+ return NULL;
+}
+
+static DBusHandlerResult service_filter(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ struct filter_data *data = user_data;
+ struct filter_callback *cb;
+ char *name, *old, *new;
+
+ if (!dbus_message_get_args(message, NULL,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_STRING, &old,
+ DBUS_TYPE_STRING, &new,
+ DBUS_TYPE_INVALID)) {
+ error("Invalid arguments for NameOwnerChanged signal");
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ update_name_cache(name, new);
+
+ while (data->callbacks) {
+ cb = data->callbacks->data;
+
+ if (*new == '\0') {
+ if (cb->disc_func)
+ cb->disc_func(connection, cb->user_data);
+ } else {
+ if (cb->conn_func)
+ cb->conn_func(connection, cb->user_data);
+ }
+
+ /* Check if the watch was removed/freed by the callback
+ * function */
+ if (!g_slist_find(data->callbacks, cb))
+ continue;
+
+ /* Only auto remove if it is a bus name watch */
+ if (data->argument[0] == ':' &&
+ (cb->conn_func == NULL || cb->disc_func == NULL)) {
+ filter_data_remove_callback(data, cb);
+ continue;
+ }
+
+ data->callbacks = g_slist_remove(data->callbacks, cb);
+ data->processed = g_slist_append(data->processed, cb);
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+
+static DBusHandlerResult message_filter(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ struct filter_data *data;
+ const char *sender, *path, *iface, *member, *arg = NULL;
+
+ /* Only filter signals */
+ if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL)
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ sender = dbus_message_get_sender(message);
+ path = dbus_message_get_path(message);
+ iface = dbus_message_get_interface(message);
+ member = dbus_message_get_member(message);
+ dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg, DBUS_TYPE_INVALID);
+
+ /* Sender is always bus name */
+ data = filter_data_find(connection, NULL, sender, path, iface, member,
+ arg);
+ if (data == NULL) {
+ error("Got %s.%s signal which has no listeners", iface, member);
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ if (data->handle_func) {
+ data->lock = TRUE;
+
+ data->handle_func(connection, message, data);
+
+ data->callbacks = data->processed;
+ data->processed = NULL;
+ data->lock = FALSE;
+ }
+
+ if (data->callbacks)
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ remove_match(data);
+
+ listeners = g_slist_remove(listeners, data);
+ filter_data_free(data);
+
+ /* Remove filter if there no listener left for the connection */
+ data = filter_data_find(connection, NULL, NULL, NULL, NULL, NULL,
+ NULL);
+ if (data == NULL)
+ dbus_connection_remove_filter(connection, message_filter,
+ NULL);
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static gboolean update_service(void *user_data)
+{
+ struct service_data *data = user_data;
+ struct filter_callback *cb = data->callback;
+
+ update_name_cache(data->name, data->owner);
+ if (cb->conn_func)
+ cb->conn_func(data->conn, cb->user_data);
+
+ service_data_free(data);
+
+ return FALSE;
+}
+
+static void service_reply(DBusPendingCall *call, void *user_data)
+{
+ struct service_data *data = user_data;
+ DBusMessage *reply;
+ DBusError err;
+
+ reply = dbus_pending_call_steal_reply(call);
+ if (reply == NULL)
+ return;
+
+ dbus_error_init(&err);
+
+ if (dbus_set_error_from_message(&err, reply))
+ goto fail;
+
+ if (dbus_message_get_args(reply, &err,
+ DBUS_TYPE_STRING, &data->owner,
+ DBUS_TYPE_INVALID) == FALSE)
+ goto fail;
+
+ update_service(data);
+
+ goto done;
+
+fail:
+ error("%s", err.message);
+ dbus_error_free(&err);
+ service_data_free(data);
+done:
+ dbus_message_unref(reply);
+}
+
+static void check_service(DBusConnection *connection,
+ const char *name,
+ struct filter_callback *callback)
+{
+ DBusMessage *message;
+ struct service_data *data;
+
+ data = g_try_malloc0(sizeof(*data));
+ if (data == NULL) {
+ error("Can't allocate data structure");
+ return;
+ }
+
+ data->conn = dbus_connection_ref(connection);
+ data->name = g_strdup(name);
+ data->callback = callback;
+ callback->data = data;
+
+ data->owner = check_name_cache(name);
+ if (data->owner != NULL) {
+ data->id = g_idle_add(update_service, data);
+ return;
+ }
+
+ message = dbus_message_new_method_call(DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "GetNameOwner");
+ if (message == NULL) {
+ error("Can't allocate new message");
+ g_free(data);
+ return;
+ }
+
+ dbus_message_append_args(message, DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_INVALID);
+
+ if (dbus_connection_send_with_reply(connection, message,
+ &data->call, -1) == FALSE) {
+ error("Failed to execute method call");
+ g_free(data);
+ goto done;
+ }
+
+ if (data->call == NULL) {
+ error("D-Bus connection not available");
+ g_free(data);
+ goto done;
+ }
+
+ dbus_pending_call_set_notify(data->call, service_reply, data, NULL);
+
+done:
+ dbus_message_unref(message);
+}
+
+guint g_dbus_add_service_watch(DBusConnection *connection, const char *name,
+ GDBusWatchFunction connect,
+ GDBusWatchFunction disconnect,
+ void *user_data, GDBusDestroyFunction destroy)
+{
+ struct filter_data *data;
+ struct filter_callback *cb;
+
+ if (name == NULL)
+ return 0;
+
+ data = filter_data_get(connection, service_filter, NULL, NULL,
+ DBUS_INTERFACE_DBUS, "NameOwnerChanged",
+ name);
+ if (data == NULL)
+ return 0;
+
+ cb = filter_data_add_callback(data, connect, disconnect, NULL, NULL,
+ user_data);
+ if (cb == NULL)
+ return 0;
+
+ if (connect)
+ check_service(connection, name, cb);
+
+ return cb->id;
+}
+
+guint g_dbus_add_disconnect_watch(DBusConnection *connection, const char *name,
+ GDBusWatchFunction func,
+ void *user_data, GDBusDestroyFunction destroy)
+{
+ return g_dbus_add_service_watch(connection, name, NULL, func,
+ user_data, destroy);
+}
+
+guint g_dbus_add_signal_watch(DBusConnection *connection,
+ const char *sender, const char *path,
+ const char *interface, const char *member,
+ GDBusSignalFunction function, void *user_data,
+ GDBusDestroyFunction destroy)
+{
+ struct filter_data *data;
+ struct filter_callback *cb;
+
+ data = filter_data_get(connection, signal_filter, sender, path,
+ interface, member, NULL);
+ if (data == NULL)
+ return 0;
+
+ cb = filter_data_add_callback(data, NULL, NULL, function, destroy,
+ user_data);
+ if (cb == NULL)
+ return 0;
+
+ if (data->name != NULL && data->name_watch == 0)
+ data->name_watch = g_dbus_add_service_watch(connection,
+ data->name, NULL,
+ NULL, NULL, NULL);
+
+ return cb->id;
+}
+
+gboolean g_dbus_remove_watch(DBusConnection *connection, guint id)
+{
+ struct filter_data *data;
+ struct filter_callback *cb;
+ GSList *ldata;
+
+ if (id == 0)
+ return FALSE;
+
+ for (ldata = listeners; ldata; ldata = ldata->next) {
+ data = ldata->data;
+
+ cb = filter_data_find_callback(data, id);
+ if (cb) {
+ filter_data_remove_callback(data, cb);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+void g_dbus_remove_all_watches(DBusConnection *connection)
+{
+ struct filter_data *data;
+
+ while ((data = filter_data_find(connection, NULL, NULL, NULL, NULL,
+ NULL, NULL))) {
+ listeners = g_slist_remove(listeners, data);
+ filter_data_call_and_free(data);
+ }
+
+ dbus_connection_remove_filter(connection, message_filter, NULL);
+}
diff --git a/include/dbus.h b/include/dbus.h
new file mode 100644
index 0000000..0743e7a
--- /dev/null
+++ b/include/dbus.h
@@ -0,0 +1,132 @@
+/*
+ *
+ * neard - Near Field Communication manager
+ *
+ * Copyright (C) 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ *
+ */
+
+#include <dbus/dbus.h>
+
+#define NFC_SERVICE "net.near"
+#define NFC_PATH "/net/near"
+
+#define NFC_ERROR_INTERFACE NFC_SERVICE ".Error"
+
+#define NFC_MANAGER_INTERFACE NFC_SERVICE ".Manager"
+#define NFC_MANAGER_PATH "/"
+
+typedef void (* near_dbus_append_cb_t) (DBusMessageIter *iter,
+ void *user_data);
+
+DBusConnection *near_dbus_get_connection(void);
+
+void near_dbus_property_append_basic(DBusMessageIter *iter,
+ const char *key, int type, void *val);
+void near_dbus_property_append_dict(DBusMessageIter *iter, const char *key,
+ near_dbus_append_cb_t function, void *user_data);
+void near_dbus_property_append_array(DBusMessageIter *iter,
+ const char *key, int type,
+ near_dbus_append_cb_t function, void *user_data);
+void near_dbus_property_append_fixed_array(DBusMessageIter *iter,
+ const char *key, int type, void *val, int len);
+
+dbus_bool_t near_dbus_property_changed_basic(const char *path,
+ const char *interface, const char *key,
+ int type, void *val);
+dbus_bool_t near_dbus_property_changed_dict(const char *path,
+ const char *interface, const char *key,
+ near_dbus_append_cb_t function, void *user_data);
+dbus_bool_t near_dbus_property_changed_array(const char *path,
+ const char *interface, const char *key, int type,
+ near_dbus_append_cb_t function, void *user_data);
+
+dbus_bool_t near_dbus_setting_changed_basic(const char *owner,
+ const char *path, const char *key,
+ int type, void *val);
+dbus_bool_t near_dbus_setting_changed_dict(const char *owner,
+ const char *path, const char *key,
+ near_dbus_append_cb_t function,
+ void *user_data);
+dbus_bool_t near_dbus_setting_changed_array(const char *owner,
+ const char *path, const char *key, int type,
+ near_dbus_append_cb_t function,
+ void *user_data);
+
+static inline void near_dbus_dict_open(DBusMessageIter *iter,
+ DBusMessageIter *dict)
+{
+ dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING, dict);
+}
+
+static inline void near_dbus_dict_close(DBusMessageIter *iter,
+ DBusMessageIter *dict)
+{
+ dbus_message_iter_close_container(iter, dict);
+}
+
+static inline void near_dbus_dict_append_basic(DBusMessageIter *dict,
+ const char *key, int type, void *val)
+{
+ DBusMessageIter entry;
+
+ dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
+ NULL, &entry);
+ near_dbus_property_append_basic(&entry, key, type, val);
+ dbus_message_iter_close_container(dict, &entry);
+}
+
+static inline void near_dbus_dict_append_dict(DBusMessageIter *dict,
+ const char *key, near_dbus_append_cb_t function,
+ void *user_data)
+{
+ DBusMessageIter entry;
+
+ dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
+ NULL, &entry);
+ near_dbus_property_append_dict(&entry, key, function, user_data);
+ dbus_message_iter_close_container(dict, &entry);
+}
+
+static inline void near_dbus_dict_append_array(DBusMessageIter *dict,
+ const char *key, int type, near_dbus_append_cb_t function,
+ void *user_data)
+{
+ DBusMessageIter entry;
+
+ dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
+ NULL, &entry);
+ near_dbus_property_append_array(&entry, key,
+ type, function, user_data);
+ dbus_message_iter_close_container(dict, &entry);
+}
+
+static inline void near_dbus_dict_append_fixed_array(DBusMessageIter *dict,
+ const char *key, int type, void *val, int len)
+{
+ DBusMessageIter entry;
+
+ dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
+ NULL, &entry);
+ near_dbus_property_append_fixed_array(&entry, key, type, val, len);
+ dbus_message_iter_close_container(dict, &entry);
+}
+
+dbus_bool_t near_dbus_validate_ident(const char *ident);
+char *near_dbus_encode_string(const char *value);
diff --git a/src/adapter.c b/src/adapter.c
new file mode 100644
index 0000000..6f10679
--- /dev/null
+++ b/src/adapter.c
@@ -0,0 +1,62 @@
+/*
+ *
+ * neard - Near Field Communication manager
+ *
+ * Copyright (C) 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 <glib.h>
+
+#include "near.h"
+
+static GSList *adapter_list = NULL;
+
+struct near_adapter {
+ char *path;
+};
+
+static void append_path(gpointer value, gpointer user_data)
+{
+ struct near_adapter *adapter = value;
+ DBusMessageIter *iter = user_data;
+
+ if (adapter->path == NULL)
+ return;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
+ &adapter->path);
+}
+
+void __near_adapter_list(DBusMessageIter *iter, void *user_data)
+{
+ g_slist_foreach(adapter_list, append_path, iter);
+}
+
+int __near_adapter_init(void)
+{
+ DBG("");
+
+ return 0;
+}
+
+void __near_adapter_cleanup(void)
+{
+}
diff --git a/src/dbus.c b/src/dbus.c
new file mode 100644
index 0000000..232c844
--- /dev/null
+++ b/src/dbus.c
@@ -0,0 +1,294 @@
+/*
+ *
+ * neard - Near Field Communication manager
+ *
+ * Copyright (C) 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 <gdbus.h>
+
+#include "near.h"
+
+static DBusConnection *connection;
+
+dbus_bool_t near_dbus_validate_ident(const char *ident)
+{
+ unsigned int i;
+
+ if (ident == NULL)
+ return FALSE;
+
+ for (i = 0; i < strlen(ident); i++) {
+ if (ident[i] >= '0' && ident[i] <= '9')
+ continue;
+ if (ident[i] >= 'a' && ident[i] <= 'z')
+ continue;
+ if (ident[i] >= 'A' && ident[i] <= 'Z')
+ continue;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+char *near_dbus_encode_string(const char *value)
+{
+ GString *str;
+ unsigned int i, size;
+
+ if (value == NULL)
+ return NULL;
+
+ size = strlen(value);
+
+ str = g_string_new(NULL);
+ if (str == NULL)
+ return NULL;
+
+ for (i = 0; i < size; i++) {
+ const char tmp = value[i];
+ if ((tmp < '0' || tmp > '9') && (tmp < 'A' || tmp > 'Z') &&
+ (tmp < 'a' || tmp > 'z'))
+ g_string_append_printf(str, "_%02x", tmp);
+ else
+ str = g_string_append_c(str, tmp);
+ }
+
+ return g_string_free(str, FALSE);
+}
+
+void near_dbus_property_append_basic(DBusMessageIter *iter,
+ const char *key, int type, void *val)
+{
+ DBusMessageIter value;
+ const char *signature;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &key);
+
+ switch (type) {
+ case DBUS_TYPE_BOOLEAN:
+ signature = DBUS_TYPE_BOOLEAN_AS_STRING;
+ break;
+ case DBUS_TYPE_STRING:
+ signature = DBUS_TYPE_STRING_AS_STRING;
+ break;
+ case DBUS_TYPE_BYTE:
+ signature = DBUS_TYPE_BYTE_AS_STRING;
+ break;
+ case DBUS_TYPE_UINT16:
+ signature = DBUS_TYPE_UINT16_AS_STRING;
+ break;
+ case DBUS_TYPE_INT16:
+ signature = DBUS_TYPE_INT16_AS_STRING;
+ break;
+ case DBUS_TYPE_UINT32:
+ signature = DBUS_TYPE_UINT32_AS_STRING;
+ break;
+ case DBUS_TYPE_INT32:
+ signature = DBUS_TYPE_INT32_AS_STRING;
+ break;
+ case DBUS_TYPE_OBJECT_PATH:
+ signature = DBUS_TYPE_OBJECT_PATH_AS_STRING;
+ break;
+ default:
+ signature = DBUS_TYPE_VARIANT_AS_STRING;
+ break;
+ }
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
+ signature, &value);
+ dbus_message_iter_append_basic(&value, type, val);
+ dbus_message_iter_close_container(iter, &value);
+}
+
+void near_dbus_property_append_dict(DBusMessageIter *iter, const char *key,
+ near_dbus_append_cb_t function, void *user_data)
+{
+ DBusMessageIter value, dict;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &key);
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
+ DBUS_TYPE_ARRAY_AS_STRING
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &value);
+
+ near_dbus_dict_open(&value, &dict);
+ if (function)
+ function(&dict, user_data);
+ near_dbus_dict_close(&value, &dict);
+
+ dbus_message_iter_close_container(iter, &value);
+}
+
+void near_dbus_property_append_fixed_array(DBusMessageIter *iter,
+ const char *key, int type, void *val, int len)
+{
+ DBusMessageIter value, array;
+ const char *variant_sig, *array_sig;
+
+ switch (type) {
+ case DBUS_TYPE_BYTE:
+ variant_sig = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING;
+ array_sig = DBUS_TYPE_BYTE_AS_STRING;
+ break;
+ default:
+ return;
+ }
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &key);
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
+ variant_sig, &value);
+
+ dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
+ array_sig, &array);
+ dbus_message_iter_append_fixed_array(&array, type, val, len);
+ dbus_message_iter_close_container(&value, &array);
+
+ dbus_message_iter_close_container(iter, &value);
+}
+
+void near_dbus_property_append_array(DBusMessageIter *iter,
+ const char *key, int type,
+ near_dbus_append_cb_t function, void *user_data)
+{
+ DBusMessageIter value, array;
+ const char *variant_sig, *array_sig;
+
+ switch (type) {
+ case DBUS_TYPE_STRING:
+ variant_sig = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING;
+ array_sig = DBUS_TYPE_STRING_AS_STRING;
+ break;
+ case DBUS_TYPE_OBJECT_PATH:
+ variant_sig = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING;
+ array_sig = DBUS_TYPE_OBJECT_PATH_AS_STRING;
+ break;
+ default:
+ return;
+ }
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &key);
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
+ variant_sig, &value);
+
+ dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
+ array_sig, &array);
+ if (function)
+ function(&array, user_data);
+ dbus_message_iter_close_container(&value, &array);
+
+ dbus_message_iter_close_container(iter, &value);
+}
+
+static DBusConnection *connection = NULL;
+
+dbus_bool_t near_dbus_property_changed_basic(const char *path,
+ const char *interface, const char *key,
+ int type, void *val)
+{
+ DBusMessage *signal;
+ DBusMessageIter iter;
+
+ if (path == NULL)
+ return FALSE;
+
+ signal = dbus_message_new_signal(path, interface, "PropertyChanged");
+ if (signal == NULL)
+ return FALSE;
+
+ dbus_message_iter_init_append(signal, &iter);
+ near_dbus_property_append_basic(&iter, key, type, val);
+
+ g_dbus_send_message(connection, signal);
+
+ return TRUE;
+}
+
+dbus_bool_t near_dbus_property_changed_dict(const char *path,
+ const char *interface, const char *key,
+ near_dbus_append_cb_t function, void *user_data)
+{
+ DBusMessage *signal;
+ DBusMessageIter iter;
+
+ if (path == NULL)
+ return FALSE;
+
+ signal = dbus_message_new_signal(path, interface, "PropertyChanged");
+ if (signal == NULL)
+ return FALSE;
+
+ dbus_message_iter_init_append(signal, &iter);
+ near_dbus_property_append_dict(&iter, key, function, user_data);
+
+ g_dbus_send_message(connection, signal);
+
+ return TRUE;
+}
+
+dbus_bool_t near_dbus_property_changed_array(const char *path,
+ const char *interface, const char *key, int type,
+ near_dbus_append_cb_t function, void *user_data)
+{
+ DBusMessage *signal;
+ DBusMessageIter iter;
+
+ if (path == NULL)
+ return FALSE;
+
+ signal = dbus_message_new_signal(path, interface, "PropertyChanged");
+ if (signal == NULL)
+ return FALSE;
+
+ dbus_message_iter_init_append(signal, &iter);
+ near_dbus_property_append_array(&iter, key, type,
+ function, user_data);
+
+ g_dbus_send_message(connection, signal);
+
+ return TRUE;
+}
+
+DBusConnection *near_dbus_get_connection(void)
+{
+ return connection;
+}
+
+int __near_dbus_init(DBusConnection *conn)
+{
+ DBG("");
+
+ connection = conn;
+
+ return 0;
+}
+
+void __near_dbus_cleanup(void)
+{
+ DBG("");
+
+ connection = NULL;
+}
diff --git a/src/error.c b/src/error.c
new file mode 100644
index 0000000..f166380
--- /dev/null
+++ b/src/error.c
@@ -0,0 +1,185 @@
+/*
+ *
+ * neard - Near Field Communication manager
+ *
+ * Copyright (C) 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 <errno.h>
+#include <string.h>
+
+#include <gdbus.h>
+
+#include "near.h"
+
+DBusMessage *__near_error_failed(DBusMessage *msg, int errnum)
+{
+ const char *str = strerror(errnum);
+
+ switch (errnum) {
+ case ESRCH:
+ return __near_error_not_registered(msg);
+ case ENXIO:
+ return __near_error_not_found(msg);
+ case EACCES:
+ return __near_error_permission_denied(msg);
+ case EEXIST:
+ return __near_error_already_exists(msg);
+ case EINVAL:
+ return __near_error_invalid_arguments(msg);
+ case ENOSYS:
+ return __near_error_not_implemented(msg);
+ case ENOLINK:
+ return __near_error_no_carrier(msg);
+ case ENOTUNIQ:
+ return __near_error_not_unique(msg);
+ case EOPNOTSUPP:
+ return __near_error_not_supported(msg);
+ case ECONNABORTED:
+ return __near_error_operation_aborted(msg);
+ case EISCONN:
+ return __near_error_already_connected(msg);
+ case ENOTCONN:
+ return __near_error_not_connected(msg);
+ case ETIMEDOUT:
+ return __near_error_operation_timeout(msg);
+ case EALREADY:
+ return __near_error_in_progress(msg);
+ case ENOKEY:
+ return __near_error_passphrase_required(msg);
+ }
+
+ return g_dbus_create_error(msg, NFC_ERROR_INTERFACE
+ ".Failed", "%s", str);
+}
+
+DBusMessage *__near_error_invalid_arguments(DBusMessage *msg)
+{
+ return g_dbus_create_error(msg, NFC_ERROR_INTERFACE
+ ".InvalidArguments", "Invalid arguments");
+}
+
+DBusMessage *__near_error_permission_denied(DBusMessage *msg)
+{
+ return g_dbus_create_error(msg, NFC_ERROR_INTERFACE
+ ".PermissionDenied", "Permission denied");
+}
+
+DBusMessage *__near_error_passphrase_required(DBusMessage *msg)
+{
+ return g_dbus_create_error(msg, NFC_ERROR_INTERFACE
+ ".PassphraseRequired", "Passphrase required");
+}
+
+DBusMessage *__near_error_not_registered(DBusMessage *msg)
+{
+ return g_dbus_create_error(msg, NFC_ERROR_INTERFACE
+ ".NotRegistered", "Not registered");
+}
+
+DBusMessage *__near_error_not_unique(DBusMessage *msg)
+{
+ return g_dbus_create_error(msg, NFC_ERROR_INTERFACE
+ ".NotUnique", "Not unique");
+}
+
+DBusMessage *__near_error_not_supported(DBusMessage *msg)
+{
+ return g_dbus_create_error(msg, NFC_ERROR_INTERFACE
+ ".NotSupported", "Not supported");
+}
+
+DBusMessage *__near_error_not_implemented(DBusMessage *msg)
+{
+ return g_dbus_create_error(msg, NFC_ERROR_INTERFACE
+ ".NotImplemented", "Not implemented");
+}
+
+DBusMessage *__near_error_not_found(DBusMessage *msg)
+{
+ return g_dbus_create_error(msg, NFC_ERROR_INTERFACE
+ ".NotFound", "Not found");
+}
+
+DBusMessage *__near_error_no_carrier(DBusMessage *msg)
+{
+ return g_dbus_create_error(msg, NFC_ERROR_INTERFACE
+ ".NoCarrier", "No carrier");
+}
+
+DBusMessage *__near_error_in_progress(DBusMessage *msg)
+{
+ return g_dbus_create_error(msg, NFC_ERROR_INTERFACE
+ ".InProgress", "In progress");
+}
+
+DBusMessage *__near_error_already_exists(DBusMessage *msg)
+{
+ return g_dbus_create_error(msg, NFC_ERROR_INTERFACE
+ ".AlreadyExists", "Already exists");
+}
+
+DBusMessage *__near_error_already_enabled(DBusMessage *msg)
+{
+ return g_dbus_create_error(msg, NFC_ERROR_INTERFACE
+ ".AlreadyEnabled", "Already enabled");
+}
+
+DBusMessage *__near_error_already_disabled(DBusMessage *msg)
+{
+ return g_dbus_create_error(msg, NFC_ERROR_INTERFACE
+ ".AlreadyDisabled", "Already disabled");
+}
+
+DBusMessage *__near_error_already_connected(DBusMessage *msg)
+{
+ return g_dbus_create_error(msg, NFC_ERROR_INTERFACE
+ ".AlreadyConnected", "Already connected");
+}
+
+DBusMessage *__near_error_not_connected(DBusMessage *msg)
+{
+ return g_dbus_create_error(msg, NFC_ERROR_INTERFACE
+ ".NotConnected", "Not connected");
+}
+DBusMessage *__near_error_operation_aborted(DBusMessage *msg)
+{
+ return g_dbus_create_error(msg, NFC_ERROR_INTERFACE
+ ".OperationAborted", "Operation aborted");
+}
+
+DBusMessage *__near_error_operation_timeout(DBusMessage *msg)
+{
+ return g_dbus_create_error(msg, NFC_ERROR_INTERFACE
+ ".OperationTimeout", "Operation timeout");
+}
+
+DBusMessage *__near_error_invalid_service(DBusMessage *msg)
+{
+ return g_dbus_create_error(msg, NFC_ERROR_INTERFACE
+ ".InvalidService", "Invalid service");
+}
+
+DBusMessage *__near_error_invalid_property(DBusMessage *msg)
+{
+ return g_dbus_create_error(msg, NFC_ERROR_INTERFACE
+ ".InvalidProperty", "Invalid property");
+}
diff --git a/src/genbuiltin b/src/genbuiltin
new file mode 100755
index 0000000..9c2ba15
--- /dev/null
+++ b/src/genbuiltin
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+for i in $*
+do
+ echo "extern struct near_plugin_desc __near_builtin_$i;"
+done
+
+echo
+echo "static struct near_plugin_desc *__near_builtin[] = {"
+
+for i in $*
+do
+ echo " &__near_builtin_$i,"
+done
+
+echo " NULL"
+echo "};"
diff --git a/src/log.c b/src/log.c
new file mode 100644
index 0000000..99fb984
--- /dev/null
+++ b/src/log.c
@@ -0,0 +1,138 @@
+/*
+ *
+ * neard - Near Field Communication manager
+ *
+ * Copyright (C) 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 <stdarg.h>
+#include <syslog.h>
+
+#include "near.h"
+
+void near_info(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+
+ vsyslog(LOG_INFO, format, ap);
+
+ va_end(ap);
+}
+
+void near_warn(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+
+ vsyslog(LOG_WARNING, format, ap);
+
+ va_end(ap);
+}
+
+void near_error(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+
+ vsyslog(LOG_ERR, format, ap);
+
+ va_end(ap);
+}
+
+void near_debug(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+
+ vsyslog(LOG_DEBUG, format, ap);
+
+ va_end(ap);
+}
+
+extern struct near_debug_desc __start___debug[];
+extern struct near_debug_desc __stop___debug[];
+
+static gchar **enabled = NULL;
+
+static gboolean is_enabled(struct near_debug_desc *desc)
+{
+ int i;
+
+ if (enabled == NULL)
+ return FALSE;
+
+ for (i = 0; enabled[i] != NULL; i++) {
+ if (desc->name != NULL && g_pattern_match_simple(enabled[i],
+ desc->name) == TRUE)
+ return TRUE;
+ if (desc->file != NULL && g_pattern_match_simple(enabled[i],
+ desc->file) == TRUE)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+int __near_log_init(const char *debug, gboolean detach)
+{
+ int option = LOG_NDELAY | LOG_PID;
+ struct near_debug_desc *desc;
+ const char *name = NULL, *file = NULL;
+
+ if (debug != NULL)
+ enabled = g_strsplit_set(debug, ":, ", 0);
+
+ for (desc = __start___debug; desc < __stop___debug; desc++) {
+ if (file != NULL || name != NULL) {
+ if (g_strcmp0(desc->file, file) == 0) {
+ if (desc->name == NULL)
+ desc->name = name;
+ } else
+ file = NULL;
+ }
+
+ if (is_enabled(desc) == TRUE)
+ desc->flags |= NEAR_DEBUG_FLAG_PRINT;
+ }
+
+ if (detach == FALSE)
+ option |= LOG_PERROR;
+
+ openlog("neard", option, LOG_DAEMON);
+
+ syslog(LOG_INFO, "NEAR daemon version %s", VERSION);
+
+ return 0;
+}
+
+void __near_log_cleanup(void)
+{
+ syslog(LOG_INFO, "Exit");
+
+ closelog();
+
+ g_strfreev(enabled);
+}
diff --git a/src/log.h b/src/log.h
new file mode 100644
index 0000000..6183b88
--- /dev/null
+++ b/src/log.h
@@ -0,0 +1,47 @@
+/*
+ *
+ * neard - Near Field Communication manager
+ *
+ * Copyright (C) 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ *
+ */
+
+void near_info(const char *format, ...)
+ __attribute__((format(printf, 1, 2)));
+void near_warn(const char *format, ...)
+ __attribute__((format(printf, 1, 2)));
+void near_error(const char *format, ...)
+ __attribute__((format(printf, 1, 2)));
+void near_debug(const char *format, ...)
+ __attribute__((format(printf, 1, 2)));
+
+struct near_debug_desc {
+ const char *name;
+ const char *file;
+#define NEAR_DEBUG_FLAG_DEFAULT (0)
+#define NEAR_DEBUG_FLAG_PRINT (1 << 0)
+ unsigned int flags;
+} __attribute__((aligned(8)));
+
+#define DBG(fmt, arg...) do { \
+ static struct near_debug_desc __near_debug_desc \
+ __attribute__((used, section("__debug"), aligned(8))) = { \
+ .file = __FILE__, .flags = NEAR_DEBUG_FLAG_DEFAULT, \
+ }; \
+ if (__near_debug_desc.flags & NEAR_DEBUG_FLAG_PRINT) \
+ near_debug("%s:%s() " fmt, \
+ __FILE__, __FUNCTION__ , ## arg); \
+} while (0)
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..63e528e
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,160 @@
+/*
+ *
+ * neard - Near Field Communication manager
+ *
+ * Copyright (C) 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+
+#include <gdbus.h>
+
+#include "near.h"
+
+static GMainLoop *main_loop = NULL;
+
+static volatile sig_atomic_t __terminated = 0;
+
+static void sig_term(int sig)
+{
+ if (__terminated > 0)
+ return;
+
+ __terminated = 1;
+
+ near_info("Terminating");
+
+ g_main_loop_quit(main_loop);
+}
+
+static void disconnect_callback(DBusConnection *conn, void *user_data)
+{
+ near_error("D-Bus disconnect");
+
+ g_main_loop_quit(main_loop);
+}
+
+static gchar *option_debug = NULL;
+static gboolean option_detach = TRUE;
+static gboolean option_version = FALSE;
+
+static gboolean parse_debug(const char *key, const char *value,
+ gpointer user_data, GError **error)
+{
+ if (value)
+ option_debug = g_strdup(value);
+ else
+ option_debug = g_strdup("*");
+
+ return TRUE;
+}
+
+static GOptionEntry options[] = {
+ { "debug", 'd', G_OPTION_FLAG_OPTIONAL_ARG,
+ G_OPTION_ARG_CALLBACK, parse_debug,
+ "Specify debug options to enable", "DEBUG" },
+ { "nodaemon", 'n', G_OPTION_FLAG_REVERSE,
+ G_OPTION_ARG_NONE, &option_detach,
+ "Don't fork daemon to background" },
+ { "version", 'v', 0, G_OPTION_ARG_NONE, &option_version,
+ "Show version information and exit" },
+ { NULL },
+};
+
+int main(int argc, char *argv[])
+{
+ GOptionContext *context;
+ GError *error = NULL;
+ DBusConnection *conn;
+ DBusError err;
+ struct sigaction sa;
+
+ context = g_option_context_new(NULL);
+ g_option_context_add_main_entries(context, options, NULL);
+
+ if (g_option_context_parse(context, &argc, &argv, &error) == FALSE) {
+ if (error != NULL) {
+ g_printerr("%s\n", error->message);
+ g_error_free(error);
+ } else
+ g_printerr("An unknown error occurred\n");
+ exit(1);
+ }
+
+ g_option_context_free(context);
+
+ if (option_version == TRUE) {
+ printf("%s\n", VERSION);
+ exit(0);
+ }
+
+ if (option_detach == TRUE) {
+ if (daemon(0, 0)) {
+ perror("Can't start daemon");
+ exit(1);
+ }
+ }
+
+ main_loop = g_main_loop_new(NULL, FALSE);
+
+ dbus_error_init(&err);
+
+ conn = g_dbus_setup_bus(DBUS_BUS_SESSION, NFC_SERVICE, &err);
+ if (conn == NULL) {
+ if (dbus_error_is_set(&err) == TRUE) {
+ fprintf(stderr, "%s\n", err.message);
+ dbus_error_free(&err);
+ } else
+ fprintf(stderr, "Can't register with session bus\n");
+ exit(1);
+ }
+
+ g_dbus_set_disconnect_function(conn, disconnect_callback, NULL, NULL);
+
+ __near_log_init(option_debug, option_detach);
+ __near_dbus_init(conn);
+
+ __near_manager_init(conn);
+ __near_adapter_init();
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = sig_term;
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
+
+ g_main_loop_run(main_loop);
+
+ __near_adapter_cleanup();
+ __near_manager_cleanup();
+
+ __near_dbus_cleanup();
+ __near_log_cleanup();
+
+ dbus_connection_unref(conn);
+
+ g_main_loop_unref(main_loop);
+
+ return 0;
+}
diff --git a/src/manager.c b/src/manager.c
new file mode 100644
index 0000000..e071979
--- /dev/null
+++ b/src/manager.c
@@ -0,0 +1,101 @@
+/*
+ *
+ * neard - Near Field Communication manager
+ *
+ * Copyright (C) 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 <glib.h>
+
+#include <gdbus.h>
+
+#include "near.h"
+
+static DBusMessage *get_properties(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ DBusMessage *reply;
+ DBusMessageIter array, dict;
+
+ DBG("conn %p", conn);
+
+ reply = dbus_message_new_method_return(msg);
+ if (reply == NULL)
+ return NULL;
+
+ dbus_message_iter_init_append(reply, &array);
+
+ near_dbus_dict_open(&array, &dict);
+
+ near_dbus_dict_append_array(&dict, "Adapters",
+ DBUS_TYPE_OBJECT_PATH, __near_adapter_list, NULL);
+
+ near_dbus_dict_close(&array, &dict);
+
+ return reply;
+}
+
+static DBusMessage *set_property(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ DBG("conn %p", conn);
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+static GDBusMethodTable manager_methods[] = {
+ { "GetProperties", "", "a{sv}", get_properties },
+ { "SetProperty", "sv", "", set_property },
+ { },
+};
+
+static GDBusSignalTable manager_signals[] = {
+ { "PropertyChanged", "sv" },
+ { "AdapterAdded", "o" },
+ { "AdapterRemoved", "o" },
+ { }
+};
+
+static DBusConnection *connection;
+
+int __near_manager_init(DBusConnection *conn)
+{
+ DBG("");
+
+ connection = dbus_connection_ref(conn);
+
+ g_dbus_register_interface(connection, NFC_MANAGER_PATH,
+ NFC_MANAGER_INTERFACE,
+ manager_methods,
+ manager_signals, NULL, NULL, NULL);
+
+ return 0;
+}
+
+void __near_manager_cleanup(void)
+{
+ DBG("");
+
+ g_dbus_unregister_interface(connection, NFC_MANAGER_PATH,
+ NFC_MANAGER_INTERFACE);
+
+ dbus_connection_unref(connection);
+}
diff --git a/src/near.h b/src/near.h
new file mode 100644
index 0000000..25f14c6
--- /dev/null
+++ b/src/near.h
@@ -0,0 +1,60 @@
+/*
+ *
+ * Near Field Communication
+ *
+ * Copyright (C) 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ *
+ */
+
+#include <glib.h>
+
+#include "log.h"
+
+int __near_log_init(const char *debug, gboolean detach);
+void __near_log_cleanup(void);
+
+#include <near/dbus.h>
+
+int __near_dbus_init(DBusConnection *conn);
+void __near_dbus_cleanup(void);
+
+DBusMessage *__near_error_failed(DBusMessage *msg, int errnum);
+DBusMessage *__near_error_invalid_arguments(DBusMessage *msg);
+DBusMessage *__near_error_permission_denied(DBusMessage *msg);
+DBusMessage *__near_error_passphrase_required(DBusMessage *msg);
+DBusMessage *__near_error_not_registered(DBusMessage *msg);
+DBusMessage *__near_error_not_unique(DBusMessage *msg);
+DBusMessage *__near_error_not_supported(DBusMessage *msg);
+DBusMessage *__near_error_not_implemented(DBusMessage *msg);
+DBusMessage *__near_error_not_found(DBusMessage *msg);
+DBusMessage *__near_error_no_carrier(DBusMessage *msg);
+DBusMessage *__near_error_in_progress(DBusMessage *msg);
+DBusMessage *__near_error_already_exists(DBusMessage *msg);
+DBusMessage *__near_error_already_enabled(DBusMessage *msg);
+DBusMessage *__near_error_already_disabled(DBusMessage *msg);
+DBusMessage *__near_error_already_connected(DBusMessage *msg);
+DBusMessage *__near_error_not_connected(DBusMessage *msg);
+DBusMessage *__near_error_operation_aborted(DBusMessage *msg);
+DBusMessage *__near_error_operation_timeout(DBusMessage *msg);
+DBusMessage *__near_error_invalid_service(DBusMessage *msg);
+DBusMessage *__near_error_invalid_property(DBusMessage *msg);
+
+int __near_manager_init(DBusConnection *conn);
+void __near_manager_cleanup(void);
+
+int __near_adapter_init(void);
+void __near_adapter_cleanup(void);
+void __near_adapter_list(DBusMessageIter *iter, void *user_data);
diff --git a/src/types.h b/src/types.h
new file mode 100644
index 0000000..ef7fdec
--- /dev/null
+++ b/src/types.h
@@ -0,0 +1,31 @@
+/*
+ *
+ * neard - Near Field Communication manager
+ *
+ * Copyright (C) 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 FALSE
+#define FALSE (0)
+#endif
+
+#ifndef TRUE
+#define TRUE (!FALSE)
+#endif
+
+typedef int near_bool_t;
+