diff options
| author | Sjoerd Simons <sjoerd@luon.net> | 2013-10-25 21:20:58 +0200 |
|---|---|---|
| committer | Sjoerd Simons <sjoerd@luon.net> | 2013-10-25 21:20:58 +0200 |
| commit | a4256940da049f91bbbea5e53e469a59ea9c10f7 (patch) | |
| tree | 2211c102aea3a33f34f960f48c8b8a55daccd97b /src/bluez-manager | |
| parent | 8d275584fc94f398f0a7c990dcd057533d9a5856 (diff) | |
Imported Upstream version 0.9.8.8 upstream/0.9.8.8
Diffstat (limited to 'src/bluez-manager')
| -rw-r--r-- | src/bluez-manager/Makefile.am | 17 | ||||
| -rw-r--r-- | src/bluez-manager/Makefile.in | 279 | ||||
| -rw-r--r-- | src/bluez-manager/nm-bluez-common.h | 17 | ||||
| -rw-r--r-- | src/bluez-manager/nm-bluez-device.c | 728 | ||||
| -rw-r--r-- | src/bluez-manager/nm-bluez-device.h | 19 | ||||
| -rw-r--r-- | src/bluez-manager/nm-bluez-manager.c | 330 | ||||
| -rw-r--r-- | src/bluez-manager/nm-bluez-manager.h | 1 | ||||
| -rw-r--r-- | src/bluez-manager/nm-bluez4-adapter.c (renamed from src/bluez-manager/nm-bluez-adapter.c) | 2 | ||||
| -rw-r--r-- | src/bluez-manager/nm-bluez4-adapter.h (renamed from src/bluez-manager/nm-bluez-adapter.h) | 0 | ||||
| -rw-r--r-- | src/bluez-manager/nm-bluez4-manager.c | 386 |
10 files changed, 1483 insertions, 296 deletions
diff --git a/src/bluez-manager/Makefile.am b/src/bluez-manager/Makefile.am index 7e7ed9a0..aee27217 100644 --- a/src/bluez-manager/Makefile.am +++ b/src/bluez-manager/Makefile.am @@ -12,13 +12,20 @@ INCLUDES = \ noinst_LTLIBRARIES = libbluez-manager.la libbluez_manager_la_SOURCES = \ - nm-bluez-manager.c \ - nm-bluez-manager.h \ - nm-bluez-adapter.c \ - nm-bluez-adapter.h \ + nm-bluez-common.h \ nm-bluez-device.c \ nm-bluez-device.h \ - nm-bluez-common.h + nm-bluez-manager.h + +if WITH_BLUEZ4 +libbluez_manager_la_SOURCES += \ + nm-bluez4-adapter.h \ + nm-bluez4-adapter.c \ + nm-bluez4-manager.c +else +libbluez_manager_la_SOURCES += \ + nm-bluez-manager.c +endif libbluez_manager_la_CPPFLAGS = \ $(DBUS_CFLAGS) \ diff --git a/src/bluez-manager/Makefile.in b/src/bluez-manager/Makefile.in index 5606d11c..f4dd166f 100644 --- a/src/bluez-manager/Makefile.in +++ b/src/bluez-manager/Makefile.in @@ -1,9 +1,8 @@ -# Makefile.in generated by automake 1.11.6 from Makefile.am. +# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software -# Foundation, Inc. +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -16,23 +15,51 @@ @SET_MAKE@ VPATH = @srcdir@ -am__make_dryrun = \ - { \ - am__dry=no; \ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ - echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ - | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ - *) \ - for am__flg in $$MAKEFLAGS; do \ - case $$am__flg in \ - *=*|--*) ;; \ - *n*) am__dry=yes; break;; \ - esac; \ - done;; \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ esac; \ - test $$am__dry = yes; \ - } + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -51,8 +78,17 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ +@WITH_BLUEZ4_TRUE@am__append_1 = \ +@WITH_BLUEZ4_TRUE@ nm-bluez4-adapter.h \ +@WITH_BLUEZ4_TRUE@ nm-bluez4-adapter.c \ +@WITH_BLUEZ4_TRUE@ nm-bluez4-manager.c + +@WITH_BLUEZ4_FALSE@am__append_2 = \ +@WITH_BLUEZ4_FALSE@ nm-bluez-manager.c + subdir = src/bluez-manager -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/build-aux/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/gettext.m4 \ @@ -78,14 +114,35 @@ libbluez_manager_la_DEPENDENCIES = \ $(top_builddir)/src/generated/libnm-generated.la \ $(top_builddir)/src/logging/libnm-logging.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +am__libbluez_manager_la_SOURCES_DIST = nm-bluez-common.h \ + nm-bluez-device.c nm-bluez-device.h nm-bluez-manager.h \ + nm-bluez4-adapter.h nm-bluez4-adapter.c nm-bluez4-manager.c \ + nm-bluez-manager.c +@WITH_BLUEZ4_TRUE@am__objects_1 = \ +@WITH_BLUEZ4_TRUE@ libbluez_manager_la-nm-bluez4-adapter.lo \ +@WITH_BLUEZ4_TRUE@ libbluez_manager_la-nm-bluez4-manager.lo +@WITH_BLUEZ4_FALSE@am__objects_2 = \ +@WITH_BLUEZ4_FALSE@ libbluez_manager_la-nm-bluez-manager.lo am_libbluez_manager_la_OBJECTS = \ - libbluez_manager_la-nm-bluez-manager.lo \ - libbluez_manager_la-nm-bluez-adapter.lo \ - libbluez_manager_la-nm-bluez-device.lo + libbluez_manager_la-nm-bluez-device.lo $(am__objects_1) \ + $(am__objects_2) libbluez_manager_la_OBJECTS = $(am_libbluez_manager_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__depfiles_maybe = depfiles @@ -98,27 +155,40 @@ LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = SOURCES = $(libbluez_manager_la_SOURCES) -DIST_SOURCES = $(libbluez_manager_la_SOURCES) +DIST_SOURCES = $(am__libbluez_manager_la_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -263,7 +333,6 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -PKGCONFIG_PATH = @PKGCONFIG_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ @@ -278,6 +347,8 @@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ +SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ +SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ @@ -371,15 +442,9 @@ INCLUDES = \ -I${top_srcdir}/src/logging noinst_LTLIBRARIES = libbluez-manager.la -libbluez_manager_la_SOURCES = \ - nm-bluez-manager.c \ - nm-bluez-manager.h \ - nm-bluez-adapter.c \ - nm-bluez-adapter.h \ - nm-bluez-device.c \ - nm-bluez-device.h \ - nm-bluez-common.h - +libbluez_manager_la_SOURCES = nm-bluez-common.h nm-bluez-device.c \ + nm-bluez-device.h nm-bluez-manager.h $(am__append_1) \ + $(am__append_2) libbluez_manager_la_CPPFLAGS = \ $(DBUS_CFLAGS) \ $(GLIB_CFLAGS) \ @@ -434,12 +499,15 @@ $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) - @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ - dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ - test "$$dir" != "$$p" || dir=.; \ - echo "rm -f \"$${dir}/so_locations\""; \ - rm -f "$${dir}/so_locations"; \ - done + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + libbluez-manager.la: $(libbluez_manager_la_OBJECTS) $(libbluez_manager_la_DEPENDENCIES) $(EXTRA_libbluez_manager_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libbluez_manager_la_OBJECTS) $(libbluez_manager_la_LIBADD) $(LIBS) @@ -449,9 +517,10 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libbluez_manager_la-nm-bluez-adapter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libbluez_manager_la-nm-bluez-device.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libbluez_manager_la-nm-bluez-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libbluez_manager_la-nm-bluez4-adapter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libbluez_manager_la-nm-bluez4-manager.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @@ -474,20 +543,6 @@ distclean-compile: @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< -libbluez_manager_la-nm-bluez-manager.lo: nm-bluez-manager.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbluez_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libbluez_manager_la-nm-bluez-manager.lo -MD -MP -MF $(DEPDIR)/libbluez_manager_la-nm-bluez-manager.Tpo -c -o libbluez_manager_la-nm-bluez-manager.lo `test -f 'nm-bluez-manager.c' || echo '$(srcdir)/'`nm-bluez-manager.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libbluez_manager_la-nm-bluez-manager.Tpo $(DEPDIR)/libbluez_manager_la-nm-bluez-manager.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-bluez-manager.c' object='libbluez_manager_la-nm-bluez-manager.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbluez_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libbluez_manager_la-nm-bluez-manager.lo `test -f 'nm-bluez-manager.c' || echo '$(srcdir)/'`nm-bluez-manager.c - -libbluez_manager_la-nm-bluez-adapter.lo: nm-bluez-adapter.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbluez_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libbluez_manager_la-nm-bluez-adapter.lo -MD -MP -MF $(DEPDIR)/libbluez_manager_la-nm-bluez-adapter.Tpo -c -o libbluez_manager_la-nm-bluez-adapter.lo `test -f 'nm-bluez-adapter.c' || echo '$(srcdir)/'`nm-bluez-adapter.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libbluez_manager_la-nm-bluez-adapter.Tpo $(DEPDIR)/libbluez_manager_la-nm-bluez-adapter.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-bluez-adapter.c' object='libbluez_manager_la-nm-bluez-adapter.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbluez_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libbluez_manager_la-nm-bluez-adapter.lo `test -f 'nm-bluez-adapter.c' || echo '$(srcdir)/'`nm-bluez-adapter.c - libbluez_manager_la-nm-bluez-device.lo: nm-bluez-device.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbluez_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libbluez_manager_la-nm-bluez-device.lo -MD -MP -MF $(DEPDIR)/libbluez_manager_la-nm-bluez-device.Tpo -c -o libbluez_manager_la-nm-bluez-device.lo `test -f 'nm-bluez-device.c' || echo '$(srcdir)/'`nm-bluez-device.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libbluez_manager_la-nm-bluez-device.Tpo $(DEPDIR)/libbluez_manager_la-nm-bluez-device.Plo @@ -495,32 +550,42 @@ libbluez_manager_la-nm-bluez-device.lo: nm-bluez-device.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbluez_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libbluez_manager_la-nm-bluez-device.lo `test -f 'nm-bluez-device.c' || echo '$(srcdir)/'`nm-bluez-device.c +libbluez_manager_la-nm-bluez4-adapter.lo: nm-bluez4-adapter.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbluez_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libbluez_manager_la-nm-bluez4-adapter.lo -MD -MP -MF $(DEPDIR)/libbluez_manager_la-nm-bluez4-adapter.Tpo -c -o libbluez_manager_la-nm-bluez4-adapter.lo `test -f 'nm-bluez4-adapter.c' || echo '$(srcdir)/'`nm-bluez4-adapter.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libbluez_manager_la-nm-bluez4-adapter.Tpo $(DEPDIR)/libbluez_manager_la-nm-bluez4-adapter.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-bluez4-adapter.c' object='libbluez_manager_la-nm-bluez4-adapter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbluez_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libbluez_manager_la-nm-bluez4-adapter.lo `test -f 'nm-bluez4-adapter.c' || echo '$(srcdir)/'`nm-bluez4-adapter.c + +libbluez_manager_la-nm-bluez4-manager.lo: nm-bluez4-manager.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbluez_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libbluez_manager_la-nm-bluez4-manager.lo -MD -MP -MF $(DEPDIR)/libbluez_manager_la-nm-bluez4-manager.Tpo -c -o libbluez_manager_la-nm-bluez4-manager.lo `test -f 'nm-bluez4-manager.c' || echo '$(srcdir)/'`nm-bluez4-manager.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libbluez_manager_la-nm-bluez4-manager.Tpo $(DEPDIR)/libbluez_manager_la-nm-bluez4-manager.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-bluez4-manager.c' object='libbluez_manager_la-nm-bluez4-manager.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbluez_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libbluez_manager_la-nm-bluez4-manager.lo `test -f 'nm-bluez4-manager.c' || echo '$(srcdir)/'`nm-bluez4-manager.c + +libbluez_manager_la-nm-bluez-manager.lo: nm-bluez-manager.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbluez_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libbluez_manager_la-nm-bluez-manager.lo -MD -MP -MF $(DEPDIR)/libbluez_manager_la-nm-bluez-manager.Tpo -c -o libbluez_manager_la-nm-bluez-manager.lo `test -f 'nm-bluez-manager.c' || echo '$(srcdir)/'`nm-bluez-manager.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libbluez_manager_la-nm-bluez-manager.Tpo $(DEPDIR)/libbluez_manager_la-nm-bluez-manager.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-bluez-manager.c' object='libbluez_manager_la-nm-bluez-manager.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbluez_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libbluez_manager_la-nm-bluez-manager.lo `test -f 'nm-bluez-manager.c' || echo '$(srcdir)/'`nm-bluez-manager.c + mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ + $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ @@ -532,15 +597,11 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $$unique; \ fi; \ fi -ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique @@ -549,6 +610,21 @@ GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags @@ -690,18 +766,19 @@ uninstall-am: .MAKE: install-am install-strip -.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ - clean-libtool clean-noinstLTLIBRARIES ctags distclean \ - distclean-compile distclean-generic distclean-libtool \ - distclean-tags distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-strip installcheck installcheck-am installdirs \ - maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ - pdf pdf-am ps ps-am tags uninstall uninstall-am +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/src/bluez-manager/nm-bluez-common.h b/src/bluez-manager/nm-bluez-common.h index 61296255..ecc4d709 100644 --- a/src/bluez-manager/nm-bluez-common.h +++ b/src/bluez-manager/nm-bluez-common.h @@ -21,14 +21,31 @@ #ifndef NM_BLUEZ_COMMON_H #define NM_BLUEZ_COMMON_H +#include <config.h> + +#define BLUETOOTH_CONNECT_DUN "dun" +#define BLUETOOTH_CONNECT_NAP "nap" + #define BLUEZ_SERVICE "org.bluez" #define BLUEZ_MANAGER_PATH "/" +#define OBJECT_MANAGER_INTERFACE "org.freedesktop.DBus.ObjectManager" + +#if ! WITH_BLUEZ4 + +#define BLUEZ_ADAPTER_INTERFACE "org.bluez.Adapter1" +#define BLUEZ_DEVICE_INTERFACE "org.bluez.Device1" +#define BLUEZ_NETWORK_INTERFACE "org.bluez.Network1" + +#else + #define BLUEZ_MANAGER_INTERFACE "org.bluez.Manager" #define BLUEZ_ADAPTER_INTERFACE "org.bluez.Adapter" #define BLUEZ_DEVICE_INTERFACE "org.bluez.Device" #define BLUEZ_SERIAL_INTERFACE "org.bluez.Serial" #define BLUEZ_NETWORK_INTERFACE "org.bluez.Network" +#endif /* WITH_BLUEZ */ + #endif /* NM_BLUEZ_COMMON_H */ diff --git a/src/bluez-manager/nm-bluez-device.c b/src/bluez-manager/nm-bluez-device.c index b12a8619..ed5e345d 100644 --- a/src/bluez-manager/nm-bluez-device.c +++ b/src/bluez-manager/nm-bluez-device.c @@ -16,9 +16,12 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Copyright (C) 2009 - 2012 Red Hat, Inc. + * Copyright (C) 2013 Intel Corporation. */ #include <glib.h> +#include <glib/gi18n.h> +#include <gio/gio.h> #include <string.h> #include <net/ethernet.h> #include <netinet/ether.h> @@ -26,12 +29,15 @@ #include "NetworkManager.h" #include "nm-setting-bluetooth.h" -#include "nm-dbus-manager.h" -#include "nm-bluez-device.h" #include "nm-bluez-common.h" +#if WITH_BLUEZ4 +#include "nm-dbus-manager.h" #include "nm-dbus-glib-types.h" +#endif +#include "nm-bluez-device.h" #include "nm-logging.h" #include "nm-marshal.h" +#include "nm-utils.h" G_DEFINE_TYPE (NMBluezDevice, nm_bluez_device, G_TYPE_OBJECT) @@ -40,18 +46,33 @@ G_DEFINE_TYPE (NMBluezDevice, nm_bluez_device, G_TYPE_OBJECT) typedef struct { char *path; - DBusGProxy *proxy; + GDBusConnection *dbus_connection; +#if ! WITH_BLUEZ4 + GDBusProxy *proxy5; + GDBusProxy *adapter; + gboolean adapter_powered; +#else + DBusGProxy *proxy4; +#endif + gboolean initialized; gboolean usable; + NMBluetoothCapabilities connection_bt_type; char *address; guint8 bin_address[ETH_ALEN]; char *name; guint32 capabilities; gint rssi; + gboolean connected; + + char *bt_iface; NMConnectionProvider *provider; GSList *connections; + + NMConnection *pan_connection; + gboolean pan_connection_no_autocreate; } NMBluezDevicePrivate; @@ -63,6 +84,7 @@ enum { PROP_CAPABILITIES, PROP_RSSI, PROP_USABLE, + PROP_CONNECTED, LAST_PROP }; @@ -74,6 +96,12 @@ enum { }; static guint signals[LAST_SIGNAL] = { 0 }; + +static void cp_connection_added (NMConnectionProvider *provider, + NMConnection *connection, NMBluezDevice *self); +static gboolean connection_compatible (NMBluezDevice *self, NMConnection *connection); + + /***********************************************************/ const char * @@ -132,13 +160,147 @@ nm_bluez_device_get_rssi (NMBluezDevice *self) return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->rssi; } +gboolean +nm_bluez_device_get_connected (NMBluezDevice *self) +{ + g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), FALSE); + + return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->connected; +} + +static void +pan_connection_check_create (NMBluezDevice *self) +{ + NMConnection *connection; + NMConnection *added; + NMSetting *setting; + char *uuid, *id; + GByteArray *bdaddr_array; + GError *error = NULL; + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + g_return_if_fail (priv->capabilities & NM_BT_CAPABILITY_NAP); + g_return_if_fail (priv->connections == NULL); + g_return_if_fail (priv->name); + + if (priv->pan_connection || priv->pan_connection_no_autocreate) { + /* already have a connection or we don't want to create one, nothing to do. */ + return; + } + + if (!nm_connection_provider_has_connections_loaded (priv->provider)) { + /* do not try to create any connections until the connection provider is ready. */ + return; + } + + /* Only try once to create a connection. If it does not succeed, we do not try again. Also, + * if the connection gets deleted later, do not create another one for this device. */ + priv->pan_connection_no_autocreate = TRUE; + + /* create a new connection */ + + connection = nm_connection_new (); + + /* Setting: Connection */ + uuid = nm_utils_uuid_generate (); + id = g_strdup_printf (_("%s Network"), priv->name); + setting = nm_setting_connection_new (); + g_object_set (setting, + NM_SETTING_CONNECTION_ID, id, + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, FALSE, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_BLUETOOTH_SETTING_NAME, + NULL); + nm_connection_add_setting (connection, setting); + + /* Setting: Bluetooth */ + bdaddr_array = g_byte_array_sized_new (sizeof (priv->bin_address)); + g_byte_array_append (bdaddr_array, priv->bin_address, sizeof (priv->bin_address)); + setting = nm_setting_bluetooth_new (); + g_object_set (G_OBJECT (setting), + NM_SETTING_BLUETOOTH_BDADDR, bdaddr_array, + NM_SETTING_BLUETOOTH_TYPE, NM_SETTING_BLUETOOTH_TYPE_PANU, + NULL); + nm_connection_add_setting (connection, setting); + g_byte_array_free (bdaddr_array, TRUE); + + /* Setting: IPv4 */ + setting = nm_setting_ip4_config_new (); + g_object_set (G_OBJECT (setting), + NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, + NM_SETTING_IP4_CONFIG_MAY_FAIL, FALSE, + NULL); + nm_connection_add_setting (connection, setting); + + /* Setting: IPv6 */ + setting = nm_setting_ip6_config_new (); + g_object_set (G_OBJECT (setting), + NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, + NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE, + NULL); + nm_connection_add_setting (connection, setting); + + /* Adding a new connection raises a signal which eventually calls check_emit_usable (again) + * which then already finds the suitable connection in priv->connections. This is confusing, + * so block the signal. check_emit_usable will succeed after this function call returns. */ + g_signal_handlers_block_by_func (priv->provider, cp_connection_added, self); + added = nm_connection_provider_add_connection (priv->provider, connection, &error); + g_signal_handlers_unblock_by_func (priv->provider, cp_connection_added, self); + + if (added) { + g_assert (!g_slist_find (priv->connections, added)); + g_assert (connection_compatible (self, added)); + + priv->connections = g_slist_prepend (priv->connections, g_object_ref (added)); + priv->pan_connection = added; + nm_log_dbg (LOGD_SETTINGS, "added new Bluetooth connection for NAP device '%s': '%s' (%s)", priv->path, id, uuid); + } else { + nm_log_warn (LOGD_SETTINGS, "couldn't add new Bluetooth connection for NAP device '%s': '%s' (%s): %d / %s", + priv->path, id, uuid, error ? error->code : -1, + (error && error->message) ? error->message : "(unknown)"); + g_clear_error (&error); + } + + g_object_unref (connection); + g_free (id); + g_free (uuid); +} + static void check_emit_usable (NMBluezDevice *self) { NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); gboolean new_usable; - new_usable = (priv->initialized && priv->capabilities && priv->name && priv->address && priv->connections); + /* only expect the supported capabilities set. */ + g_assert ((priv->capabilities & ~( NM_BT_CAPABILITY_NAP +#if WITH_BLUEZ4 + | NM_BT_CAPABILITY_DUN +#endif + )) == NM_BT_CAPABILITY_NONE); + + new_usable = (priv->initialized && priv->capabilities && priv->name && +#if ! WITH_BLUEZ4 + priv->adapter && priv->adapter_powered && +#endif + priv->dbus_connection && priv->address); + + if (!new_usable) + goto END; + + if (priv->connections) + goto END; + + if (!(priv->capabilities & NM_BT_CAPABILITY_NAP)) { + /* non NAP devices are only usable, if they already have a connection. */ + new_usable = FALSE; + goto END; + } + + pan_connection_check_create (self); + new_usable = !!priv->pan_connection; + +END: if (new_usable != priv->usable) { priv->usable = new_usable; g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_USABLE); @@ -162,6 +324,10 @@ connection_compatible (NMBluezDevice *self, NMConnection *connection) if (!s_bt) return FALSE; + if (!priv->address) { + /* unless address is set, bin_address is not initialized. */ + return FALSE; + } bdaddr = nm_setting_bluetooth_get_bdaddr (s_bt); if (!bdaddr || bdaddr->len != ETH_ALEN) return FALSE; @@ -171,11 +337,11 @@ connection_compatible (NMBluezDevice *self, NMConnection *connection) bt_type = nm_setting_bluetooth_get_connection_type (s_bt); if ( g_str_equal (bt_type, NM_SETTING_BLUETOOTH_TYPE_DUN) && !(priv->capabilities & NM_BT_CAPABILITY_DUN)) - return FALSE; + return FALSE; if ( g_str_equal (bt_type, NM_SETTING_BLUETOOTH_TYPE_PANU) && !(priv->capabilities & NM_BT_CAPABILITY_NAP)) - return FALSE; + return FALSE; return TRUE; } @@ -209,6 +375,9 @@ cp_connection_removed (NMConnectionProvider *provider, if (g_slist_find (priv->connections, connection)) { priv->connections = g_slist_remove (priv->connections, connection); + if (priv->pan_connection == connection) { + priv->pan_connection = NULL; + } g_object_unref (connection); check_emit_usable (self); } @@ -237,6 +406,165 @@ cp_connections_loaded (NMConnectionProvider *provider, NMBluezDevice *self) /***********************************************************/ +static void +bluez_disconnect_cb (GDBusConnection *dbus_connection, + GAsyncResult *res, + gpointer user_data) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (user_data); + GError *error = NULL; + GVariant *variant; + + variant = g_dbus_connection_call_finish (dbus_connection, res, &error); + if (!variant) { + nm_log_warn (LOGD_BT, "%s: failed to disconnect: %s", priv->address, error->message); + g_error_free (error); + } else + g_variant_unref (variant); +} + +void +nm_bluez_device_disconnect (NMBluezDevice *self) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GVariant *args = NULL; + const char *dbus_iface = BLUEZ_NETWORK_INTERFACE; + + g_return_if_fail (priv->dbus_connection); + +#if ! WITH_BLUEZ4 + g_return_if_fail (priv->connection_bt_type == NM_BT_CAPABILITY_NAP); +#else + g_return_if_fail (priv->connection_bt_type == NM_BT_CAPABILITY_NAP || priv->connection_bt_type == NM_BT_CAPABILITY_DUN); + + if (priv->connection_bt_type == NM_BT_CAPABILITY_DUN) { + /* Can't pass a NULL interface name through dbus to bluez, so just + * ignore the disconnect if the interface isn't known. + */ + if (!priv->bt_iface) + return; + + args = g_variant_new ("(s)", priv->bt_iface), + dbus_iface = BLUEZ_SERIAL_INTERFACE; + } +#endif + + g_dbus_connection_call (priv->dbus_connection, + BLUEZ_SERVICE, + priv->path, + dbus_iface, + "Disconnect", + args ? args : g_variant_new ("()"), + NULL, + G_DBUS_CALL_FLAGS_NONE, + 10000, + NULL, + (GAsyncReadyCallback) bluez_disconnect_cb, + self); + + priv->connection_bt_type = NM_BT_CAPABILITY_NONE; +} + +static void +bluez_connect_cb (GDBusConnection *dbus_connection, + GAsyncResult *res, + gpointer user_data) +{ + GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data); + GObject *result_object = g_async_result_get_source_object (G_ASYNC_RESULT (result)); + NMBluezDevice *self = NM_BLUEZ_DEVICE (result_object); + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GError *error = NULL; + char *device; + GVariant *variant; + + variant = g_dbus_connection_call_finish (dbus_connection, res, &error); + + if (!variant) { + g_simple_async_result_take_error (result, error); + } else { + g_variant_get (variant, "(s)", &device); + + g_simple_async_result_set_op_res_gpointer (result, + g_strdup (device), + g_free); + priv->bt_iface = device; + g_variant_unref (variant); + } + + g_simple_async_result_complete (result); + g_object_unref (result); + g_object_unref (result_object); +} + +void +nm_bluez_device_connect_async (NMBluezDevice *self, + NMBluetoothCapabilities connection_bt_type, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + const char *dbus_iface = BLUEZ_NETWORK_INTERFACE; + const char *connect_type = BLUETOOTH_CONNECT_NAP; + + g_return_if_fail (priv->capabilities & connection_bt_type & (NM_BT_CAPABILITY_DUN | NM_BT_CAPABILITY_NAP)); +#if ! WITH_BLUEZ4 + g_return_if_fail (connection_bt_type == NM_BT_CAPABILITY_NAP); +#else + g_return_if_fail (connection_bt_type == NM_BT_CAPABILITY_NAP || connection_bt_type == NM_BT_CAPABILITY_DUN); + + if (connection_bt_type == NM_BT_CAPABILITY_DUN) { + dbus_iface = BLUEZ_SERIAL_INTERFACE; + connect_type = BLUETOOTH_CONNECT_DUN; + } +#endif + + simple = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + nm_bluez_device_connect_async); + + g_dbus_connection_call (priv->dbus_connection, + BLUEZ_SERVICE, + priv->path, + dbus_iface, + "Connect", + g_variant_new ("(s)", connect_type), + NULL, + G_DBUS_CALL_FLAGS_NONE, + 20000, + NULL, + (GAsyncReadyCallback) bluez_connect_cb, + simple); + + priv->connection_bt_type = connection_bt_type; +} + +const char * +nm_bluez_device_connect_finish (NMBluezDevice *self, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + const char *device; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, + G_OBJECT (self), + nm_bluez_device_connect_async), + NULL); + + simple = (GSimpleAsyncResult *) result; + + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + + device = (const char *) g_simple_async_result_get_op_res_gpointer (simple); + return device; +} + +/***********************************************************/ + static guint32 convert_uuids_to_capabilities (const char **strings) { @@ -249,9 +577,11 @@ convert_uuids_to_capabilities (const char **strings) parts = g_strsplit (*iter, "-", -1); if (parts && parts[0]) { switch (g_ascii_strtoull (parts[0], NULL, 16)) { +#if WITH_BLUEZ4 case 0x1103: capabilities |= NM_BT_CAPABILITY_DUN; break; +#endif case 0x1116: capabilities |= NM_BT_CAPABILITY_NAP; break; @@ -266,7 +596,175 @@ convert_uuids_to_capabilities (const char **strings) } static void -property_changed (DBusGProxy *proxy, +_set_property_capabilities (NMBluezDevice *self, const char **uuids, gboolean notify) +{ + guint32 uint_val; + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + uint_val = convert_uuids_to_capabilities (uuids); + if (priv->capabilities != uint_val) { + if (priv->capabilities) { + /* changing (relevant) capabilities is not supported and ignored -- except setting initially */ + nm_log_warn (LOGD_BT, "ignore change of capabilities for Bluetooth device %s from %u to %u", + priv->path, priv->capabilities, uint_val); + return; + } + nm_log_dbg (LOGD_BT, "set capabilities for Bluetooth device %s: %s%s%s", priv->path, + uint_val & NM_BT_CAPABILITY_NAP ? "NAP" : "", + ((uint_val & NM_BT_CAPABILITY_DUN) && (uint_val &NM_BT_CAPABILITY_NAP)) ? " | " : "", + uint_val & NM_BT_CAPABILITY_DUN ? "DUN" : ""); + priv->capabilities = uint_val; + if (notify) + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CAPABILITIES); + } +} + +/** + * priv->address can only be set one to a certain (non NULL) value. Every later attempt + * to reset it to another value will be ignored and a warning will be logged. + * + * When setting the address for the first time, we also set bin_address. + **/ +static void +_set_property_address (NMBluezDevice *self, const char *addr) +{ + struct ether_addr *tmp; + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + if (g_strcmp0 (priv->address, addr) == 0) + return; + + if (!addr) { + nm_log_warn (LOGD_BT, "[%s] cannot reset address from '%s' to NULL", priv->path, priv->address); + return; + } + + if (priv->address != NULL) { + nm_log_warn (LOGD_BT, "[%s] cannot reset address from '%s' to '%s'", priv->path, priv->address, addr); + return; + } + + tmp = ether_aton (addr); + if (!tmp) { + if (priv->address) + nm_log_warn (LOGD_BT, "[%s] cannot reset address from '%s' to '%s' (invalid value)", priv->path, priv->address, addr); + else + nm_log_warn (LOGD_BT, "[%s] cannot reset address from NULL to '%s' (invalid value)", priv->path, addr); + return; + } + memcpy (priv->bin_address, tmp->ether_addr_octet, ETH_ALEN); + priv->address = g_strdup (addr); + return; +} + +#if ! WITH_BLUEZ4 +static void +adapter_properties_changed (GDBusProxy *proxy5, + GVariant *changed_properties, + GStrv invalidated_properties, + gpointer user_data) +{ + NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GVariantIter i; + const char *property; + GVariant *v; + + g_variant_iter_init (&i, changed_properties); + while (g_variant_iter_next (&i, "{&sv}", &property, &v)) { + if (!strcmp (property, "Powered")) { + gboolean powered = g_variant_get_boolean (v); + if (priv->adapter_powered != powered) + priv->adapter_powered = powered; + } + g_variant_unref (v); + } + + check_emit_usable (self); +} + +static void +on_adapter_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GError *error; + GVariant *v; + + priv->adapter = g_dbus_proxy_new_for_bus_finish (res, &error); + if (!priv->adapter) { + nm_log_warn (LOGD_BT, "failed to acquire adapter proxy: %s.", error->message); + g_clear_error (&error); + g_signal_emit (self, signals[INITIALIZED], 0, FALSE); + } else { + g_signal_connect (priv->adapter, "g-properties-changed", + G_CALLBACK (adapter_properties_changed), self); + + /* Check adapter's powered state */ + v = g_dbus_proxy_get_cached_property (priv->adapter, "Powered"); + priv->adapter_powered = v ? g_variant_get_boolean (v) : FALSE; + if (v) + g_variant_unref (v); + + priv->initialized = TRUE; + g_signal_emit (self, signals[INITIALIZED], 0, TRUE); + + check_emit_usable (self); + } + + g_object_unref (self); +} + +static void +properties_changed (GDBusProxy *proxy5, + GVariant *changed_properties, + GStrv invalidated_properties, + gpointer user_data) +{ + NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GVariantIter i; + const char *property; + const char *str; + GVariant *v; + gint int_val; + const char **strv; + + g_object_freeze_notify (G_OBJECT (self)); + g_variant_iter_init (&i, changed_properties); + while (g_variant_iter_next (&i, "{&sv}", &property, &v)) { + if (!strcmp (property, "Name")) { + str = g_variant_get_string (v, NULL); + if (g_strcmp0 (priv->name, str)) { + g_free (priv->name); + priv->name = g_strdup (str); + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_NAME); + } + } else if (!strcmp (property, "RSSI")) { + int_val = g_variant_get_int16 (v); + if (priv->rssi != int_val) { + priv->rssi = int_val; + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_RSSI); + } + } else if (!strcmp (property, "UUIDs")) { + strv = g_variant_get_strv (v, NULL); + _set_property_capabilities (self, strv, TRUE); + g_free (strv); + } else if (!strcmp (property, "Connected")) { + gboolean connected = g_variant_get_boolean (v); + if (priv->connected != connected) { + priv->connected = connected; + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CONNECTED); + } + } + g_variant_unref (v); + } + g_object_thaw_notify (G_OBJECT (self)); + + check_emit_usable (self); +} +#else +static void +property_changed (DBusGProxy *proxy4, const char *property, GValue *value, gpointer user_data) @@ -274,47 +772,100 @@ property_changed (DBusGProxy *proxy, NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); const char *str; - guint32 uint_val; gint int_val; - if (!strcmp (property, "Name")) { - str = g_value_get_string (value); - if ( (!priv->name && str) - || (priv->name && !str) - || (priv->name && str && strcmp (priv->name, str))) { - g_free (priv->name); - priv->name = g_strdup (str); - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_NAME); - } - } else if (!strcmp (property, "RSSI")) { - int_val = g_value_get_int (value); - if (priv->rssi != int_val) { - priv->rssi = int_val; - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_RSSI); - } - } else if (!strcmp (property, "UUIDs")) { - uint_val = convert_uuids_to_capabilities ((const char **) g_value_get_boxed (value)); - if (priv->capabilities != uint_val) { - priv->capabilities = uint_val; - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CAPABILITIES); + g_object_freeze_notify (G_OBJECT (self)); + { + if (!strcmp (property, "Name")) { + str = g_value_get_string (value); + if ( (!priv->name && str) + || (priv->name && !str) + || (priv->name && str && strcmp (priv->name, str))) { + g_free (priv->name); + priv->name = g_strdup (str); + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_NAME); + } + } else if (!strcmp (property, "RSSI")) { + int_val = g_value_get_int (value); + if (priv->rssi != int_val) { + priv->rssi = int_val; + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_RSSI); + } + } else if (!strcmp (property, "UUIDs")) { + _set_property_capabilities (self, (const char **) g_value_get_boxed (value), TRUE); + } else if (!strcmp (property, "Connected")) { + gboolean connected = g_value_get_boolean (value); + if (priv->connected != connected) { + priv->connected = connected; + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CONNECTED); + } } } + g_object_thaw_notify (G_OBJECT (self)); check_emit_usable (self); } +#endif + +#if ! WITH_BLUEZ4 +static void +query_properties (NMBluezDevice *self) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GVariant *v; + const char **uuids; + + v = g_dbus_proxy_get_cached_property (priv->proxy5, "Address"); + _set_property_address (self, v ? g_variant_get_string (v, NULL) : NULL); + if (v) + g_variant_unref (v); + + v = g_dbus_proxy_get_cached_property (priv->proxy5, "Name"); + priv->name = v ? g_variant_dup_string (v, NULL) : NULL; + if (v) + g_variant_unref (v); + + v = g_dbus_proxy_get_cached_property (priv->proxy5, "RSSI"); + priv->rssi = v ? g_variant_get_int16 (v) : 0; + if (v) + g_variant_unref (v); + + v = g_dbus_proxy_get_cached_property (priv->proxy5, "UUIDs"); + if (v) { + uuids = g_variant_get_strv (v, NULL); + _set_property_capabilities (self, uuids, FALSE); + g_variant_unref (v); + } else + priv->capabilities = NM_BT_CAPABILITY_NONE; + + v = g_dbus_proxy_get_cached_property (priv->proxy5, "Adapter"); + if (v) { + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + BLUEZ_SERVICE, + g_variant_get_string (v, NULL), + BLUEZ_ADAPTER_INTERFACE, + NULL, + (GAsyncReadyCallback) on_adapter_acquired, + g_object_ref (self)); + g_variant_unref (v); + } + /* Check if any connections match this device */ + cp_connections_loaded (priv->provider, self); +} +#else static void -get_properties_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +get_properties_cb (DBusGProxy *proxy4, DBusGProxyCall *call, gpointer user_data) { NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); GHashTable *properties = NULL; GError *err = NULL; GValue *value; - const char **uuids; - struct ether_addr *tmp; - if (!dbus_g_proxy_end_call (proxy, call, &err, + if (!dbus_g_proxy_end_call (proxy4, call, &err, DBUS_TYPE_G_MAP_OF_VARIANT, &properties, G_TYPE_INVALID)) { nm_log_warn (LOGD_BT, "bluez error getting device properties: %s", @@ -325,12 +876,7 @@ get_properties_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) } value = g_hash_table_lookup (properties, "Address"); - priv->address = value ? g_value_dup_string (value) : NULL; - if (priv->address) { - tmp = ether_aton (priv->address); - g_assert (tmp); - memcpy (priv->bin_address, tmp->ether_addr_octet, ETH_ALEN); - } + _set_property_address (self, value ? g_value_get_string (value) : NULL); value = g_hash_table_lookup (properties, "Name"); priv->name = value ? g_value_dup_string (value) : NULL; @@ -340,8 +886,7 @@ get_properties_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) value = g_hash_table_lookup (properties, "UUIDs"); if (value) { - uuids = (const char **) g_value_get_boxed (value); - priv->capabilities = convert_uuids_to_capabilities (uuids); + _set_property_capabilities (self, (const char **) g_value_get_boxed (value), FALSE); } else priv->capabilities = NM_BT_CAPABILITY_NONE; @@ -362,7 +907,7 @@ query_properties (NMBluezDevice *self) NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); DBusGProxyCall *call; - call = dbus_g_proxy_begin_call (priv->proxy, "GetProperties", + call = dbus_g_proxy_begin_call (priv->proxy4, "GetProperties", get_properties_cb, self, NULL, G_TYPE_INVALID); @@ -371,6 +916,49 @@ query_properties (NMBluezDevice *self) priv->path); } } +#endif + + +#if ! WITH_BLUEZ4 +static void +on_proxy_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GError *error; + + priv->proxy5 = g_dbus_proxy_new_for_bus_finish (res, &error); + + if (!priv->proxy5) { + nm_log_warn (LOGD_BT, "failed to acquire device proxy: %s.", error->message); + g_clear_error (&error); + g_signal_emit (self, signals[INITIALIZED], 0, FALSE); + } else { + g_signal_connect (priv->proxy5, "g-properties-changed", + G_CALLBACK (properties_changed), self); + + query_properties (self); + } + g_object_unref (self); +} +#endif + +static void +on_bus_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GError *error = NULL; + + priv->dbus_connection = g_bus_get_finish (res, &error); + + if (!priv->dbus_connection) { + nm_log_warn (LOGD_BT, "failed to acquire bus connection: %s.", error->message); + g_clear_error (&error); + g_signal_emit (self, signals[INITIALIZED], 0, FALSE); + return; + } + + check_emit_usable (self); +} /********************************************************************/ @@ -379,8 +967,10 @@ nm_bluez_device_new (const char *path, NMConnectionProvider *provider) { NMBluezDevice *self; NMBluezDevicePrivate *priv; +#if WITH_BLUEZ4 NMDBusManager *dbus_mgr; DBusGConnection *connection; +#endif g_return_val_if_fail (path != NULL, NULL); g_return_val_if_fail (provider != NULL, NULL); @@ -415,25 +1005,43 @@ nm_bluez_device_new (const char *path, NMConnectionProvider *provider) G_CALLBACK (cp_connections_loaded), self); + g_bus_get (G_BUS_TYPE_SYSTEM, + NULL, + (GAsyncReadyCallback) on_bus_acquired, + self); + +#if ! WITH_BLUEZ4 + g_object_ref (self); + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + BLUEZ_SERVICE, + priv->path, + BLUEZ_DEVICE_INTERFACE, + NULL, + (GAsyncReadyCallback) on_proxy_acquired, + self); +#else dbus_mgr = nm_dbus_manager_get (); connection = nm_dbus_manager_get_connection (dbus_mgr); - priv->proxy = dbus_g_proxy_new_for_name (connection, - BLUEZ_SERVICE, - priv->path, - BLUEZ_DEVICE_INTERFACE); + priv->proxy4 = dbus_g_proxy_new_for_name (connection, + BLUEZ_SERVICE, + priv->path, + BLUEZ_DEVICE_INTERFACE); g_object_unref (dbus_mgr); dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_BOXED, G_TYPE_NONE, G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_INVALID); - dbus_g_proxy_add_signal (priv->proxy, "PropertyChanged", + dbus_g_proxy_add_signal (priv->proxy4, "PropertyChanged", G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->proxy, "PropertyChanged", + dbus_g_proxy_connect_signal (priv->proxy4, "PropertyChanged", G_CALLBACK (property_changed), self, NULL); query_properties (self); +#endif return self; } @@ -457,6 +1065,11 @@ dispose (GObject *object) g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_updated, self); g_signal_handlers_disconnect_by_func (priv->provider, cp_connections_loaded, self); +#if ! WITH_BLUEZ4 + g_clear_object (&priv->adapter); +#endif + g_clear_object (&priv->dbus_connection); + G_OBJECT_CLASS (nm_bluez_device_parent_class)->dispose (object); } @@ -468,7 +1081,12 @@ finalize (GObject *object) g_free (priv->path); g_free (priv->address); g_free (priv->name); - g_object_unref (priv->proxy); + g_free (priv->bt_iface); +#if ! WITH_BLUEZ4 + g_object_unref (priv->proxy5); +#else + g_object_unref (priv->proxy4); +#endif G_OBJECT_CLASS (nm_bluez_device_parent_class)->finalize (object); } @@ -498,6 +1116,9 @@ get_property (GObject *object, guint prop_id, case PROP_USABLE: g_value_set_boolean (value, priv->usable); break; + case PROP_CONNECTED: + g_value_set_boolean (value, priv->connected); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -583,13 +1204,20 @@ nm_bluez_device_class_init (NMBluezDeviceClass *config_class) FALSE, G_PARAM_READABLE)); + g_object_class_install_property + (object_class, PROP_CONNECTED, + g_param_spec_boolean (NM_BLUEZ_DEVICE_CONNECTED, + "Connected", + "Connected", + FALSE, + G_PARAM_READABLE)); + /* Signals */ signals[INITIALIZED] = g_signal_new ("initialized", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NMBluezDeviceClass, initialized), - NULL, NULL, - g_cclosure_marshal_VOID__BOOLEAN, + NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); } diff --git a/src/bluez-manager/nm-bluez-device.h b/src/bluez-manager/nm-bluez-device.h index 18f9fc30..11add389 100644 --- a/src/bluez-manager/nm-bluez-device.h +++ b/src/bluez-manager/nm-bluez-device.h @@ -23,7 +23,9 @@ #include <glib.h> #include <glib-object.h> +#include <gio/gio.h> +#include <config.h> #include "nm-connection.h" #include "nm-connection-provider.h" @@ -40,6 +42,7 @@ #define NM_BLUEZ_DEVICE_CAPABILITIES "capabilities" #define NM_BLUEZ_DEVICE_RSSI "rssi" #define NM_BLUEZ_DEVICE_USABLE "usable" +#define NM_BLUEZ_DEVICE_CONNECTED "connected" typedef struct { GObject parent; @@ -74,5 +77,21 @@ guint32 nm_bluez_device_get_capabilities (NMBluezDevice *self); gint nm_bluez_device_get_rssi (NMBluezDevice *self); +gboolean nm_bluez_device_get_connected (NMBluezDevice *self); + +void +nm_bluez_device_connect_async (NMBluezDevice *self, + NMBluetoothCapabilities connection_bt_type, + GAsyncReadyCallback callback, + gpointer user_data); + +const char * +nm_bluez_device_connect_finish (NMBluezDevice *self, + GAsyncResult *result, + GError **error); + +void +nm_bluez_device_disconnect (NMBluezDevice *self); + #endif /* NM_BLUEZ_DEVICE_H */ diff --git a/src/bluez-manager/nm-bluez-manager.c b/src/bluez-manager/nm-bluez-manager.c index a6848631..3801d5ee 100644 --- a/src/bluez-manager/nm-bluez-manager.c +++ b/src/bluez-manager/nm-bluez-manager.c @@ -17,21 +17,20 @@ * * Copyright (C) 2007 - 2008 Novell, Inc. * Copyright (C) 2007 - 2012 Red Hat, Inc. + * Copyright (C) 2013 Intel Corporation. */ #include <signal.h> #include <string.h> #include <stdlib.h> -#include <dbus/dbus-glib.h> +#include <gio/gio.h> #include "nm-logging.h" -#include "nm-dbus-glib-types.h" -#include "nm-marshal.h" #include "nm-bluez-manager.h" -#include "nm-bluez-adapter.h" -#include "nm-dbus-manager.h" +#include "nm-bluez-device.h" #include "nm-bluez-common.h" +#include "nm-dbus-manager.h" typedef struct { NMDBusManager *dbus_mgr; @@ -39,9 +38,9 @@ typedef struct { NMConnectionProvider *provider; - DBusGProxy *proxy; + GDBusProxy *proxy; - NMBluezAdapter *adapter; + GHashTable *devices; } NMBluezManagerPrivate; #define NM_BLUEZ_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_BLUEZ_MANAGER, NMBluezManagerPrivate)) @@ -57,11 +56,14 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; -static void +static void device_initialized (NMBluezDevice *device, gboolean success, NMBluezManager *self); +static void device_usable (NMBluezDevice *device, GParamSpec *pspec, NMBluezManager *self); +static void emit_bdaddr_added (NMBluezManager *self, NMBluezDevice *device) { g_signal_emit (self, signals[BDADDR_ADDED], 0, + device, nm_bluez_device_get_address (device), nm_bluez_device_get_name (device), nm_bluez_device_get_path (device), @@ -72,173 +74,216 @@ void nm_bluez_manager_query_devices (NMBluezManager *self) { NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - GSList *devices, *iter; + NMBluezDevice *device; + GHashTableIter iter; - if (!priv->adapter) - return; + g_hash_table_iter_init (&iter, priv->devices); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) { + if (nm_bluez_device_get_usable (device)) + emit_bdaddr_added (self, device); + } +} - devices = nm_bluez_adapter_get_devices (priv->adapter); - for (iter = devices; iter; iter = g_slist_next (iter)) - emit_bdaddr_added (self, NM_BLUEZ_DEVICE (iter->data)); - g_slist_free (devices); +static void +remove_device (NMBluezManager *self, NMBluezDevice *device) +{ + if (nm_bluez_device_get_usable (device)) { + g_signal_emit (self, signals[BDADDR_REMOVED], 0, + nm_bluez_device_get_address (device), + nm_bluez_device_get_path (device)); + } + g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_initialized), self); + g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_usable), self); } static void -device_added (NMBluezAdapter *adapter, NMBluezDevice *device, gpointer user_data) +remove_all_devices (NMBluezManager *self) { - emit_bdaddr_added (NM_BLUEZ_MANAGER (user_data), device); + GHashTableIter iter; + NMBluezDevice *device; + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + g_hash_table_iter_init (&iter, priv->devices); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) { + g_hash_table_iter_steal (&iter); + remove_device (self, device); + g_object_unref (device); + } } static void -device_removed (NMBluezAdapter *adapter, NMBluezDevice *device, gpointer user_data) +device_usable (NMBluezDevice *device, GParamSpec *pspec, NMBluezManager *self) { - NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); + gboolean usable = nm_bluez_device_get_usable (device); + + nm_log_dbg (LOGD_BT, "(%s): bluez device now %s", + nm_bluez_device_get_path (device), + usable ? "usable" : "unusable"); + + if (usable) { + nm_log_dbg (LOGD_BT, "(%s): bluez device address %s", + nm_bluez_device_get_path (device), + nm_bluez_device_get_address (device)); + emit_bdaddr_added (self, device); + } else + g_signal_emit (self, signals[BDADDR_REMOVED], 0, + nm_bluez_device_get_address (device), + nm_bluez_device_get_path (device)); +} - g_signal_emit (self, signals[BDADDR_REMOVED], 0, - nm_bluez_device_get_address (device), - nm_bluez_device_get_path (device)); +static void +device_initialized (NMBluezDevice *device, gboolean success, NMBluezManager *self) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + nm_log_dbg (LOGD_BT, "(%s): bluez device %s", + nm_bluez_device_get_path (device), + success ? "initialized" : "failed to initialize"); + if (!success) + g_hash_table_remove (priv->devices, nm_bluez_device_get_path (device)); } static void -adapter_initialized (NMBluezAdapter *adapter, gboolean success, gpointer user_data) +device_added (GDBusProxy *proxy, const gchar *path, NMBluezManager *self) { - NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + NMBluezDevice *device; + + device = nm_bluez_device_new (path, priv->provider); + g_signal_connect (device, "initialized", G_CALLBACK (device_initialized), self); + g_signal_connect (device, "notify::usable", G_CALLBACK (device_usable), self); + g_hash_table_insert (priv->devices, (gpointer) nm_bluez_device_get_path (device), device); + + nm_log_dbg (LOGD_BT, "(%s): new bluez device found", path); +} - if (success) { - GSList *devices, *iter; +static void +device_removed (GDBusProxy *proxy, const gchar *path, NMBluezManager *self) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + NMBluezDevice *device; - devices = nm_bluez_adapter_get_devices (adapter); - for (iter = devices; iter; iter = g_slist_next (iter)) - emit_bdaddr_added (self, NM_BLUEZ_DEVICE (iter->data)); - g_slist_free (devices); + nm_log_dbg (LOGD_BT, "(%s): bluez device removed", path); - g_signal_connect (adapter, "device-added", G_CALLBACK (device_added), self); - g_signal_connect (adapter, "device-removed", G_CALLBACK (device_removed), self); - } else { - g_object_unref (priv->adapter); - priv->adapter = NULL; + device = g_hash_table_lookup (priv->devices, path); + if (device) { + g_hash_table_steal (priv->devices, nm_bluez_device_get_path (device)); + remove_device (NM_BLUEZ_MANAGER (self), device); + g_object_unref (device); } } static void -adapter_removed (DBusGProxy *proxy, const char *path, NMBluezManager *self) +object_manager_g_signal (GDBusProxy *proxy, + gchar *sender_name, + gchar *signal_name, + GVariant *parameters, + NMBluezManager *self) { - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + GVariant *variant; + const gchar *path; - if (priv->adapter && !strcmp (path, nm_bluez_adapter_get_path (priv->adapter))) { - if (nm_bluez_adapter_get_initialized (priv->adapter)) { - GSList *devices, *iter; + if (!strcmp (signal_name, "InterfacesRemoved")) { + const gchar **ifaces; + gsize i, length; - devices = nm_bluez_adapter_get_devices (priv->adapter); - for (iter = devices; iter; iter = g_slist_next (iter)) { - NMBluezDevice *device = NM_BLUEZ_DEVICE (iter->data); + g_variant_get (parameters, "(&o*)", &path, &variant); - g_signal_emit (self, signals[BDADDR_REMOVED], 0, - nm_bluez_device_get_address (device), - nm_bluez_device_get_path (device)); + ifaces = g_variant_get_strv (variant, &length); + + for (i = 0; i < length; i++) { + if (!strcmp (ifaces[i], BLUEZ_DEVICE_INTERFACE)) { + device_removed (proxy, path, self); + break; } - g_slist_free (devices); } - g_object_unref (priv->adapter); - priv->adapter = NULL; + g_free (ifaces); + + } else if (!strcmp (signal_name, "InterfacesAdded")) { + g_variant_get (parameters, "(&o*)", &path, &variant); + + if (g_variant_lookup_value (variant, BLUEZ_DEVICE_INTERFACE, + G_VARIANT_TYPE_DICTIONARY)) + device_added (proxy, path, self); } } static void -default_adapter_changed (DBusGProxy *proxy, const char *path, NMBluezManager *self) +get_managed_objects_cb (GDBusProxy *proxy, + GAsyncResult *res, + NMBluezManager *self) { - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - const char *cur_path = NULL; - - if (priv->adapter) - cur_path = nm_bluez_adapter_get_path (priv->adapter); - - if (cur_path) { - if (!path || strcmp (path, cur_path)) { - /* Default adapter changed */ - adapter_removed (priv->proxy, cur_path, self); - } else { - /* This adapter is already the default */ - return; + GVariant *variant, *ifaces; + GVariantIter i; + GError *error = NULL; + const char *path; + + variant = g_dbus_proxy_call_finish (proxy, res, &error); + + if (!variant) { + nm_log_warn (LOGD_BT, "Couldn't get managed objects: %s", + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + return; + } + g_variant_iter_init (&i, g_variant_get_child_value (variant, 0)); + while ((g_variant_iter_next (&i, "{&o*}", &path, &ifaces))) { + if (g_variant_lookup_value (ifaces, BLUEZ_DEVICE_INTERFACE, + G_VARIANT_TYPE_DICTIONARY)) { + device_added (proxy, path, self); } } - /* Add the new default adapter */ - if (path) { - priv->adapter = nm_bluez_adapter_new (path, priv->provider); - g_signal_connect (priv->adapter, "initialized", G_CALLBACK (adapter_initialized), self); - } + g_variant_unref (variant); } static void -default_adapter_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +on_proxy_acquired (GObject *object, + GAsyncResult *res, + NMBluezManager *self) { - NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - const char *default_adapter = NULL; - GError *err = NULL; - - if (!dbus_g_proxy_end_call (proxy, call, &err, - DBUS_TYPE_G_OBJECT_PATH, &default_adapter, - G_TYPE_INVALID)) { - /* Ignore "No such adapter" errors; just means bluetooth isn't active */ - if ( !dbus_g_error_has_name (err, "org.bluez.Error.NoSuchAdapter") - && !dbus_g_error_has_name (err, "org.freedesktop.systemd1.LoadFailed") - && !g_error_matches (err, DBUS_GERROR, DBUS_GERROR_SERVICE_UNKNOWN)) { - nm_log_warn (LOGD_BT, "bluez error getting default adapter: %s", - err && err->message ? err->message : "(unknown)"); - } - g_error_free (err); + GError *error = NULL; + + priv->proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + + if (!priv->proxy) { + nm_log_warn (LOGD_BT, "Couldn't acquire object manager proxy: %s", + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); return; } - default_adapter_changed (priv->proxy, default_adapter, self); -} - -static void -query_default_adapter (NMBluezManager *self) -{ - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - DBusGProxyCall *call; - - call = dbus_g_proxy_begin_call (priv->proxy, "DefaultAdapter", - default_adapter_cb, - self, - NULL, G_TYPE_INVALID); - if (!call) - nm_log_warn (LOGD_BT, "failed to request default Bluetooth adapter."); + /* Get already managed devices. */ + g_dbus_proxy_call (priv->proxy, "GetManagedObjects", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + (GAsyncReadyCallback) get_managed_objects_cb, + self); + + g_signal_connect (priv->proxy, "g-signal", + G_CALLBACK (object_manager_g_signal), self); } static void bluez_connect (NMBluezManager *self) { NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - DBusGConnection *connection; g_return_if_fail (priv->proxy == NULL); - connection = nm_dbus_manager_get_connection (priv->dbus_mgr); - if (!connection) - return; - - priv->proxy = dbus_g_proxy_new_for_name (connection, - BLUEZ_SERVICE, - BLUEZ_MANAGER_PATH, - BLUEZ_MANAGER_INTERFACE); - - dbus_g_proxy_add_signal (priv->proxy, "AdapterRemoved", - DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->proxy, "AdapterRemoved", - G_CALLBACK (adapter_removed), self, NULL); - - dbus_g_proxy_add_signal (priv->proxy, "DefaultAdapterChanged", - DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->proxy, "DefaultAdapterChanged", - G_CALLBACK (default_adapter_changed), self, NULL); - - query_default_adapter (self); + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + BLUEZ_SERVICE, + BLUEZ_MANAGER_PATH, + OBJECT_MANAGER_INTERFACE, + NULL, + (GAsyncReadyCallback) on_proxy_acquired, + self); } static void @@ -257,14 +302,9 @@ name_owner_changed_cb (NMDBusManager *dbus_mgr, if (strcmp (BLUEZ_SERVICE, name)) return; - if (!old_owner_good && new_owner_good) - query_default_adapter (self); - else if (old_owner_good && !new_owner_good) { - /* Throwing away the adapter removes all devices too */ - if (priv->adapter) { - g_object_unref (priv->adapter); - priv->adapter = NULL; - } + if (old_owner_good && !new_owner_good) { + if (priv->devices) + remove_all_devices (self); } } @@ -278,10 +318,10 @@ bluez_cleanup (NMBluezManager *self, gboolean do_signal) priv->proxy = NULL; } - if (priv->adapter) { - g_object_unref (priv->adapter); - priv->adapter = NULL; - } + if (do_signal) + remove_all_devices (self); + else + g_hash_table_remove_all (priv->devices); } static void @@ -335,6 +375,9 @@ nm_bluez_manager_init (NMBluezManager *self) self); bluez_connect (self); + + priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, + NULL, g_object_unref); } static void @@ -348,13 +391,23 @@ dispose (GObject *object) if (priv->dbus_mgr) { g_signal_handlers_disconnect_by_func (priv->dbus_mgr, name_owner_changed_cb, self); g_signal_handlers_disconnect_by_func (priv->dbus_mgr, dbus_connection_changed_cb, self); - g_object_unref (priv->dbus_mgr); + priv->dbus_mgr = NULL; } G_OBJECT_CLASS (nm_bluez_manager_parent_class)->dispose (object); } static void +finalize (GObject *object) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (object); + + g_hash_table_destroy (priv->devices); + + G_OBJECT_CLASS (nm_bluez_manager_parent_class)->finalize (object); +} + +static void nm_bluez_manager_class_init (NMBluezManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); @@ -363,6 +416,7 @@ nm_bluez_manager_class_init (NMBluezManagerClass *klass) /* virtual methods */ object_class->dispose = dispose; + object_class->finalize = finalize; /* Signals */ signals[BDADDR_ADDED] = @@ -370,17 +424,15 @@ nm_bluez_manager_class_init (NMBluezManagerClass *klass) G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (NMBluezManagerClass, bdaddr_added), - NULL, NULL, - _nm_marshal_VOID__STRING_STRING_STRING_UINT, - G_TYPE_NONE, 4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT); + NULL, NULL, NULL, + G_TYPE_NONE, 5, G_TYPE_OBJECT, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT); signals[BDADDR_REMOVED] = g_signal_new (NM_BLUEZ_MANAGER_BDADDR_REMOVED, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (NMBluezManagerClass, bdaddr_removed), - NULL, NULL, - _nm_marshal_VOID__STRING_STRING, + NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); } - diff --git a/src/bluez-manager/nm-bluez-manager.h b/src/bluez-manager/nm-bluez-manager.h index 2bfc971e..95e319c5 100644 --- a/src/bluez-manager/nm-bluez-manager.h +++ b/src/bluez-manager/nm-bluez-manager.h @@ -25,6 +25,7 @@ #include <glib.h> #include <glib-object.h> +#include <config.h> #include "nm-connection-provider.h" G_BEGIN_DECLS diff --git a/src/bluez-manager/nm-bluez-adapter.c b/src/bluez-manager/nm-bluez4-adapter.c index 4c36f3de..817df73d 100644 --- a/src/bluez-manager/nm-bluez-adapter.c +++ b/src/bluez-manager/nm-bluez4-adapter.c @@ -23,7 +23,7 @@ #include "NetworkManager.h" #include "nm-dbus-manager.h" -#include "nm-bluez-adapter.h" +#include "nm-bluez4-adapter.h" #include "nm-bluez-device.h" #include "nm-bluez-common.h" #include "nm-dbus-glib-types.h" diff --git a/src/bluez-manager/nm-bluez-adapter.h b/src/bluez-manager/nm-bluez4-adapter.h index 8e53b40d..8e53b40d 100644 --- a/src/bluez-manager/nm-bluez-adapter.h +++ b/src/bluez-manager/nm-bluez4-adapter.h diff --git a/src/bluez-manager/nm-bluez4-manager.c b/src/bluez-manager/nm-bluez4-manager.c new file mode 100644 index 00000000..bd1d251a --- /dev/null +++ b/src/bluez-manager/nm-bluez4-manager.c @@ -0,0 +1,386 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2007 - 2008 Novell, Inc. + * Copyright (C) 2007 - 2012 Red Hat, Inc. + */ + +#include <signal.h> +#include <string.h> +#include <stdlib.h> +#include <dbus/dbus-glib.h> + +#include "nm-logging.h" +#include "nm-dbus-glib-types.h" +#include "nm-marshal.h" +#include "nm-bluez-manager.h" +#include "nm-bluez4-adapter.h" +#include "nm-dbus-manager.h" +#include "nm-bluez-common.h" + + +typedef struct { + NMDBusManager *dbus_mgr; + gulong name_owner_changed_id; + + NMConnectionProvider *provider; + + DBusGProxy *proxy; + + NMBluezAdapter *adapter; +} NMBluezManagerPrivate; + +#define NM_BLUEZ_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_BLUEZ_MANAGER, NMBluezManagerPrivate)) + +G_DEFINE_TYPE (NMBluezManager, nm_bluez_manager, G_TYPE_OBJECT) + +enum { + BDADDR_ADDED, + BDADDR_REMOVED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +static void + +emit_bdaddr_added (NMBluezManager *self, NMBluezDevice *device) +{ + g_signal_emit (self, signals[BDADDR_ADDED], 0, + device, + nm_bluez_device_get_address (device), + nm_bluez_device_get_name (device), + nm_bluez_device_get_path (device), + nm_bluez_device_get_capabilities (device)); +} + +void +nm_bluez_manager_query_devices (NMBluezManager *self) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + GSList *devices, *iter; + + if (!priv->adapter) + return; + + devices = nm_bluez_adapter_get_devices (priv->adapter); + for (iter = devices; iter; iter = g_slist_next (iter)) + emit_bdaddr_added (self, NM_BLUEZ_DEVICE (iter->data)); + g_slist_free (devices); +} + +static void +device_added (NMBluezAdapter *adapter, NMBluezDevice *device, gpointer user_data) +{ + emit_bdaddr_added (NM_BLUEZ_MANAGER (user_data), device); +} + +static void +device_removed (NMBluezAdapter *adapter, NMBluezDevice *device, gpointer user_data) +{ + NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); + + g_signal_emit (self, signals[BDADDR_REMOVED], 0, + nm_bluez_device_get_address (device), + nm_bluez_device_get_path (device)); +} + +static void +adapter_initialized (NMBluezAdapter *adapter, gboolean success, gpointer user_data) +{ + NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + if (success) { + GSList *devices, *iter; + + devices = nm_bluez_adapter_get_devices (adapter); + for (iter = devices; iter; iter = g_slist_next (iter)) + emit_bdaddr_added (self, NM_BLUEZ_DEVICE (iter->data)); + g_slist_free (devices); + + g_signal_connect (adapter, "device-added", G_CALLBACK (device_added), self); + g_signal_connect (adapter, "device-removed", G_CALLBACK (device_removed), self); + } else { + g_object_unref (priv->adapter); + priv->adapter = NULL; + } +} + +static void +adapter_removed (DBusGProxy *proxy, const char *path, NMBluezManager *self) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + if (priv->adapter && !strcmp (path, nm_bluez_adapter_get_path (priv->adapter))) { + if (nm_bluez_adapter_get_initialized (priv->adapter)) { + GSList *devices, *iter; + + devices = nm_bluez_adapter_get_devices (priv->adapter); + for (iter = devices; iter; iter = g_slist_next (iter)) { + NMBluezDevice *device = NM_BLUEZ_DEVICE (iter->data); + + g_signal_emit (self, signals[BDADDR_REMOVED], 0, + nm_bluez_device_get_address (device), + nm_bluez_device_get_path (device)); + } + g_slist_free (devices); + } + + g_object_unref (priv->adapter); + priv->adapter = NULL; + } +} + +static void +default_adapter_changed (DBusGProxy *proxy, const char *path, NMBluezManager *self) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + const char *cur_path = NULL; + + if (priv->adapter) + cur_path = nm_bluez_adapter_get_path (priv->adapter); + + if (cur_path) { + if (!path || strcmp (path, cur_path)) { + /* Default adapter changed */ + adapter_removed (priv->proxy, cur_path, self); + } else { + /* This adapter is already the default */ + return; + } + } + + /* Add the new default adapter */ + if (path) { + priv->adapter = nm_bluez_adapter_new (path, priv->provider); + g_signal_connect (priv->adapter, "initialized", G_CALLBACK (adapter_initialized), self); + } +} + +static void +default_adapter_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +{ + NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + const char *default_adapter = NULL; + GError *err = NULL; + + if (!dbus_g_proxy_end_call (proxy, call, &err, + DBUS_TYPE_G_OBJECT_PATH, &default_adapter, + G_TYPE_INVALID)) { + /* Ignore "No such adapter" errors; just means bluetooth isn't active */ + if ( !dbus_g_error_has_name (err, "org.bluez.Error.NoSuchAdapter") + && !dbus_g_error_has_name (err, "org.freedesktop.systemd1.LoadFailed") + && !g_error_matches (err, DBUS_GERROR, DBUS_GERROR_SERVICE_UNKNOWN)) { + nm_log_warn (LOGD_BT, "bluez error getting default adapter: %s", + err && err->message ? err->message : "(unknown)"); + } + g_error_free (err); + return; + } + + default_adapter_changed (priv->proxy, default_adapter, self); +} + +static void +query_default_adapter (NMBluezManager *self) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + DBusGProxyCall *call; + + call = dbus_g_proxy_begin_call (priv->proxy, "DefaultAdapter", + default_adapter_cb, + self, + NULL, G_TYPE_INVALID); + if (!call) + nm_log_warn (LOGD_BT, "failed to request default Bluetooth adapter."); +} + +static void +bluez_connect (NMBluezManager *self) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + DBusGConnection *connection; + + g_return_if_fail (priv->proxy == NULL); + + connection = nm_dbus_manager_get_connection (priv->dbus_mgr); + if (!connection) + return; + + priv->proxy = dbus_g_proxy_new_for_name (connection, + BLUEZ_SERVICE, + BLUEZ_MANAGER_PATH, + BLUEZ_MANAGER_INTERFACE); + + dbus_g_proxy_add_signal (priv->proxy, "AdapterRemoved", + DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->proxy, "AdapterRemoved", + G_CALLBACK (adapter_removed), self, NULL); + + dbus_g_proxy_add_signal (priv->proxy, "DefaultAdapterChanged", + DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->proxy, "DefaultAdapterChanged", + G_CALLBACK (default_adapter_changed), self, NULL); + + query_default_adapter (self); +} + +static void +name_owner_changed_cb (NMDBusManager *dbus_mgr, + const char *name, + const char *old_owner, + const char *new_owner, + gpointer user_data) +{ + NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + gboolean old_owner_good = (old_owner && strlen (old_owner)); + gboolean new_owner_good = (new_owner && strlen (new_owner)); + + /* Can't handle the signal if its not from the Bluez */ + if (strcmp (BLUEZ_SERVICE, name)) + return; + + if (!old_owner_good && new_owner_good) + query_default_adapter (self); + else if (old_owner_good && !new_owner_good) { + /* Throwing away the adapter removes all devices too */ + if (priv->adapter) { + g_object_unref (priv->adapter); + priv->adapter = NULL; + } + } +} + +static void +bluez_cleanup (NMBluezManager *self, gboolean do_signal) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + if (priv->proxy) { + g_object_unref (priv->proxy); + priv->proxy = NULL; + } + + if (priv->adapter) { + g_object_unref (priv->adapter); + priv->adapter = NULL; + } +} + +static void +dbus_connection_changed_cb (NMDBusManager *dbus_mgr, + DBusGConnection *connection, + gpointer user_data) +{ + NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); + + if (!connection) + bluez_cleanup (self, TRUE); + else + bluez_connect (self); +} + +/****************************************************************/ + +NMBluezManager * +nm_bluez_manager_get (NMConnectionProvider *provider) +{ + static NMBluezManager *singleton = NULL; + + if (singleton) + return g_object_ref (singleton); + + singleton = (NMBluezManager *) g_object_new (NM_TYPE_BLUEZ_MANAGER, NULL); + g_assert (singleton); + + /* Cache the connection provider for NMBluezAdapter objects */ + NM_BLUEZ_MANAGER_GET_PRIVATE (singleton)->provider = provider; + + return singleton; +} + +static void +nm_bluez_manager_init (NMBluezManager *self) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + priv->dbus_mgr = nm_dbus_manager_get (); + g_assert (priv->dbus_mgr); + + g_signal_connect (priv->dbus_mgr, + NM_DBUS_MANAGER_NAME_OWNER_CHANGED, + G_CALLBACK (name_owner_changed_cb), + self); + + g_signal_connect (priv->dbus_mgr, + NM_DBUS_MANAGER_DBUS_CONNECTION_CHANGED, + G_CALLBACK (dbus_connection_changed_cb), + self); + + bluez_connect (self); +} + +static void +dispose (GObject *object) +{ + NMBluezManager *self = NM_BLUEZ_MANAGER (object); + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + bluez_cleanup (self, FALSE); + + if (priv->dbus_mgr) { + g_signal_handlers_disconnect_by_func (priv->dbus_mgr, name_owner_changed_cb, self); + g_signal_handlers_disconnect_by_func (priv->dbus_mgr, dbus_connection_changed_cb, self); + g_object_unref (priv->dbus_mgr); + } + + G_OBJECT_CLASS (nm_bluez_manager_parent_class)->dispose (object); +} + +static void +nm_bluez_manager_class_init (NMBluezManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMBluezManagerPrivate)); + + /* virtual methods */ + object_class->dispose = dispose; + + /* Signals */ + signals[BDADDR_ADDED] = + g_signal_new (NM_BLUEZ_MANAGER_BDADDR_ADDED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMBluezManagerClass, bdaddr_added), + NULL, NULL, NULL, + G_TYPE_NONE, 5, G_TYPE_OBJECT, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT); + + signals[BDADDR_REMOVED] = + g_signal_new (NM_BLUEZ_MANAGER_BDADDR_REMOVED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMBluezManagerClass, bdaddr_removed), + NULL, NULL, NULL, + G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); +} + |