Upgrade to bluez-5.10 for testing devel_test
authorWu zheng <wu.zheng@intel.com>
Mon, 21 Oct 2013 07:46:54 +0000 (15:46 +0800)
committerWu zheng <wu.zheng@intel.com>
Mon, 21 Oct 2013 07:46:54 +0000 (15:46 +0800)
54 files changed:
ChangeLog
Makefile.am
Makefile.android
Makefile.in
Makefile.tools
android/Android.mk
android/hal-ipc-api.txt [new file with mode: 0644]
bluez.pc.in [deleted file]
configure
configure.ac
doc/input-api.txt [deleted file]
doc/mgmt-api.txt
doc/settings-storage.txt [deleted file]
emulator/btdev.c
gdbus/client.c
gdbus/object.c
monitor/bt.h
monitor/packet.c
obexd/client/session.c
obexd/plugins/messages-tracker.c [deleted file]
obexd/plugins/phonebook-ebook.c [deleted file]
obexd/plugins/phonebook-tracker.c [deleted file]
obexd/plugins/syncevolution.c [deleted file]
packaging/bluetooth.sh [changed mode: 0644->0755]
packaging/bluez.spec
packaging/create-symlinks [changed mode: 0644->0755]
packaging/obex-root-setup [changed mode: 0644->0755]
profiles/audio/1.patch [deleted file]
profiles/audio/avctp.c
profiles/audio/avdtp.c
profiles/audio/media.c
test/exchange-business-cards [deleted file]
test/ftp-client [deleted file]
test/get-managed-objects [deleted file]
test/get-obex-capabilities [deleted file]
test/list-folders [deleted file]
test/map-client [deleted file]
test/opp-client [deleted file]
test/pbap-client [deleted file]
test/simple-obex-agent [deleted file]
test/test-alert [changed mode: 0755->0644]
test/test-cyclingspeed [changed mode: 0755->0644]
test/test-heartrate [changed mode: 0755->0644]
test/test-hfp [changed mode: 0755->0644]
test/test-profile [changed mode: 0755->0644]
tools/bdaddr.1 [deleted file]
tools/btmgmt.c
tools/example.psr [deleted file]
tools/mgmt-tester.c
tools/mpris-player.c
tools/obexctl.c [new file with mode: 0644]
tools/sdptool.1
tools/update_compids.sh [deleted file]
ylwrap [deleted file]

index d829640260d74cdb599a83fbfa114f2310c6789e..fc9b3d7f22c6291334a535239a8dbb78b2e16cbd 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+ver 5.10:
+       Fix issue with discoverable timeout handling.
+       Fix issue with MAP messages and record version.
+       Fix issue with MAP messages and status events.
+       Fix issue with MAP messages and relative folders.
+       Fix issue with MAP messages and type property signals.
+       Fix issue with transfer size for OBEX GET operations.
+       Fix issue with AVRCP service class identifier.
+       Fix issue with AVRCP tracking seeked signal.
+       Add support for OBEX command line client.
+
 ver 5.9:
        Fix issue with network service and adapter removal.
        Fix issue with misleading OBEX error messages.
index 51204f4742bc50f9318ae251787ed23724c3a9d0..8aed6f7e459d8c7e4d5b52fce8e3ee5f7cc2fd84 100644 (file)
@@ -80,7 +80,7 @@ include_HEADERS += $(lib_headers)
 lib_LTLIBRARIES += lib/libbluetooth.la
 
 lib_libbluetooth_la_SOURCES = $(lib_headers) $(lib_sources)
-lib_libbluetooth_la_LDFLAGS = $(AM_LDFLAGS) -version-info 20:0:17
+lib_libbluetooth_la_LDFLAGS = $(AM_LDFLAGS) -version-info 20:1:17
 lib_libbluetooth_la_DEPENDENCIES = $(local_headers)
 endif
 
index e161e6dceb75b9a7d150e670dba09f21beffdf3e..3ceefd8f07fec6ce69d833dfdcbe20703b6d4dd5 100644 (file)
@@ -6,3 +6,5 @@ android_bluetoothd_LDADD = @GLIB_LIBS@
 endif
 
 EXTRA_DIST += android/Android.mk android/log.c
+
+EXTRA_DIST += android/hal-ipc-api.txt
index 6841024166a32a8ac82b45b559ed0b792f2bb0e3..677ad3e98aed7b54dfcc5b21541ae060c40c5f4e 100644 (file)
@@ -58,12 +58,13 @@ build_triplet = @build@
 host_triplet = @host@
 bin_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3)
 noinst_PROGRAMS = $(am__EXEEXT_4) $(am__EXEEXT_5) $(am__EXEEXT_6) \
-       $(am__EXEEXT_7)
+       $(am__EXEEXT_7) $(am__EXEEXT_8)
 libexec_PROGRAMS = src/bluetoothd$(EXEEXT) obexd/src/obexd$(EXEEXT)
 @LIBRARY_TRUE@am__append_1 = $(lib_headers)
 @LIBRARY_TRUE@am__append_2 = lib/libbluetooth.la
 DIST_COMMON = README $(am__configure_deps) $(am__include_HEADERS_DIST) \
-       $(dist_man_MANS) $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+       $(dist_man_MANS) $(srcdir)/Makefile.am \
+       $(srcdir)/Makefile.android $(srcdir)/Makefile.in \
        $(srcdir)/Makefile.obexd $(srcdir)/Makefile.plugins \
        $(srcdir)/Makefile.tools $(srcdir)/config.h.in \
        $(top_srcdir)/configure $(top_srcdir)/lib/bluez.pc.in \
@@ -114,10 +115,11 @@ DIST_COMMON = README $(am__configure_deps) $(am__include_HEADERS_DIST) \
 @EXPERIMENTAL_TRUE@    tools/mgmt-tester tools/gap-tester \
 @EXPERIMENTAL_TRUE@    tools/l2cap-tester tools/sco-tester \
 @EXPERIMENTAL_TRUE@    tools/bdaddr tools/avinfo tools/avtest \
-@EXPERIMENTAL_TRUE@    tools/scotest tools/hcieventmask \
-@EXPERIMENTAL_TRUE@    tools/hcisecfilter tools/hwdb tools/btmgmt \
-@EXPERIMENTAL_TRUE@    tools/btinfo tools/btattach tools/btsnoop \
-@EXPERIMENTAL_TRUE@    tools/btiotest tools/mpris-player
+@EXPERIMENTAL_TRUE@    tools/scotest tools/amptest tools/hwdb \
+@EXPERIMENTAL_TRUE@    tools/hcieventmask tools/hcisecfilter \
+@EXPERIMENTAL_TRUE@    tools/btmgmt tools/btinfo tools/btattach \
+@EXPERIMENTAL_TRUE@    tools/btsnoop tools/btiotest tools/cltest \
+@EXPERIMENTAL_TRUE@    tools/mpris-player
 @TOOLS_TRUE@am__append_16 = tools/hciattach tools/hciconfig tools/hcitool tools/hcidump \
 @TOOLS_TRUE@                   tools/rfcomm tools/rctest tools/l2test tools/l2ping \
 @TOOLS_TRUE@                   tools/sdptool tools/ciptool tools/bccmd
@@ -138,7 +140,7 @@ DIST_COMMON = README $(am__configure_deps) $(am__include_HEADERS_DIST) \
 @EXPERIMENTAL_TRUE@am__append_21 = tools/bdaddr.1
 @READLINE_TRUE@am__append_22 = attrib/gatttool \
 @READLINE_TRUE@                        tools/obex-client-tool tools/obex-server-tool \
-@READLINE_TRUE@                        tools/bluetooth-player
+@READLINE_TRUE@                        tools/bluetooth-player tools/obexctl
 
 @EXPERIMENTAL_TRUE@am__append_23 = profiles/iap/iapd
 @CUPS_TRUE@cups_PROGRAMS = profiles/cups/bluetooth$(EXEEXT)
@@ -149,8 +151,9 @@ DIST_COMMON = README $(am__configure_deps) $(am__include_HEADERS_DIST) \
 @OBEX_TRUE@    obexd/plugins/vcard.h obexd/plugins/vcard.c \
 @OBEX_TRUE@    obexd/plugins/phonebook.h \
 @OBEX_TRUE@    obexd/plugins/phonebook-dummy.c
-@HID2HCI_TRUE@am__append_28 = $(rules_DATA)
-TESTS = $(am__EXEEXT_7)
+@ANDROID_TRUE@am__append_28 = android/bluetoothd
+@HID2HCI_TRUE@am__append_29 = $(rules_DATA)
+TESTS = $(am__EXEEXT_8)
 subdir = .
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
@@ -275,20 +278,23 @@ plugins_external_dummy_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 @EXPERIMENTAL_TRUE@    tools/bdaddr$(EXEEXT) tools/avinfo$(EXEEXT) \
 @EXPERIMENTAL_TRUE@    tools/avtest$(EXEEXT) \
 @EXPERIMENTAL_TRUE@    tools/scotest$(EXEEXT) \
+@EXPERIMENTAL_TRUE@    tools/amptest$(EXEEXT) tools/hwdb$(EXEEXT) \
 @EXPERIMENTAL_TRUE@    tools/hcieventmask$(EXEEXT) \
 @EXPERIMENTAL_TRUE@    tools/hcisecfilter$(EXEEXT) \
-@EXPERIMENTAL_TRUE@    tools/hwdb$(EXEEXT) tools/btmgmt$(EXEEXT) \
-@EXPERIMENTAL_TRUE@    tools/btinfo$(EXEEXT) \
+@EXPERIMENTAL_TRUE@    tools/btmgmt$(EXEEXT) tools/btinfo$(EXEEXT) \
 @EXPERIMENTAL_TRUE@    tools/btattach$(EXEEXT) \
 @EXPERIMENTAL_TRUE@    tools/btsnoop$(EXEEXT) \
 @EXPERIMENTAL_TRUE@    tools/btiotest$(EXEEXT) \
+@EXPERIMENTAL_TRUE@    tools/cltest$(EXEEXT) \
 @EXPERIMENTAL_TRUE@    tools/mpris-player$(EXEEXT)
 @READLINE_TRUE@am__EXEEXT_5 = attrib/gatttool$(EXEEXT) \
 @READLINE_TRUE@        tools/obex-client-tool$(EXEEXT) \
 @READLINE_TRUE@        tools/obex-server-tool$(EXEEXT) \
-@READLINE_TRUE@        tools/bluetooth-player$(EXEEXT)
+@READLINE_TRUE@        tools/bluetooth-player$(EXEEXT) \
+@READLINE_TRUE@        tools/obexctl$(EXEEXT)
 @EXPERIMENTAL_TRUE@am__EXEEXT_6 = profiles/iap/iapd$(EXEEXT)
-am__EXEEXT_7 = unit/test-eir$(EXEEXT) unit/test-uuid$(EXEEXT) \
+@ANDROID_TRUE@am__EXEEXT_7 = android/bluetoothd$(EXEEXT)
+am__EXEEXT_8 = unit/test-eir$(EXEEXT) unit/test-uuid$(EXEEXT) \
        unit/test-textfile$(EXEEXT) unit/test-crc$(EXEEXT) \
        unit/test-mgmt$(EXEEXT) unit/test-sdp$(EXEEXT) \
        unit/test-gdbus-client$(EXEEXT) \
@@ -298,6 +304,11 @@ am__EXEEXT_7 = unit/test-eir$(EXEEXT) unit/test-uuid$(EXEEXT) \
        unit/test-gobex-apparam$(EXEEXT) unit/test-lib$(EXEEXT)
 PROGRAMS = $(bin_PROGRAMS) $(cups_PROGRAMS) $(libexec_PROGRAMS) \
        $(noinst_PROGRAMS) $(udev_PROGRAMS)
+am__android_bluetoothd_SOURCES_DIST = android/main.c src/log.c
+@ANDROID_TRUE@am_android_bluetoothd_OBJECTS = android/main.$(OBJEXT) \
+@ANDROID_TRUE@ src/log.$(OBJEXT)
+android_bluetoothd_OBJECTS = $(am_android_bluetoothd_OBJECTS)
+android_bluetoothd_DEPENDENCIES =
 am__attrib_gatttool_SOURCES_DIST = attrib/gatttool.c attrib/att.c \
        attrib/gatt.c attrib/gattrib.c btio/btio.c attrib/gatttool.h \
        attrib/interactive.c attrib/utils.c src/log.c client/display.c \
@@ -330,14 +341,15 @@ am__emulator_btvirt_SOURCES_DIST = emulator/main.c monitor/bt.h \
        monitor/mainloop.h monitor/mainloop.c emulator/server.h \
        emulator/server.c emulator/vhci.h emulator/vhci.c \
        emulator/btdev.h emulator/btdev.c emulator/bthost.h \
-       emulator/bthost.c
+       emulator/bthost.c emulator/amp.h emulator/amp.c
 @EXPERIMENTAL_TRUE@am_emulator_btvirt_OBJECTS =  \
 @EXPERIMENTAL_TRUE@    emulator/main.$(OBJEXT) \
 @EXPERIMENTAL_TRUE@    monitor/mainloop.$(OBJEXT) \
 @EXPERIMENTAL_TRUE@    emulator/server.$(OBJEXT) \
 @EXPERIMENTAL_TRUE@    emulator/vhci.$(OBJEXT) \
 @EXPERIMENTAL_TRUE@    emulator/btdev.$(OBJEXT) \
-@EXPERIMENTAL_TRUE@    emulator/bthost.$(OBJEXT)
+@EXPERIMENTAL_TRUE@    emulator/bthost.$(OBJEXT) \
+@EXPERIMENTAL_TRUE@    emulator/amp.$(OBJEXT)
 emulator_btvirt_OBJECTS = $(am_emulator_btvirt_OBJECTS)
 emulator_btvirt_LDADD = $(LDADD)
 am__monitor_btmon_SOURCES_DIST = monitor/main.c monitor/bt.h \
@@ -614,6 +626,10 @@ src_bluetoothd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
        $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
        $(src_bluetoothd_CFLAGS) $(CFLAGS) $(src_bluetoothd_LDFLAGS) \
        $(LDFLAGS) -o $@
+tools_amptest_SOURCES = tools/amptest.c
+tools_amptest_OBJECTS = tools/amptest.$(OBJEXT)
+@EXPERIMENTAL_TRUE@tools_amptest_DEPENDENCIES =  \
+@EXPERIMENTAL_TRUE@    lib/libbluetooth-internal.la
 tools_avinfo_SOURCES = tools/avinfo.c
 tools_avinfo_OBJECTS = tools/avinfo.$(OBJEXT)
 @EXPERIMENTAL_TRUE@tools_avinfo_DEPENDENCIES =  \
@@ -681,6 +697,13 @@ tools_btsnoop_LDADD = $(LDADD)
 tools_ciptool_SOURCES = tools/ciptool.c
 tools_ciptool_OBJECTS = tools/ciptool.$(OBJEXT)
 @TOOLS_TRUE@tools_ciptool_DEPENDENCIES = lib/libbluetooth-internal.la
+am__tools_cltest_SOURCES_DIST = tools/cltest.c monitor/mainloop.h \
+       monitor/mainloop.c
+@EXPERIMENTAL_TRUE@am_tools_cltest_OBJECTS = tools/cltest.$(OBJEXT) \
+@EXPERIMENTAL_TRUE@    monitor/mainloop.$(OBJEXT)
+tools_cltest_OBJECTS = $(am_tools_cltest_OBJECTS)
+@EXPERIMENTAL_TRUE@tools_cltest_DEPENDENCIES =  \
+@EXPERIMENTAL_TRUE@    lib/libbluetooth-internal.la
 am__tools_gap_tester_SOURCES_DIST = tools/gap-tester.c monitor/bt.h \
        emulator/btdev.h emulator/btdev.c emulator/bthost.h \
        emulator/bthost.c src/shared/hciemu.h src/shared/hciemu.c \
@@ -844,6 +867,13 @@ am__tools_obex_server_tool_SOURCES_DIST = gobex/gobex.h gobex/gobex.c \
 tools_obex_server_tool_OBJECTS = $(am_tools_obex_server_tool_OBJECTS)
 @READLINE_TRUE@tools_obex_server_tool_DEPENDENCIES =  \
 @READLINE_TRUE@        lib/libbluetooth-internal.la
+am__tools_obexctl_SOURCES_DIST = tools/obexctl.c client/display.h \
+       client/display.c
+@READLINE_TRUE@am_tools_obexctl_OBJECTS = tools/obexctl.$(OBJEXT) \
+@READLINE_TRUE@        client/display.$(OBJEXT)
+tools_obexctl_OBJECTS = $(am_tools_obexctl_OBJECTS)
+@READLINE_TRUE@tools_obexctl_DEPENDENCIES =  \
+@READLINE_TRUE@        gdbus/libgdbus-internal.la
 tools_rctest_SOURCES = tools/rctest.c
 tools_rctest_OBJECTS = tools/rctest.$(OBJEXT)
 @TOOLS_TRUE@tools_rctest_DEPENDENCIES = lib/libbluetooth-internal.la
@@ -957,18 +987,19 @@ SOURCES = $(profiles_sap_libsap_a_SOURCES) \
        $(lib_libbluetooth_internal_la_SOURCES) \
        $(lib_libbluetooth_la_SOURCES) \
        $(plugins_external_dummy_la_SOURCES) \
-       $(attrib_gatttool_SOURCES) $(client_bluetoothctl_SOURCES) \
-       $(emulator_b1ee_SOURCES) $(emulator_btvirt_SOURCES) \
-       $(monitor_btmon_SOURCES) $(obexd_src_obexd_SOURCES) \
-       $(nodist_obexd_src_obexd_SOURCES) \
+       $(android_bluetoothd_SOURCES) $(attrib_gatttool_SOURCES) \
+       $(client_bluetoothctl_SOURCES) $(emulator_b1ee_SOURCES) \
+       $(emulator_btvirt_SOURCES) $(monitor_btmon_SOURCES) \
+       $(obexd_src_obexd_SOURCES) $(nodist_obexd_src_obexd_SOURCES) \
        $(profiles_cups_bluetooth_SOURCES) \
        $(profiles_iap_iapd_SOURCES) $(src_bluetoothd_SOURCES) \
-       $(nodist_src_bluetoothd_SOURCES) tools/avinfo.c tools/avtest.c \
-       $(tools_bccmd_SOURCES) $(tools_bdaddr_SOURCES) \
-       $(tools_bluetooth_player_SOURCES) tools/btattach.c \
-       $(tools_btinfo_SOURCES) $(tools_btiotest_SOURCES) \
-       $(tools_btmgmt_SOURCES) $(tools_btsnoop_SOURCES) \
-       tools/ciptool.c $(tools_gap_tester_SOURCES) \
+       $(nodist_src_bluetoothd_SOURCES) tools/amptest.c \
+       tools/avinfo.c tools/avtest.c $(tools_bccmd_SOURCES) \
+       $(tools_bdaddr_SOURCES) $(tools_bluetooth_player_SOURCES) \
+       tools/btattach.c $(tools_btinfo_SOURCES) \
+       $(tools_btiotest_SOURCES) $(tools_btmgmt_SOURCES) \
+       $(tools_btsnoop_SOURCES) tools/ciptool.c \
+       $(tools_cltest_SOURCES) $(tools_gap_tester_SOURCES) \
        $(tools_hciattach_SOURCES) $(tools_hciconfig_SOURCES) \
        $(tools_hcidump_SOURCES) tools/hcieventmask.c \
        tools/hcisecfilter.c $(tools_hcitool_SOURCES) tools/hid2hci.c \
@@ -976,11 +1007,12 @@ SOURCES = $(profiles_sap_libsap_a_SOURCES) \
        tools/l2test.c $(tools_mgmt_tester_SOURCES) \
        $(tools_mpris_player_SOURCES) \
        $(tools_obex_client_tool_SOURCES) \
-       $(tools_obex_server_tool_SOURCES) tools/rctest.c \
-       tools/rfcomm.c $(tools_sco_tester_SOURCES) tools/scotest.c \
-       $(tools_sdptool_SOURCES) $(unit_test_crc_SOURCES) \
-       $(unit_test_eir_SOURCES) $(unit_test_gdbus_client_SOURCES) \
-       $(unit_test_gobex_SOURCES) $(unit_test_gobex_apparam_SOURCES) \
+       $(tools_obex_server_tool_SOURCES) $(tools_obexctl_SOURCES) \
+       tools/rctest.c tools/rfcomm.c $(tools_sco_tester_SOURCES) \
+       tools/scotest.c $(tools_sdptool_SOURCES) \
+       $(unit_test_crc_SOURCES) $(unit_test_eir_SOURCES) \
+       $(unit_test_gdbus_client_SOURCES) $(unit_test_gobex_SOURCES) \
+       $(unit_test_gobex_apparam_SOURCES) \
        $(unit_test_gobex_header_SOURCES) \
        $(unit_test_gobex_packet_SOURCES) \
        $(unit_test_gobex_transfer_SOURCES) $(unit_test_lib_SOURCES) \
@@ -991,6 +1023,7 @@ DIST_SOURCES = $(am__profiles_sap_libsap_a_SOURCES_DIST) \
        $(lib_libbluetooth_internal_la_SOURCES) \
        $(am__lib_libbluetooth_la_SOURCES_DIST) \
        $(am__plugins_external_dummy_la_SOURCES_DIST) \
+       $(am__android_bluetoothd_SOURCES_DIST) \
        $(am__attrib_gatttool_SOURCES_DIST) \
        $(am__client_bluetoothctl_SOURCES_DIST) \
        $(am__emulator_b1ee_SOURCES_DIST) \
@@ -999,14 +1032,15 @@ DIST_SOURCES = $(am__profiles_sap_libsap_a_SOURCES_DIST) \
        $(am__obexd_src_obexd_SOURCES_DIST) \
        $(am__profiles_cups_bluetooth_SOURCES_DIST) \
        $(am__profiles_iap_iapd_SOURCES_DIST) \
-       $(am__src_bluetoothd_SOURCES_DIST) tools/avinfo.c \
-       tools/avtest.c $(am__tools_bccmd_SOURCES_DIST) \
+       $(am__src_bluetoothd_SOURCES_DIST) tools/amptest.c \
+       tools/avinfo.c tools/avtest.c $(am__tools_bccmd_SOURCES_DIST) \
        $(am__tools_bdaddr_SOURCES_DIST) \
        $(am__tools_bluetooth_player_SOURCES_DIST) tools/btattach.c \
        $(am__tools_btinfo_SOURCES_DIST) \
        $(am__tools_btiotest_SOURCES_DIST) \
        $(am__tools_btmgmt_SOURCES_DIST) \
        $(am__tools_btsnoop_SOURCES_DIST) tools/ciptool.c \
+       $(am__tools_cltest_SOURCES_DIST) \
        $(am__tools_gap_tester_SOURCES_DIST) \
        $(am__tools_hciattach_SOURCES_DIST) \
        $(am__tools_hciconfig_SOURCES_DIST) \
@@ -1017,7 +1051,8 @@ DIST_SOURCES = $(am__profiles_sap_libsap_a_SOURCES_DIST) \
        tools/l2test.c $(am__tools_mgmt_tester_SOURCES_DIST) \
        $(am__tools_mpris_player_SOURCES_DIST) \
        $(am__tools_obex_client_tool_SOURCES_DIST) \
-       $(am__tools_obex_server_tool_SOURCES_DIST) tools/rctest.c \
+       $(am__tools_obex_server_tool_SOURCES_DIST) \
+       $(am__tools_obexctl_SOURCES_DIST) tools/rctest.c \
        tools/rfcomm.c $(am__tools_sco_tester_SOURCES_DIST) \
        tools/scotest.c $(am__tools_sdptool_SOURCES_DIST) \
        $(unit_test_crc_SOURCES) $(unit_test_eir_SOURCES) \
@@ -1224,13 +1259,14 @@ dist_man_MANS = $(am__append_17) $(am__append_19)
 dist_noinst_MANS = 
 CLEANFILES = $(builtin_files) src/bluetooth.service \
        obexd/src/builtin.h $(builtin_files) obexd/src/obex.service \
-       $(am__append_28)
+       $(am__append_29)
 EXTRA_DIST = src/bluetooth.service.in src/org.bluez.service \
        src/genbuiltin src/bluetooth.conf src/main.conf \
        profiles/network/network.conf profiles/input/input.conf \
        profiles/proximity/proximity.conf $(am__append_18) \
        $(am__append_20) $(am__append_21) obexd/src/obex.service.in \
        obexd/src/org.bluez.obex.service obexd/src/genbuiltin \
+       android/Android.mk android/log.c android/hal-ipc-api.txt \
        tools/hid2hci.rules $(test_scripts) doc/assigned-numbers.txt \
        doc/supported-features.txt doc/mgmt-api.txt \
        doc/adapter-api.txt doc/device-api.txt doc/agent-api.txt \
@@ -1267,7 +1303,7 @@ extra_sources = lib/uuid.c
 local_headers = $(foreach file,$(lib_headers), lib/bluetooth/$(notdir $(file)))
 BUILT_SOURCES = $(local_headers) src/builtin.h obexd/src/builtin.h
 @LIBRARY_TRUE@lib_libbluetooth_la_SOURCES = $(lib_headers) $(lib_sources)
-@LIBRARY_TRUE@lib_libbluetooth_la_LDFLAGS = $(AM_LDFLAGS) -version-info 20:0:17
+@LIBRARY_TRUE@lib_libbluetooth_la_LDFLAGS = $(AM_LDFLAGS) -version-info 20:1:17
 @LIBRARY_TRUE@lib_libbluetooth_la_DEPENDENCIES = $(local_headers)
 lib_libbluetooth_internal_la_SOURCES = $(lib_headers) $(lib_sources) \
                                        $(extra_headers) $(extra_sources)
@@ -1405,7 +1441,8 @@ test_scripts = test/sap_client.py test/bluezutils.py test/dbusdef.py \
 @EXPERIMENTAL_TRUE@                                    emulator/server.h emulator/server.c \
 @EXPERIMENTAL_TRUE@                                    emulator/vhci.h emulator/vhci.c \
 @EXPERIMENTAL_TRUE@                                    emulator/btdev.h emulator/btdev.c \
-@EXPERIMENTAL_TRUE@                                    emulator/bthost.h emulator/bthost.c
+@EXPERIMENTAL_TRUE@                                    emulator/bthost.h emulator/bthost.c \
+@EXPERIMENTAL_TRUE@                                    emulator/amp.h emulator/amp.c
 
 @EXPERIMENTAL_TRUE@emulator_b1ee_SOURCES = emulator/b1ee.c monitor/mainloop.h monitor/mainloop.c
 @EXPERIMENTAL_TRUE@tools_mgmt_tester_SOURCES = tools/mgmt-tester.c monitor/bt.h \
@@ -1502,8 +1539,9 @@ test_scripts = test/sap_client.py test/bluezutils.py test/dbusdef.py \
 @EXPERIMENTAL_TRUE@tools_avinfo_LDADD = lib/libbluetooth-internal.la
 @EXPERIMENTAL_TRUE@tools_avtest_LDADD = lib/libbluetooth-internal.la
 @EXPERIMENTAL_TRUE@tools_scotest_LDADD = lib/libbluetooth-internal.la
-@EXPERIMENTAL_TRUE@tools_hcieventmask_LDADD = lib/libbluetooth-internal.la
+@EXPERIMENTAL_TRUE@tools_amptest_LDADD = lib/libbluetooth-internal.la
 @EXPERIMENTAL_TRUE@tools_hwdb_LDADD = lib/libbluetooth-internal.la
+@EXPERIMENTAL_TRUE@tools_hcieventmask_LDADD = lib/libbluetooth-internal.la
 @EXPERIMENTAL_TRUE@tools_btmgmt_SOURCES = tools/btmgmt.c src/glib-helper.c src/eir.c \
 @EXPERIMENTAL_TRUE@                            src/shared/util.h src/shared/util.c \
 @EXPERIMENTAL_TRUE@                            src/shared/mgmt.h src/shared/mgmt.c
@@ -1518,6 +1556,8 @@ test_scripts = test/sap_client.py test/bluezutils.py test/dbusdef.py \
 @EXPERIMENTAL_TRUE@tools_btiotest_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 @EXPERIMENTAL_TRUE@tools_mpris_player_SOURCES = tools/mpris-player.c
 @EXPERIMENTAL_TRUE@tools_mpris_player_LDADD = gdbus/libgdbus-internal.la @GLIB_LIBS@ @DBUS_LIBS@
+@EXPERIMENTAL_TRUE@tools_cltest_SOURCES = tools/cltest.c monitor/mainloop.h monitor/mainloop.c
+@EXPERIMENTAL_TRUE@tools_cltest_LDADD = lib/libbluetooth-internal.la
 @READLINE_TRUE@attrib_gatttool_SOURCES = attrib/gatttool.c attrib/att.c attrib/gatt.c \
 @READLINE_TRUE@                                attrib/gattrib.c btio/btio.c \
 @READLINE_TRUE@                                attrib/gatttool.h attrib/interactive.c \
@@ -1541,6 +1581,12 @@ test_scripts = test/sap_client.py test/bluezutils.py test/dbusdef.py \
 @READLINE_TRUE@tools_bluetooth_player_LDADD = gdbus/libgdbus-internal.la \
 @READLINE_TRUE@                                @GLIB_LIBS@ @DBUS_LIBS@ -lreadline
 
+@READLINE_TRUE@tools_obexctl_SOURCES = tools/obexctl.c \
+@READLINE_TRUE@                                client/display.h client/display.c
+
+@READLINE_TRUE@tools_obexctl_LDADD = gdbus/libgdbus-internal.la \
+@READLINE_TRUE@                                @GLIB_LIBS@ @DBUS_LIBS@ -lreadline
+
 @EXPERIMENTAL_TRUE@profiles_iap_iapd_SOURCES = profiles/iap/main.c
 @EXPERIMENTAL_TRUE@profiles_iap_iapd_LDADD = gdbus/libgdbus-internal.la @GLIB_LIBS@ @DBUS_LIBS@
 @CUPS_TRUE@cupsdir = $(libdir)/cups/backend
@@ -1600,10 +1646,10 @@ obexd_src_obexd_LDADD = lib/libbluetooth-internal.la \
                        @ICAL_LIBS@ @DBUS_LIBS@ @GLIB_LIBS@ -ldl
 
 obexd_src_obexd_LDFLAGS = -Wl,--export-dynamic
-obexd_src_obexd_CFLAGS = @GLIB_CFLAGS@ @DBUS_CFLAGS@ @ICAL_CFLAGS@ \
-                                       -DOBEX_PLUGIN_BUILTIN \
-                                       -DPLUGINDIR=\""$(obex_plugindir)"\" \
-                                       -fPIC -D_FILE_OFFSET_BITS=64
+obexd_src_obexd_CFLAGS = $(AM_CFLAGS) @GLIB_CFLAGS@ @DBUS_CFLAGS@ \
+                               @ICAL_CFLAGS@ -DOBEX_PLUGIN_BUILTIN \
+                               -DPLUGINDIR=\""$(obex_plugindir)"\" \
+                               -fPIC -D_FILE_OFFSET_BITS=64
 
 obexd_src_obexd_CPPFLAGS = -I$(builddir)/lib -I$(builddir)/obexd/src  \
                                -I$(srcdir)/obexd/src -I$(srcdir)/btio \
@@ -1612,6 +1658,8 @@ obexd_src_obexd_CPPFLAGS = -I$(builddir)/lib -I$(builddir)/obexd/src  \
 obexd_src_obexd_SHORTNAME = obexd
 obexd_builtin_files = obexd/src/builtin.h $(obexd_builtin_nodist)
 nodist_obexd_src_obexd_SOURCES = $(obexd_builtin_files)
+@ANDROID_TRUE@android_bluetoothd_SOURCES = android/main.c src/log.c
+@ANDROID_TRUE@android_bluetoothd_LDADD = @GLIB_LIBS@
 @HID2HCI_TRUE@rulesdir = @UDEV_DIR@/rules.d
 @HID2HCI_TRUE@rules_DATA = tools/97-hid2hci.rules
 @TEST_TRUE@testdir = $(pkglibdir)/test
@@ -1672,7 +1720,8 @@ unit_test_lib_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 pkgconfigdir = $(libdir)/pkgconfig
 @LIBRARY_TRUE@pkgconfig_DATA = lib/bluez.pc
 DISTCHECK_CONFIGURE_FLAGS = --disable-datafiles --enable-library \
-                                       --disable-systemd --disable-udev
+                                       --disable-systemd --disable-udev \
+                                       --enable-android
 
 DISTCLEANFILES = $(pkgconfig_DATA)
 MAINTAINERCLEANFILES = Makefile.in \
@@ -1690,7 +1739,7 @@ all: $(BUILT_SOURCES) config.h
 .SUFFIXES: .c .lo .o .obj
 am--refresh: Makefile
        @:
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/Makefile.plugins $(srcdir)/Makefile.tools $(srcdir)/Makefile.obexd $(am__configure_deps)
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/Makefile.plugins $(srcdir)/Makefile.tools $(srcdir)/Makefile.obexd $(srcdir)/Makefile.android $(am__configure_deps)
        @for dep in $?; do \
          case '$(am__configure_deps)' in \
            *$$dep*) \
@@ -1713,7 +1762,7 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
            echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
            cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
        esac;
-$(srcdir)/Makefile.plugins $(srcdir)/Makefile.tools $(srcdir)/Makefile.obexd:
+$(srcdir)/Makefile.plugins $(srcdir)/Makefile.tools $(srcdir)/Makefile.obexd $(srcdir)/Makefile.android:
 
 $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
        $(SHELL) ./config.status --recheck
@@ -2061,6 +2110,24 @@ clean-udevPROGRAMS:
        list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
        echo " rm -f" $$list; \
        rm -f $$list
+android/$(am__dirstamp):
+       @$(MKDIR_P) android
+       @: > android/$(am__dirstamp)
+android/$(DEPDIR)/$(am__dirstamp):
+       @$(MKDIR_P) android/$(DEPDIR)
+       @: > android/$(DEPDIR)/$(am__dirstamp)
+android/main.$(OBJEXT): android/$(am__dirstamp) \
+       android/$(DEPDIR)/$(am__dirstamp)
+src/$(am__dirstamp):
+       @$(MKDIR_P) src
+       @: > src/$(am__dirstamp)
+src/$(DEPDIR)/$(am__dirstamp):
+       @$(MKDIR_P) src/$(DEPDIR)
+       @: > src/$(DEPDIR)/$(am__dirstamp)
+src/log.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
+android/bluetoothd$(EXEEXT): $(android_bluetoothd_OBJECTS) $(android_bluetoothd_DEPENDENCIES) $(EXTRA_android_bluetoothd_DEPENDENCIES) android/$(am__dirstamp)
+       @rm -f android/bluetoothd$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(android_bluetoothd_OBJECTS) $(android_bluetoothd_LDADD) $(LIBS)
 attrib/$(am__dirstamp):
        @$(MKDIR_P) attrib
        @: > attrib/$(am__dirstamp)
@@ -2087,13 +2154,6 @@ attrib/interactive.$(OBJEXT): attrib/$(am__dirstamp) \
        attrib/$(DEPDIR)/$(am__dirstamp)
 attrib/utils.$(OBJEXT): attrib/$(am__dirstamp) \
        attrib/$(DEPDIR)/$(am__dirstamp)
-src/$(am__dirstamp):
-       @$(MKDIR_P) src
-       @: > src/$(am__dirstamp)
-src/$(DEPDIR)/$(am__dirstamp):
-       @$(MKDIR_P) src/$(DEPDIR)
-       @: > src/$(DEPDIR)/$(am__dirstamp)
-src/log.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
 client/$(am__dirstamp):
        @$(MKDIR_P) client
        @: > client/$(am__dirstamp)
@@ -2143,6 +2203,8 @@ emulator/btdev.$(OBJEXT): emulator/$(am__dirstamp) \
        emulator/$(DEPDIR)/$(am__dirstamp)
 emulator/bthost.$(OBJEXT): emulator/$(am__dirstamp) \
        emulator/$(DEPDIR)/$(am__dirstamp)
+emulator/amp.$(OBJEXT): emulator/$(am__dirstamp) \
+       emulator/$(DEPDIR)/$(am__dirstamp)
 emulator/btvirt$(EXEEXT): $(emulator_btvirt_OBJECTS) $(emulator_btvirt_DEPENDENCIES) $(EXTRA_emulator_btvirt_DEPENDENCIES) emulator/$(am__dirstamp)
        @rm -f emulator/btvirt$(EXEEXT)
        $(AM_V_CCLD)$(LINK) $(emulator_btvirt_OBJECTS) $(emulator_btvirt_LDADD) $(LIBS)
@@ -2606,6 +2668,11 @@ tools/$(am__dirstamp):
 tools/$(DEPDIR)/$(am__dirstamp):
        @$(MKDIR_P) tools/$(DEPDIR)
        @: > tools/$(DEPDIR)/$(am__dirstamp)
+tools/amptest.$(OBJEXT): tools/$(am__dirstamp) \
+       tools/$(DEPDIR)/$(am__dirstamp)
+tools/amptest$(EXEEXT): $(tools_amptest_OBJECTS) $(tools_amptest_DEPENDENCIES) $(EXTRA_tools_amptest_DEPENDENCIES) tools/$(am__dirstamp)
+       @rm -f tools/amptest$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(tools_amptest_OBJECTS) $(tools_amptest_LDADD) $(LIBS)
 tools/avinfo.$(OBJEXT): tools/$(am__dirstamp) \
        tools/$(DEPDIR)/$(am__dirstamp)
 tools/avinfo$(EXEEXT): $(tools_avinfo_OBJECTS) $(tools_avinfo_DEPENDENCIES) $(EXTRA_tools_avinfo_DEPENDENCIES) tools/$(am__dirstamp)
@@ -2687,6 +2754,11 @@ tools/ciptool.$(OBJEXT): tools/$(am__dirstamp) \
 tools/ciptool$(EXEEXT): $(tools_ciptool_OBJECTS) $(tools_ciptool_DEPENDENCIES) $(EXTRA_tools_ciptool_DEPENDENCIES) tools/$(am__dirstamp)
        @rm -f tools/ciptool$(EXEEXT)
        $(AM_V_CCLD)$(LINK) $(tools_ciptool_OBJECTS) $(tools_ciptool_LDADD) $(LIBS)
+tools/cltest.$(OBJEXT): tools/$(am__dirstamp) \
+       tools/$(DEPDIR)/$(am__dirstamp)
+tools/cltest$(EXEEXT): $(tools_cltest_OBJECTS) $(tools_cltest_DEPENDENCIES) $(EXTRA_tools_cltest_DEPENDENCIES) tools/$(am__dirstamp)
+       @rm -f tools/cltest$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(tools_cltest_OBJECTS) $(tools_cltest_LDADD) $(LIBS)
 tools/gap-tester.$(OBJEXT): tools/$(am__dirstamp) \
        tools/$(DEPDIR)/$(am__dirstamp)
 src/shared/hciemu.$(OBJEXT): src/shared/$(am__dirstamp) \
@@ -2849,6 +2921,11 @@ tools/obex-server-tool.$(OBJEXT): tools/$(am__dirstamp) \
 tools/obex-server-tool$(EXEEXT): $(tools_obex_server_tool_OBJECTS) $(tools_obex_server_tool_DEPENDENCIES) $(EXTRA_tools_obex_server_tool_DEPENDENCIES) tools/$(am__dirstamp)
        @rm -f tools/obex-server-tool$(EXEEXT)
        $(AM_V_CCLD)$(LINK) $(tools_obex_server_tool_OBJECTS) $(tools_obex_server_tool_LDADD) $(LIBS)
+tools/obexctl.$(OBJEXT): tools/$(am__dirstamp) \
+       tools/$(DEPDIR)/$(am__dirstamp)
+tools/obexctl$(EXEEXT): $(tools_obexctl_OBJECTS) $(tools_obexctl_DEPENDENCIES) $(EXTRA_tools_obexctl_DEPENDENCIES) tools/$(am__dirstamp)
+       @rm -f tools/obexctl$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(tools_obexctl_OBJECTS) $(tools_obexctl_LDADD) $(LIBS)
 tools/rctest.$(OBJEXT): tools/$(am__dirstamp) \
        tools/$(DEPDIR)/$(am__dirstamp)
 tools/rctest$(EXEEXT): $(tools_rctest_OBJECTS) $(tools_rctest_DEPENDENCIES) $(EXTRA_tools_rctest_DEPENDENCIES) tools/$(am__dirstamp)
@@ -2995,6 +3072,7 @@ uninstall-testSCRIPTS:
 
 mostlyclean-compile:
        -rm -f *.$(OBJEXT)
+       -rm -f android/main.$(OBJEXT)
        -rm -f attrib/att.$(OBJEXT)
        -rm -f attrib/bluetoothd-att.$(OBJEXT)
        -rm -f attrib/bluetoothd-gatt-service.$(OBJEXT)
@@ -3011,6 +3089,7 @@ mostlyclean-compile:
        -rm -f client/agent.$(OBJEXT)
        -rm -f client/display.$(OBJEXT)
        -rm -f client/main.$(OBJEXT)
+       -rm -f emulator/amp.$(OBJEXT)
        -rm -f emulator/b1ee.$(OBJEXT)
        -rm -f emulator/btdev.$(OBJEXT)
        -rm -f emulator/bthost.$(OBJEXT)
@@ -3192,6 +3271,7 @@ mostlyclean-compile:
        -rm -f src/shared/tester.$(OBJEXT)
        -rm -f src/shared/util.$(OBJEXT)
        -rm -f src/textfile.$(OBJEXT)
+       -rm -f tools/amptest.$(OBJEXT)
        -rm -f tools/avinfo.$(OBJEXT)
        -rm -f tools/avtest.$(OBJEXT)
        -rm -f tools/bccmd.$(OBJEXT)
@@ -3203,6 +3283,7 @@ mostlyclean-compile:
        -rm -f tools/btmgmt.$(OBJEXT)
        -rm -f tools/btsnoop.$(OBJEXT)
        -rm -f tools/ciptool.$(OBJEXT)
+       -rm -f tools/cltest.$(OBJEXT)
        -rm -f tools/csr.$(OBJEXT)
        -rm -f tools/csr_3wire.$(OBJEXT)
        -rm -f tools/csr_bcsp.$(OBJEXT)
@@ -3231,6 +3312,7 @@ mostlyclean-compile:
        -rm -f tools/mpris-player.$(OBJEXT)
        -rm -f tools/obex-client-tool.$(OBJEXT)
        -rm -f tools/obex-server-tool.$(OBJEXT)
+       -rm -f tools/obexctl.$(OBJEXT)
        -rm -f tools/parser/amp.$(OBJEXT)
        -rm -f tools/parser/att.$(OBJEXT)
        -rm -f tools/parser/avctp.$(OBJEXT)
@@ -3279,6 +3361,7 @@ mostlyclean-compile:
 distclean-compile:
        -rm -f *.tab.c
 
+@AMDEP_TRUE@@am__include@ @am__quote@android/$(DEPDIR)/main.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@attrib/$(DEPDIR)/att.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@attrib/$(DEPDIR)/bluetoothd-att.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@attrib/$(DEPDIR)/bluetoothd-gatt-service.Po@am__quote@
@@ -3295,6 +3378,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/agent.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/display.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/amp.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/b1ee.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/btdev.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@emulator/$(DEPDIR)/bthost.Po@am__quote@
@@ -3466,6 +3550,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/pcap.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/tester.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/util.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/amptest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/avinfo.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/avtest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/bccmd.Po@am__quote@
@@ -3477,6 +3562,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/btmgmt.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/btsnoop.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/ciptool.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/cltest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/csr.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/csr_3wire.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/csr_bcsp.Po@am__quote@
@@ -3505,6 +3591,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/mpris-player.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/obex-client-tool.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/obex-server-tool.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/obexctl.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/rctest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/rfcomm.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/sco-tester.Po@am__quote@
@@ -5266,6 +5353,7 @@ mostlyclean-libtool:
 
 clean-libtool:
        -rm -rf .libs _libs
+       -rm -rf android/.libs android/_libs
        -rm -rf attrib/.libs attrib/_libs
        -rm -rf client/.libs client/_libs
        -rm -rf emulator/.libs emulator/_libs
@@ -5938,6 +6026,8 @@ clean-generic:
 distclean-generic:
        -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
        -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+       -rm -f android/$(DEPDIR)/$(am__dirstamp)
+       -rm -f android/$(am__dirstamp)
        -rm -f attrib/$(DEPDIR)/$(am__dirstamp)
        -rm -f attrib/$(am__dirstamp)
        -rm -f btio/$(DEPDIR)/$(am__dirstamp)
@@ -6021,7 +6111,7 @@ clean-am: clean-binPROGRAMS clean-cupsPROGRAMS clean-generic \
 
 distclean: distclean-am
        -rm -f $(am__CONFIG_DISTCLEAN_FILES)
-       -rm -rf attrib/$(DEPDIR) btio/$(DEPDIR) client/$(DEPDIR) emulator/$(DEPDIR) gdbus/$(DEPDIR) gobex/$(DEPDIR) lib/$(DEPDIR) monitor/$(DEPDIR) obexd/client/$(DEPDIR) obexd/plugins/$(DEPDIR) obexd/src/$(DEPDIR) plugins/$(DEPDIR) profiles/alert/$(DEPDIR) profiles/audio/$(DEPDIR) profiles/cups/$(DEPDIR) profiles/cyclingspeed/$(DEPDIR) profiles/deviceinfo/$(DEPDIR) profiles/gatt/$(DEPDIR) profiles/health/$(DEPDIR) profiles/heartrate/$(DEPDIR) profiles/iap/$(DEPDIR) profiles/input/$(DEPDIR) profiles/network/$(DEPDIR) profiles/proximity/$(DEPDIR) profiles/sap/$(DEPDIR) profiles/scanparam/$(DEPDIR) profiles/thermometer/$(DEPDIR) profiles/time/$(DEPDIR) src/$(DEPDIR) src/shared/$(DEPDIR) tools/$(DEPDIR) tools/parser/$(DEPDIR) unit/$(DEPDIR)
+       -rm -rf android/$(DEPDIR) attrib/$(DEPDIR) btio/$(DEPDIR) client/$(DEPDIR) emulator/$(DEPDIR) gdbus/$(DEPDIR) gobex/$(DEPDIR) lib/$(DEPDIR) monitor/$(DEPDIR) obexd/client/$(DEPDIR) obexd/plugins/$(DEPDIR) obexd/src/$(DEPDIR) plugins/$(DEPDIR) profiles/alert/$(DEPDIR) profiles/audio/$(DEPDIR) profiles/cups/$(DEPDIR) profiles/cyclingspeed/$(DEPDIR) profiles/deviceinfo/$(DEPDIR) profiles/gatt/$(DEPDIR) profiles/health/$(DEPDIR) profiles/heartrate/$(DEPDIR) profiles/iap/$(DEPDIR) profiles/input/$(DEPDIR) profiles/network/$(DEPDIR) profiles/proximity/$(DEPDIR) profiles/sap/$(DEPDIR) profiles/scanparam/$(DEPDIR) profiles/thermometer/$(DEPDIR) profiles/time/$(DEPDIR) src/$(DEPDIR) src/shared/$(DEPDIR) tools/$(DEPDIR) tools/parser/$(DEPDIR) unit/$(DEPDIR)
        -rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
        distclean-hdr distclean-libtool distclean-tags
@@ -6076,7 +6166,7 @@ installcheck-am:
 maintainer-clean: maintainer-clean-am
        -rm -f $(am__CONFIG_DISTCLEAN_FILES)
        -rm -rf $(top_srcdir)/autom4te.cache
-       -rm -rf attrib/$(DEPDIR) btio/$(DEPDIR) client/$(DEPDIR) emulator/$(DEPDIR) gdbus/$(DEPDIR) gobex/$(DEPDIR) lib/$(DEPDIR) monitor/$(DEPDIR) obexd/client/$(DEPDIR) obexd/plugins/$(DEPDIR) obexd/src/$(DEPDIR) plugins/$(DEPDIR) profiles/alert/$(DEPDIR) profiles/audio/$(DEPDIR) profiles/cups/$(DEPDIR) profiles/cyclingspeed/$(DEPDIR) profiles/deviceinfo/$(DEPDIR) profiles/gatt/$(DEPDIR) profiles/health/$(DEPDIR) profiles/heartrate/$(DEPDIR) profiles/iap/$(DEPDIR) profiles/input/$(DEPDIR) profiles/network/$(DEPDIR) profiles/proximity/$(DEPDIR) profiles/sap/$(DEPDIR) profiles/scanparam/$(DEPDIR) profiles/thermometer/$(DEPDIR) profiles/time/$(DEPDIR) src/$(DEPDIR) src/shared/$(DEPDIR) tools/$(DEPDIR) tools/parser/$(DEPDIR) unit/$(DEPDIR)
+       -rm -rf android/$(DEPDIR) attrib/$(DEPDIR) btio/$(DEPDIR) client/$(DEPDIR) emulator/$(DEPDIR) gdbus/$(DEPDIR) gobex/$(DEPDIR) lib/$(DEPDIR) monitor/$(DEPDIR) obexd/client/$(DEPDIR) obexd/plugins/$(DEPDIR) obexd/src/$(DEPDIR) plugins/$(DEPDIR) profiles/alert/$(DEPDIR) profiles/audio/$(DEPDIR) profiles/cups/$(DEPDIR) profiles/cyclingspeed/$(DEPDIR) profiles/deviceinfo/$(DEPDIR) profiles/gatt/$(DEPDIR) profiles/health/$(DEPDIR) profiles/heartrate/$(DEPDIR) profiles/iap/$(DEPDIR) profiles/input/$(DEPDIR) profiles/network/$(DEPDIR) profiles/proximity/$(DEPDIR) profiles/sap/$(DEPDIR) profiles/scanparam/$(DEPDIR) profiles/thermometer/$(DEPDIR) profiles/time/$(DEPDIR) src/$(DEPDIR) src/shared/$(DEPDIR) tools/$(DEPDIR) tools/parser/$(DEPDIR) unit/$(DEPDIR)
        -rm -f Makefile
 maintainer-clean-am: distclean-am maintainer-clean-generic
 
index 87bb62e8dec05f46fd6f54523464f874ba357410..840b95cbed4ffe024b3c86813a8ce6fbcaee80a4 100644 (file)
@@ -218,7 +218,7 @@ endif
 if READLINE
 noinst_PROGRAMS += attrib/gatttool \
                        tools/obex-client-tool tools/obex-server-tool \
-                       tools/bluetooth-player
+                       tools/bluetooth-player tools/obexctl
 
 attrib_gatttool_SOURCES = attrib/gatttool.c attrib/att.c attrib/gatt.c \
                                attrib/gattrib.c btio/btio.c \
@@ -240,6 +240,11 @@ tools_bluetooth_player_SOURCES = tools/bluetooth-player.c \
                                client/display.h client/display.c
 tools_bluetooth_player_LDADD = gdbus/libgdbus-internal.la \
                                @GLIB_LIBS@ @DBUS_LIBS@ -lreadline
+
+tools_obexctl_SOURCES = tools/obexctl.c \
+                               client/display.h client/display.c
+tools_obexctl_LDADD = gdbus/libgdbus-internal.la \
+                               @GLIB_LIBS@ @DBUS_LIBS@ -lreadline
 endif
 
 if EXPERIMENTAL
index ec820aca9502a85b5566234ab24f4945fb2fe92c..0e025acd810af250f7d5c9aaa4df13923379d86a 100644 (file)
@@ -29,3 +29,23 @@ LOCAL_SHARED_LIBRARIES := \
 LOCAL_MODULE := bluetoothd
 
 include $(BUILD_EXECUTABLE)
+
+#
+# bluetooth.default.so HAL
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+       hal_bluetooth.c \
+       hal_bt_sock.c \
+
+LOCAL_SHARED_LIBRARIES := \
+       libcutils \
+
+LOCAL_MODULE := bluetooth.default
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/android/hal-ipc-api.txt b/android/hal-ipc-api.txt
new file mode 100644 (file)
index 0000000..9a8b770
--- /dev/null
@@ -0,0 +1,1247 @@
+Android HAL protocol for Bluetooth
+==================================
+
+The Android HAL daemon for Bluetooth functionality implements the Unix socket
+server protocol around /run/bluetooth/daemon (tentative location) or Linux
+abstract sockets (tentative name).
+
+The daemon is single threaded and uses a mainloop for scheduling and general
+operation.
+
+The protocol is SOCK_SEQPACKET based and follows a strict PDU specification
+with a generic header and initial registration exchange. The communication
+is driven from the HAL with command/response exchanges. The daemon will use
+notification to signal events. The protocol is single PDU exchanged based,
+meaning every command requires a response. Notification does not require
+any confirmation. Not handling this PDU exchange leads to a disconnection of
+the socket.
+
+Command/response and notification use separate sockets. First connected socket
+is used for command/response, second for notification.  All services are
+multi-plexed over same pair of sockets. Separation is done to ease
+implementation of simple HAL library with dedicated thread for handling
+notification.
+
+This strict protocol requirement is done to match C based callbacks and
+callout functions that are running in a thread inside the HAL and might
+block.
+
+       .--Android--.                             .--Android--.
+       |  daemon   |                             |  HAL      |
+       |           |          Command            |           |
+       |           | <-------------------------- |           |
+       |           |                             |           |
+       |           | --------------------------> |           |
+       |           |          Response           |           |
+       |           |                             |           |
+       |           |                             |           |
+       |           |        Notification         |           |
+       |           | --------------------------> |           |
+       |           |                             |           |
+       '-----------'                             '-----------'
+
+Every packet will follow the basic header to support simple multi-plexing
+over the same socket. It will also support a basic control channel with service
+id 0.
+
+       0              8              16             24            31
+       +--------------+--------------+--------------+--------------+
+       | Service ID   | Opcode       | Data Length                 |
+       +--------------+--------------+-----------------------------+
+       |                                                           |
+
+The unique service ID is assigned by this specification for each HAL.
+
+As general rule of thumb, the opcode for command matches the opcode for a
+response. Or the opcode 0x00 for an error is returned.
+
+Notification opcodes start from 0x80.
+
+All command/response opcodes have the least significant bit not set. And all
+notifications have the least significant bit set.
+
+The HAL modules only have the job to map the callback and event functions
+to the protocol. They do not need to do anything else. Below is an example
+of a sample transaction for the Bluetooth Core HAL and enabling of an
+adapter.
+
+       HAL                                Daemon
+       ----------------------------------------------------
+
+       call enable()                  --> command 0x01
+       return enable()                <-- response 0x01
+
+       call adapter_state_changed()   <-- notification 0x81
+       return adapter_state_changed()
+
+When the Android hardware framework calls into the Bluetooth Core HAL
+and executes the enable() callback, the HAL module sends the enable
+command with opcode 0x01 to the daemon. As soon as the daemon responds,
+the callback will return with the appropriate result.
+
+After the daemon switched on the adapter, it will send a notification
+with opcode 0x81 to the HAL module.
+
+The Bluetooth Core HAL and Bluetooth Socket HAL are guaranteed to be
+available from the daemon. All other HAL modules are optional.
+
+When the Bluetooth Core HAL init() function is called, it should open
+the socket and register both "bluetooth" and "socket" service modules. It is
+required to register "socket" service at the same time since the HAL module
+does not have its own init() function.
+
+When new profiles are initiated, the get_profile_interface() callback
+will load the profile and during init() of the profile, it should register the
+specific service.
+
+       Bluetooth main thread       Daemon
+       -------------------------------------------------------
+
+       init()                  --> open command socket
+                               --> open notification socket
+                               --> register module "bluetooth"
+                               --> register module "socket"
+
+       get_profile_interface() --> return profile struct
+                               --> continue on Handsfree thread
+
+
+       Handsfree thread            Daemon
+       --------------------------------------------------------
+
+       init()                  --> register module handsfree
+
+
+Core Service (ID 0)
+===================
+
+       Opcode 0x00 - Error response
+
+               Response parameters: Error (1 octet)
+
+       Opcode 0x01 - Register module command/response
+
+               Command parameters: Service id (1 octet)
+               Response parameters: <none>
+
+               In case a command is sent for an undeclared service ID, it will
+               be rejected. Also there will be no notifications for undeclared
+               service ID.
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x02 - Unregister module command/response
+
+               Command parameters: Service id (1 octet)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+
+Bluetooth Core HAL (ID 1)
+=========================
+
+Android HAL name: "bluetooth" (BT_HARDWARE_MODULE_ID)
+
+Commands and responses:
+
+       Opcode 0x00 - Error response
+
+               Response parameters: Status (1 octet)
+
+       Opcode 0x01 - Enable command/response
+
+               Command parameters: <none>
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x02 - Disable command/response
+
+               Command parameters: <none>
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x03 - Get Adapter Properties command/response
+
+               Command parameters: <none>
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x04 - Get Adapter Property command/response
+
+               Command parameters: Property type (1 octet)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x05 - Set Adapter Property command/response
+
+               Command parameters: Property type (1 octet)
+                                   Property length (2 octets)
+                                   Property value (variable)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x06 - Get Remote Device Properties command/response
+
+               Command parameters: Remote address (6 octets)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x07 - Get Remote Device Property command/response
+
+               Command parameters: Remote address (6 octets)
+                                   Property type (1 octet)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x08 - Set Remote Device Property command/response
+
+               Command parameters: Remote address (6 octets)
+                                   Property type (1 octet)
+                                   Property length (2 octets)
+                                   Property value (variable)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x09 - Get Remote Service Record command/response
+
+               Command parameters: Remote address (6 octets)
+                                   UUID (16 octets)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x0a - Get Remote Services command/response
+
+               Command parameters: Remote address (6 octets)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x0b - Start Discovery command/response
+
+               Command parameters: <none>
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x0c - Cancel Discovery command/response
+
+               Command parameters: <none>
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x0d - Create Bond command/response
+
+               Command parameters: Remote address (6 octets)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x0e - Remove Bond command/response
+
+               Command parameters: Remote address (6 octets)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x0f - Cancel Bond command/response
+
+               Command parameters: Remote address (6 octets)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x10 - PIN Reply command/response
+
+               Command parameters: Remote address (6 octets)
+                                   Accept (1 octet)
+                                   PIN length (1 octet)
+                                   PIN code (16 octets)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x11 - SSP Reply command/response
+
+               Command parameters: Remote address (6 octets)
+                                   SSP variant (1 octet)
+                                   Accept (1 octet)
+                                   Passkey (4 octets)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x12 - DUT Mode Configure command/response
+
+               Command parameters: Enable (1 octet)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x13 - DUT Mode Send command/response
+
+               Command parameters: Opcode (2 octets)
+                                   Length (1 octet)
+                                   Data (variable)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x14 - LE Test Mode command/response
+
+               Command parameters: Opcode (2 octets)
+                                   Length (1 octet)
+                                   Data (variable)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+Notifications:
+
+       Opcode 0x81 - Adapter State Changed notification
+
+               Notifications parameters: State (1 octect)
+
+       Opcode 0x82 - Adapter Properties Changed notification
+
+               Notification parameters: Status (1 octect)
+                                        Num properties (1 octet)
+                                        Type[i] (1 octect)
+                                        Length[i] (2 octets)
+                                        Value[i] (variable)
+
+       Opcode 0x83 - Remote Device Properties notification
+
+               Notification parameters: Status (1 octect)
+                                        Remote address (6 octets)
+                                        Num properties (1 octet)
+                                        Type[i] (1 octect)
+                                        Length[i] (2 octets)
+                                        Value[i] (variable)
+
+       Opcode 0x84 - Device Found notification
+
+               Notification parameters: Num properties (1 octet)
+                                        Type[i] (1 octect)
+                                        Length[i] (2 octets)
+                                        Value[i] (variable)
+
+       Opcode 0x85 - Discovery State Changed notification
+
+               Notifications parameters: State (1 octect)
+
+       Opcode 0x86 - PIN Request notification
+
+               Notification parameters: Remote address (6 octets)
+                                        Remote name (249 octets)
+                                        Class of device (3 octets)
+
+       Opcode 0x87 - SSP Request notification
+
+               Notification parameters: Remote address (6 octets)
+                                        Remote name (249 octets)
+                                        Class of device (3 octets)
+                                        Pairing variant (1 octet)
+                                        Passkey (4 octets)
+
+       Opcode 0x88 - Bond State Changed notification
+
+               Notification parameters: Status (1 octect)
+                                        Remote address (6 octets)
+                                        Bond state (1 octet)
+
+       Opcode 0x89 - ACL State Changed notification
+
+               Notification parameters: Status (1 octect)
+                                        Remote address (6 octets)
+                                        ACL state (1 octet)
+
+       Opcode 0x8a - DUT Mode Receive notification
+
+               Notification parameters: Opcode (2 octects)
+                                        Length  (1 octet)
+                                        Data (variable)
+
+       Opcode 0x8b - LE Test Mode notification
+
+               Notification parameters: Status (1 octect)
+                                        Num packets (2 octets)
+
+
+Bluetooth Socket HAL (ID 2)
+===========================
+
+Android HAL name:: "socket" (BT_PROFILE_SOCKETS_ID)
+
+Commands and responses:
+
+       Opcode 0x00 - Error response
+
+               Response parameters: Status (1 octet)
+
+               Valid status values: 0x01 = Fail
+                                    0x02 = Not ready
+                                    0x03 = No memory
+                                    0x04 = Busy
+                                    0x05 = Done (already completed)
+                                    0x06 = Unsupported
+                                    0x07 = Parameter invalid
+                                    0x08 = Unhandled
+                                    0x09 = Authentication failure
+                                    0x0a = Remote device down
+
+       Opcode 0x01 - Listen command/response
+
+               Command parameters: Socket type (1 octet)
+                                   Service name (256 octets)
+                                   Service UUID (16 octets)
+                                   Channel (2 octets)
+                                   Socket flags (1 octet)
+               Response parameters: File descriptor (inline)
+
+               Valid socket types: 0x01 = RFCOMM
+                                   0x02 = SCO
+                                   0x03 = L2CAP
+
+               Valid socket flags: 0x01 = Encrypt
+                                   0x02 = Auth
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x02 - Connect command/response
+
+               Command parameters: Remote address (6 octets)
+                                   Socket type (1 octet)
+                                   Service UUID (16 octets)
+                                   Channel (2 octets)
+                                   Socket flags (1 octet)
+               Response parameters: File descriptor (inline)
+
+               Valid socket types: 0x01 = RFCOMM
+                                   0x02 = SCO
+                                   0x03 = L2CAP
+
+               Valid socket flags: 0x01 = Encrypt
+                                   0x02 = Auth
+
+               In case of an error, the error response will be returned.
+
+
+Bluetooth HID Host HAL (ID 3)
+============================
+
+Android HAL name: "hidhost" (BT_PROFILE_HIDHOST_ID)
+
+Commands and responses:
+
+       Opcode 0x00 - Error response
+
+               Response parameters: Status (1 octet)
+
+               Valid status values: 0x01 = Fail
+                                    0x02 = Not ready
+                                    0x03 = No memory
+                                    0x04 = Busy
+                                    0x05 = Done (already completed)
+                                    0x06 = Unsupported
+                                    0x07 = Parameter invalid
+                                    0x08 = Unhandled
+                                    0x09 = Authentication failure
+                                    0x0a = Remote device down
+
+       Opcode 0x01 - Connect command/response
+
+               Command parameters: Remote address (6 octets)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x02 - Disconnect command/response
+
+               Command parameters: Remote address (6 octets)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x03 - Virtual Unplug command/response
+
+               Command parameters: Remote address (6 octets)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x04 - Set Info command/response
+
+               Command parameters: Remote address (6 octets)
+                                   Attribute mask (2 octets)
+                                   Subclass (1 octet)
+                                   Application ID (1 octet)
+                                   Vendor ID (2 octets)
+                                   Product ID (2 octets)
+                                   Version (2 octets)
+                                   Country code (1 octet)
+                                   Descriptor length (2 octet)
+                                   Descriptor value (884 octets)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x05 - Get Protocol command/response
+
+               Command parameters: Remote address (6 octets)
+                                   Protocol mode (1 octet)
+               Response parameters: <none>
+
+               Valid protocol modes: 0x00 = Report
+                                     0x01 = Boot
+                                     0xff = Unsupported
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x06 - Set Protocol command/response
+
+               Command parameters: Remote address (6 octets)
+                                   Protocol mode (1 octet)
+               Response parameters: <none>
+
+               Valid protocol modes: 0x00 = Report
+                                     0x01 = Boot
+                                     0xff = Unsupported
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x07 - Get Report command/response
+
+               Command parameters: Remote address (6 octets)
+                                   Report type (1 octet)
+                                   Report ID (1 octet)
+                                   Buffer size (2 octet)
+               Response parameters: <none>
+
+               Valid report types: 0x01 = Input
+                                   0x02 = Output
+                                   0x03 = Feature
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x08 - Set Report command/response
+
+               Command parameters: Remote address (6 octets)
+                                   Report type (1 octet)
+                                   ...
+               Response parameters: <none>
+
+               Valid report types: 0x01 = Input
+                                   0x02 = Output
+                                   0x03 = Feature
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x09 - Send Data command/response
+
+               Command parameters: Remote address (6 octets)
+                                   ...
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+Notifications:
+
+       Opcode 0x81 - Connection State notification
+
+               Notification parameters: Remote address (6 octets)
+
+               Valid connection states: 0x00 = Connected
+                                        0x01 = Connecting
+                                        0x02 = Disconnected
+                                        0x03 = Disconnecting
+                                        0x04 = Failed - Mouse from host
+                                        0x05 = Failed - Keyboard from host
+                                        0x06 = Failed - Too many devices
+                                        0x07 = Failed - No HID driver
+                                        0x08 = Failed - generic
+                                        0x09 = Unknown
+
+       Opcode 0x82 - HID Info notification
+
+               Notification parameters: Remote address (6 octets)
+                                        Attribute mask (2 octets)
+                                        Subclass (1 octet)
+                                        Application ID (1 octet)
+                                        Vendor ID (2 octets)
+                                        Product ID (2 octets)
+                                        Version (2 octets)
+                                        Country code (1 octet)
+                                        Descriptor length (2 octet)
+                                        Descriptor value (884 octets)
+
+       Opcode 0x83 - Protocol Mode notification
+
+               Notification parameters: Remote address (6 octets)
+                                        Status (1 octet)
+                                        Protocol mode (1 octet)
+
+               Valid protocol modes: 0x00 = Report
+                                     0x01 = Boot
+                                     0xff = Unsupported
+
+       Opcode 0x84 - Idle Time notification
+
+               Notification parameters: Remote address (6 octets)
+                                        Status (1 octet)
+                                        Idle time (2 octets)
+
+       Opcode 0x85 - Get Report notification
+
+               Notification parameters: Remote address (6 octets)
+                                        Status (1 octet)
+                                        Report length (2 octets)
+                                        Report data (variable)
+
+       Opcode 0x86 - Virtual Unplug notification
+
+               Notification parameters: Remote address (6 octets)
+                                        Status (1 octet)
+
+               Valid status values: 0x00 = Ok
+                                    0x01 = Handshake - Device not ready
+                                    0x02 = Handshake - Invalid report ID
+                                    0x03 = Handshake - Transaction not SPT
+                                    0x04 = Handshake - Invalid parameter
+                                    0x05 = Handshake - Generic error
+                                    0x06 = General error
+                                    0x07 = SDP error
+                                    0x08 = Set protocol error
+                                    0x09 = Device database full
+                                    0x0a = Device type not supported
+                                    0x0b = No resources
+                                    0x0c = Authentication failed
+                                    0x0d = HDL
+
+
+Bluetooth PAN HAL (ID 4)
+========================
+
+Android HAL name: "pan" (BT_PROFILE_PAN_ID)
+
+Commands and responses:
+
+       Opcode 0x00 - Error response
+
+               Response parameters: Status (1 octet)
+
+               Valid status values: 0x01 = Fail
+                                    0x02 = Not ready
+                                    0x03 = No memory
+                                    0x04 = Busy
+                                    0x05 = Done (already completed)
+                                    0x06 = Unsupported
+                                    0x07 = Parameter invalid
+                                    0x08 = Unhandled
+                                    0x09 = Authentication failure
+                                    0x0a = Remote device down
+
+       Opcode 0x01 - Enable command/response
+
+               Command parameters: Local role (1 octet)
+               Response parameters: <none>
+
+               Valid role values: 0x00 = None
+                                  0x01 = NAP
+                                  0x02 = PANU
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x02 - Get Local Role command/response
+
+               Command parameters: <none>
+               Response parameters: Local role (1 octet)
+
+               Valid role values: 0x00 = None
+                                  0x01 = NAP
+                                  0x02 = PANU
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x03 - Connect command/response
+
+               Command parameters: Remote address (6 octets)
+                                   Local role (1 octet)
+                                   Remote role (1 octet)
+               Response parameters: <none>
+
+               Valid role values: 0x01 = NAP
+                                  0x02 = PANU
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x04 - Disconnect command/response
+
+               Command parameters: Remote address (6 octets)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+Notifications:
+
+       Opcode 0x81 - Control State notification
+
+               Notification parameters: Control state (1 octect)
+                                        Status (1 octet)
+                                        Local role (1 octet)
+                                        Interface name (17 octet)
+
+               Valid control states: 0x00 = Enabled
+                                     0x01 = Disabled
+
+               Valid role values: 0x00 = None
+                                  0x01 = NAP
+                                  0x02 = PANU
+
+       Opcode 0x82 - Connection State notification
+
+               Notification parameters: Connection state (1 octect)
+                                        Status (1 octet)
+                                        Remote address (6 octets)
+                                        Local role (1 octet)
+                                        Remote role (1 octet)
+
+               Valid connection states: 0x00 = Connected
+                                        0x01 = Connecting
+                                        0x02 = Disconnected
+                                        0x03 = Disconnecting
+
+               Valid role values: 0x01 = NAP
+                                  0x02 = PANU
+
+
+Bluetooth Handsfree HAL (ID 5)
+==============================
+
+Android HAL name: "handsfree" (BT_PROFILE_HANDSFREE_ID)
+
+       Opcode 0x00 - Error response
+
+               Response parameters: Status (1 octet)
+
+               Valid status values: 0x01 = Fail
+                                    0x02 = Not ready
+                                    0x03 = No memory
+                                    0x04 = Busy
+                                    0x05 = Done (already completed)
+                                    0x06 = Unsupported
+                                    0x07 = Parameter invalid
+                                    0x08 = Unhandled
+                                    0x09 = Authentication failure
+                                    0x0a = Remote device down
+
+       Opcode 0x01 - Connect command/response
+
+               Command parameters: Remote address (6 octets)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x02 - Disconnect command/response
+
+               Command parameters: Remote address (6 octets)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x03 - Connect Audio command/response
+
+               Command parameters: Remote address (6 octets)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x04 - Disconnect Audio command/response
+
+               Command parameters: Remote address (6 octets)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x05 - Start Voice Recognition command/response
+
+               Command parameters: <none>
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x06 - Stop Voice Recognition command/response
+
+               Command parameters: <none>
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x07 - Volume Control command/response
+
+               Command parameters: Volume type (1 octet)
+                                   Volume (1 octet)
+               Response parameters: <none>
+
+               Valid volume types: 0x00 = Speaker
+                                   0x01 = Microphone
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x08 - Device Status Notification command/response
+
+               Command parameters: Network state (1 octet)
+                                   Service type (1 octet)
+                                   Signal strength (1 octet)
+                                   Battery level (1 octet)
+               Response parameters: <none>
+
+               Valid network states: 0x00 = Not available
+                                     0x01 = Available
+
+               Valid service types: 0x00 = Home network
+                                    0x01 = Roaming network
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x09 - COPS Response command/response
+
+               Command parameters: COPS command response (string)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x0a - CIND Response command/response
+
+               Command parameters: Service (1 octet)
+                                   Number of active calls (1 octet)
+                                   Number of held calls (1 octet)
+                                   Call setup state (1 octet)
+                                   Signal strength (1 octet)
+                                   Roaming indicator (1 octet)
+                                   Battery level (1 octet)
+               Response parameters: <none>
+
+               Valid call setup states: 0x00 = Active
+                                        0x01 = Held
+                                        0x02 = Dialing
+                                        0x03 = Alerting
+                                        0x04 = Incoming
+                                        0x05 = Waiting
+                                        0x06 = Idle
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x0b - Formatted AT Response command/response
+
+               Command parameters: Pre-formatted AT response (string)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x0c - AT Response command/response
+
+               Command parameters: Response code (1 octet)
+                                   Error code (1 octet)
+               Response parameters: <none>
+
+               Valid response codes: 0x00 = ERROR
+                                     0x01 = OK
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x0d - CLCC Response command/response
+
+               Command parameters: Call index (1 octet)
+                                   Call direction (1 octet)
+                                   Call state (1 octet)
+                                   Call mode (1 octet)
+                                   Call multiparty type (1 octet)
+                                   Call number type (1 octet)
+                                   Call number (variable)
+               Response parameters: <none>
+
+               Valid call directions: 0x00 = Outgoing
+                                      0x01 = Incoming
+
+               Valid call states: 0x00 = Active
+                                  0x01 = Held
+                                  0x02 = Dialing
+                                  0x03 = Alerting
+                                  0x04 = Incoming
+                                  0x05 = Waiting
+                                  0x06 = Idle
+
+               Valid call modes: 0x00 = Voice
+                                 0x01 = Data
+                                 0x02 = Fax
+
+               Valid multiparty types: 0x00 = Single call
+                                       0x01 = Multiparty call
+
+               Valid number types: 0x81 = Unknown
+                                   0x91 = International
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x0e - Phone Status Change command/response
+
+               Command parameters: Number of active calls (1 octet)
+                                   Number of held calls (1 octet)
+                                   Call setup state (1 octet)
+                                   Call number type (1 octet)
+                                   Call number (variable)
+               Response parameters: <none>
+
+               Valid call setup states: 0x00 = Active
+                                        0x01 = Held
+                                        0x02 = Dialing
+                                        0x03 = Alerting
+                                        0x04 = Incoming
+                                        0x05 = Waiting
+                                        0x06 = Idle
+
+               Valid number types: 0x81 = Unknown
+                                   0x91 = International
+
+               In case of an error, the error response will be returned.
+
+Notifications:
+
+       Opcode 0x81 - Connection State notification
+
+               Notification parameters: Connection state (1 octect)
+                                        Remote address (6 octets)
+
+               Valid connection states: 0x00 = Disconnected
+                                        0x01 = Connecting
+                                        0x02 = Connected
+                                        0x03 = SLC connected
+                                        0x04 = Disconnecting
+
+       Opcode 0x82 - Audio State notification
+
+               Notification parameters: Audio state (1 octect)
+                                        Remote address (6 octets)
+
+               Valid audio states: 0x00 = Disconnected
+                                   0x01 = Connecting
+                                   0x02 = Connected
+                                   0x03 = Disconnecting
+
+       Opcode 0x83 - Voice Recognition Command notification
+
+               Notification parameters: Voice recognition state (1 octet)
+
+               Valid voice recognition states: 0x00 = Stopped
+                                               0x01 = Started
+
+       Opcode 0x84 - Answer Call Command notification
+
+               Notification parameters: <none>
+
+       Opcode 0x85 - Hangup Call Command notification
+
+               Notification parameters: <none>
+
+       Opcode 0x86 - Volume Command notification
+
+               Notification parameters: Volume type (1 octet)
+
+               Valid volume types: 0x00 = Speaker
+                                   0x01 = Microphone
+
+       Opcode 0x87 - Dial Call Command notification
+
+               Notification parameters: Number (string)
+
+       Opcode 0x88 - DTMF Command notification
+
+               Notification parameters: Tone (1 octet)
+
+       Opcode 0x89 - NREC Command notification
+
+               Notification parameters: NREC types (1 octet)
+
+               Valid NREC types: 0x00 = Stop
+                                 0x01 = Start
+
+       Opcode 0x8a - CHLD Command notification
+
+               Notification parameters: NREC types (1 octet)
+
+               Valid CHLD types: 0x00 = Release and hold
+                                 0x01 = Release active and accept held
+                                 0x02 = Hold active and accept held
+                                 0x03 = Add held call to conference
+
+       Opcode 0x8b - CNUM Command notification
+
+               Notification parameters: <none>
+
+       Opcode 0x8c - CIND Command notification
+
+               Notification parameters: <none>
+
+       Opcode 0x8d - COPS Command notification
+
+               Notification parameters: <none>
+
+       Opcode 0x8e - CLCC Command notification
+
+               Notification parameters: <none>
+
+       Opcode 0x8f - Unknown AT Command notification
+
+               Notification parameters: AT command (string)
+
+       Opcode 0x90 - Key Pressed Command notification
+
+               Notification parameters: <none>
+
+
+Bluetooth Advanced Audio HAL (ID 6)
+===================================
+
+Android HAL name: "ad2p" (BT_PROFILE_ADVANCED_AUDIO_ID)
+
+Commands and responses:
+
+       Opcode 0x00 - Error response
+
+               Response parameters: Status (1 octet)
+
+               Valid status values: 0x01 = Fail
+                                    0x02 = Not ready
+                                    0x03 = No memory
+                                    0x04 = Busy
+                                    0x05 = Done (already completed)
+                                    0x06 = Unsupported
+                                    0x07 = Parameter invalid
+                                    0x08 = Unhandled
+                                    0x09 = Authentication failure
+                                    0x0a = Remote device down
+
+       Opcode 0x01 - Connect command/response
+
+               Command parameters: Remote address (6 octets)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x02 - Disconnect command/response
+
+               Command parameters: Remote address (6 octets)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+Notifications:
+
+       Opcode 0x81 - Connection State notification
+
+               Notification parameters: Connection state (1 octect)
+                                        Remote address (6 octets)
+
+               Valid connection states: 0x00 = Disconnected
+                                        0x01 = Connecting
+                                        0x02 = Connected
+                                        0x03 = Disconnecting
+
+       Opcode 0x82 - Audio State notification
+
+               Notification parameters: Audio state (1 octect)
+                                        Remote address (6 octets)
+
+               Valid connection states: 0x00 = Remote suspend
+                                        0x01 = Stopped
+                                        0x02 = Started
+
+
+Bluetooth Health HAL (ID 7)
+===========================
+
+Android HAL name: "health" (BT_PROFILE_HEALTH_ID)
+
+       Opcode 0x00 - Error response
+
+               Response parameters: Status (1 octet)
+
+               Valid status values: 0x01 = Fail
+                                    0x02 = Not ready
+                                    0x03 = No memory
+                                    0x04 = Busy
+                                    0x05 = Done (already completed)
+                                    0x06 = Unsupported
+                                    0x07 = Parameter invalid
+                                    0x08 = Unhandled
+                                    0x09 = Authentication failure
+                                    0x0a = Remote device down
+
+       Opcode 0x01 - Register Application command/response
+
+               Command parameters: Application name (string)
+                                   Provider name (string)
+                                   Service name (string)
+                                   Service description (string)
+                                   Number of MDEP (1 octet)
+                                   MDEP Role[i] (1 octet)
+                                   Data type[i] (1 octet)
+                                   Channel type[i] (1 octet)
+                                   MDEP description (string)
+               Response parameters: Application ID (2 octets)
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x02 - Unregister Application command/response
+
+               Command parameters: Application ID (2 octets)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x03 - Connect Channel command/response
+
+               Command parameters: Application ID (2 octets)
+                                   Remote address (6 octets)
+                                   MDEP index (1 octet)
+               Response parameters: Channel ID (2 octets)
+
+               In case of an error, the error response will be returned.
+
+       Opcode 0x04 - Destroy Channel command/response
+
+               Command parameters: Channel ID (2 octets)
+               Response parameters: <none>
+
+               In case of an error, the error response will be returned.
+
+Notifications:
+
+       Opcode 0x81 - Application Registration State notification
+
+               Notification parameters: Application ID (2 octects)
+                                        Application state (1 octet)
+
+               Valid application states: 0x00 = Registration success
+                                         0x01 = Registration failed
+                                         0x02 = Deregistration success
+                                         0x03 = Deregistration failed
+
+       Opcode 0x82 - Channel State notification
+
+               Notification parameters: Application ID (2 octects)
+                                        Remote address (6 octets)
+                                        MDEP index (1 octet)
+                                        Channel ID (2 octets)
+                                        Channel state (1 octet)
+                                        File descriptor (inline)
+
+               Valid channel states: 0x00 = Connecting
+                                     0x01 = Connected
+                                     0x02 = Disconnecting
+                                     0x03 = Disconnected
+                                     0x04 = Destroyed
+
+
+Bluetooth Remote Control HAL (ID 8)
+===================================
+
+Android HAL name: "avrcp" (BT_PROFILE_AV_RC_ID)
+
+       Opcode 0x00 - Error response
+       Opcode 0x01 - Get Play Status command/response
+       Opcode 0x02 - List Player Application Attributes command/response
+       Opcode 0x03 - List Player Application Values command/response
+       Opcode 0x04 - Get Player Application Values command/response
+       Opcode 0x05 - Get Player Application Attributes Text command/response
+       Opcode 0x06 - Get Player Application Values Text command/response
+       Opcode 0x07 - Get Element Attributes Text command/response
+       Opcode 0x08 - Set Player Attributes Value command/response
+       Opcode 0x09 - Register Notification command/response
+
+       Opcode 0x81 - Get Play Status notification
+       Opcode 0x82 - List Player Application Attributes notification
+       ...
+
+
+Bluetooth GATT HAL (ID 9)
+=========================
+
+Android HAL name: "gatt" (BT_PROFILE_GATT_ID)
+
+       Opcode 0x00 - Error response
+       Opcode 0x01 - Register Client command/response
+       Opcode 0x02 - Unregister Client command/response
+       Opcode 0x03 - Scan command/response
+       Opcode 0x04 - Connect Device command/response
+       Opcode 0x05 - Disconnect Device command/response
+       Opcode 0x06 - Refresh command/response
+       Opcode 0x07 - Search Service command/response
+       Opcode 0x08 - Get Included Service command/response
+       Opcode 0x09 - Get Characteristic command/response
+       Opcode 0x0a - Get Descriptor command/response
+       Opcode 0x0b - Read Characteristic command/response
+       Opcode 0x0c - Write Characteristic command/response
+       Opcode 0x0d - Read Descriptor command/response
+       Opcode 0x0e - Write Descriptor command/response
+       Opcode 0x0f - Execute Write command/response
+       Opcode 0x10 - Register For Notification command/response
+       Opcode 0x11 - Deregister For Notification command/response
+       Opcode 0x12 - Read Remote RSSI command/response
+       Opcode 0x13 - Get Device Type command/response
+       Opcode 0x14 - Test Command command/response
+       Opcode 0x15 - Register Server command/response
+       Opcode 0x16 - Unregister Server command/response
+       Opcode 0x17 - Connect Peripheral command/response
+       Opcode 0x18 - Disconnect Peripheral command/response
+       Opcode 0x19 - Add Service command/response
+       Opcode 0x1a - Add Included Service command/response
+       Opcode 0x1b - Add Characteristic command/response
+       Opcode 0x1c - Add Descriptor command/response
+       Opcode 0x1d - Start Service command/response
+       Opcode 0x1e - Stop Service command/response
+       Opcode 0x1f - Delete Service command/response
+       Opcode 0x20 - Send Indication command/response
+       Opcode 0x21 - Send Response command/response
+
+       Opcode 0x81 - Register Client notification
+       Opcode 0x82 - Scan Result notification
+       Opcode 0x83 - Connect Device notification
+       Opcode 0x84 - Disconnect Device notification
+       Opcode 0x85 - Search Complete notification
+       Opcode 0x86 - Search Result notification
+       Opcode 0x87 - Get Characteristic notification
+       Opcode 0x88 - Get Descriptor notification
+       Opcode 0x89 - Get Included Service notification
+       Opcode 0x8a - Register For Notification notification
+       Opcode 0x8b - Notify notification
+       Opcode 0x8c - Read Characteristic notification
+       Opcode 0x8d - Write Characteristic notification
+       Opcode 0x8e - Execute Write notification
+       Opcode 0x8f - Read Descriptor notification
+       Opcode 0x90 - Write Descriptor notification
+       Opcode 0x91 - Read Remote RSSI notification
+       Opcode 0x92 - Register Server notification
+       Opcode 0x93 - Connection notification
+       Opcode 0x94 - Service Added notification
+       Opcode 0x95 - Included Service Added notification
+       Opcode 0x96 - Characteristic Added notification
+       Opcode 0x97 - Descriptor Added notification
+       Opcode 0x98 - Service Started notification
+       Opcode 0x99 - Service Stopped notification
+       Opcode 0x9a - Service Deleted notification
+       Opcode 0x9b - Request Read notification
+       Opcode 0x9c - Request Write notification
+       Opcode 0x9d - Request Execute Write notification
+       Opcode 0x9e - Response Confirmation notification
diff --git a/bluez.pc.in b/bluez.pc.in
deleted file mode 100644 (file)
index 3d6e596..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-Name: BlueZ
-Description: Bluetooth protocol stack for Linux
-Version: @VERSION@
-Libs: -L${libdir} -lbluetooth
-Cflags: -I${includedir}
index 26a2e354688e6c2e9d6775a56e3915d695f80da3..2bb5b0f5abec7f1b3036c74df86cd72cc4410a44 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for bluez 5.9.
+# Generated by GNU Autoconf 2.69 for bluez 5.10.
 #
 #
 # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -587,8 +587,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='bluez'
 PACKAGE_TARNAME='bluez'
-PACKAGE_VERSION='5.9'
-PACKAGE_STRING='bluez 5.9'
+PACKAGE_VERSION='5.10'
+PACKAGE_STRING='bluez 5.10'
 PACKAGE_BUGREPORT=''
 PACKAGE_URL=''
 
@@ -633,6 +633,8 @@ ac_subst_vars='am__EXEEXT_FALSE
 am__EXEEXT_TRUE
 LTLIBOBJS
 LIBOBJS
+ANDROID_FALSE
+ANDROID_TRUE
 CONFIGDIR
 EXPERIMENTAL_FALSE
 EXPERIMENTAL_TRUE
@@ -831,6 +833,7 @@ with_systemdsystemunitdir
 with_systemduserunitdir
 enable_datafiles
 enable_experimental
+enable_android
 '
       ac_precious_vars='build_alias
 host_alias
@@ -1394,7 +1397,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures bluez 5.9 to adapt to many kinds of systems.
+\`configure' configures bluez 5.10 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1464,7 +1467,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of bluez 5.9:";;
+     short | recursive ) echo "Configuration of bluez 5.10:";;
    esac
   cat <<\_ACEOF
 
@@ -1498,6 +1501,7 @@ Optional Features:
   --disable-systemd       disable systemd integration
   --disable-datafiles     do not install configuration and data files
   --enable-experimental   enable experimental plugins (SAP, NFC, ...)
+  --enable-android        enable BlueZ for Android
 
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
@@ -1611,7 +1615,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-bluez configure 5.9
+bluez configure 5.10
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1976,7 +1980,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by bluez $as_me 5.9, which was
+It was created by bluez $as_me 5.10, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2831,7 +2835,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='bluez'
- VERSION='5.9'
+ VERSION='5.10'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -13589,6 +13593,20 @@ _ACEOF
 CONFIGDIR="${configdir}"
 
 
+# Check whether --enable-android was given.
+if test "${enable_android+set}" = set; then :
+  enableval=$enable_android; enable_android=${enableval}
+fi
+
+ if test "${enable_android}" = "yes"; then
+  ANDROID_TRUE=
+  ANDROID_FALSE='#'
+else
+  ANDROID_TRUE='#'
+  ANDROID_FALSE=
+fi
+
+
 ac_config_files="$ac_config_files Makefile src/bluetoothd.8 lib/bluez.pc"
 
 cat >confcache <<\_ACEOF
@@ -13776,6 +13794,10 @@ if test -z "${EXPERIMENTAL_TRUE}" && test -z "${EXPERIMENTAL_FALSE}"; then
   as_fn_error $? "conditional \"EXPERIMENTAL\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${ANDROID_TRUE}" && test -z "${ANDROID_FALSE}"; then
+  as_fn_error $? "conditional \"ANDROID\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 
 : "${CONFIG_STATUS=./config.status}"
 ac_write_fail=0
@@ -14173,7 +14195,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by bluez $as_me 5.9, which was
+This file was extended by bluez $as_me 5.10, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -14239,7 +14261,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-bluez config.status 5.9
+bluez config.status 5.10
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
index 7b1f64aa812f224692fb776ab708b4aa9f7920be..b4d3998de00b8d63029d3dcf17156ca3385b9770 100644 (file)
@@ -1,5 +1,5 @@
 AC_PREREQ(2.60)
-AC_INIT(bluez, 5.9)
+AC_INIT(bluez, 5.10)
 
 AM_INIT_AUTOMAKE([foreign subdir-objects color-tests silent-rules
                                        tar-pax no-dist-gzip dist-xz])
diff --git a/doc/input-api.txt b/doc/input-api.txt
deleted file mode 100644 (file)
index 67da08b..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-BlueZ D-Bus Input API description
-*********************************
-
-Input hierarchy
-===============
-
-Service                org.bluez
-Interface      org.bluez.Input1
-Object path    [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
-
-Properties     string ReconnectMode [readonly]
-
-                       Determines the Connectability mode of the HID device as
-                       defined by the HID Profile specification, Section 5.4.2.
-
-                       This mode is based in the two properties
-                       HIDReconnectInitiate (see Section 5.3.4.6) and
-                       HIDNormallyConnectable (see Section 5.3.4.14) which
-                       define the following four possible values:
-
-                       "none"          Device and host are not required to
-                                       automatically restore the connection.
-
-                       "host"          Bluetooth HID host restores connection.
-
-                       "device"        Bluetooth HID device restores
-                                       connection.
-
-                       "any"           Bluetooth HID device shall attempt to
-                                       restore the lost connection, but
-                                       Bluetooth HID Host may also restore the
-                                       connection.
index c15904946d2f02521eae746b66b55464a72749f5..371f25298e2b5719c928e54b4a483af4840c90d6 100644 (file)
@@ -237,11 +237,17 @@ Set Discoverable Command
 
        This command is used to set the discoverable property of a
        controller. The allowed Discoverable command parameter values
-       are 0x00 and 0x01. All other values will return Invalid Parameters.
+       are 0x00, 0x01 and 0x02. All other values will return Invalid
+       Parameters.
 
        Timeout is the time in seconds and is only meaningful when
-       Discoverable is set to 0x01. Providing a timeout with 0x00 will
-       return Invalid Parameters.
+       Discoverable is set to 0x01 or 0x02. Providing a timeout
+       with 0x00 return Invalid Parameters. For 0x02, the timeout
+       value is required.
+
+       The value 0x00 disables discoverable, the value 0x01 enables
+       general discoverable and the value 0x02 enables limited
+       discoverable.
 
        This command is only available for BR/EDR capable controllers
        (e.g. not for single-mode LE ones). It will return Not Supported
@@ -279,9 +285,13 @@ Set Connectable Command
        controller. The allowed Connectable command parameter values are
        0x00 and 0x01. All other values will return Invalid Parameters.
 
-       This command is only available for BR/EDR capable controllers
-       (e.g. not for single-mode LE ones). It will return Not Supported
-       otherwise.
+       This command is available for BR/EDR, LE-only and also dual
+       mode controllers. For BR/EDR is changes the page scan setting
+       and for LE controllers it changes the advertising type. For
+       dual mode controllers it affects both settings.
+
+       For LE capable controllers the connectable setting only takes
+       affect when advertising is enabled.
 
        This command can be used when the controller is not powered and
        all settings will be programmed once powered.
@@ -1238,7 +1248,7 @@ Set Advertising Command
 
        Command Code:           0x0029
        Controller Index:       <controller id>
-       Command Parameters      Advertising (1 Octet)
+       Command Parameters:     Advertising (1 Octet)
        Return Parameters:      Current_Settings (4 Octets)
 
        This command is used to enable LE advertising on a controller
@@ -1264,7 +1274,7 @@ Set BR/EDR Command
 
        Command Code:           0x002A
        Controller Index:       <controller id>
-       Command Parameters      BR/EDR (1 Octet)
+       Command Parameters:     BR/EDR (1 Octet)
        Return Parameters:      Current_Settings (4 Octets)
 
        This command is used to enable or disable BR/EDR support
@@ -1294,7 +1304,7 @@ Set Static Address Command
 
        Command Code:           0x002B
        Controller Index:       <controller id>
-       Command Parameters      Address (6 Octets)
+       Command Parameters:     Address (6 Octets)
        Return Parameters:
 
        This command allows for setting the static random address. It is
@@ -1316,6 +1326,28 @@ Set Static Address Command
                                Invalid Index
 
 
+Set Scan Parameters Command
+===========================
+
+       Command Code:           0x002C
+       Controller Index:       <controller id>
+       Command Parameters:     Interval (2 Octets)
+                               Window (2 Octets)
+       Return Parameters:
+
+       This command allows for setting the Low Energy scan parameters
+       used for connection establishment and passive scanning. It is
+       only supported on controllers with LE support.
+
+       This command generates a Command Complete event on success or a
+       Command Status event on failure.
+
+       Possible errors:        Rejected
+                               Not Supported
+                               Invalid Parameters
+                               Invalid Index
+
+
 Command Complete Event
 ======================
 
diff --git a/doc/settings-storage.txt b/doc/settings-storage.txt
deleted file mode 100644 (file)
index a3b58e6..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-BlueZ settings storage
-**********************
-
-Purpose
-=======
-
-The purpose of this document is to describe the directory structure of
-BlueZ settings storage. In effect, this document will serve as the primary,
-up to date source of BlueZ storage information.
-
-It is intended as reference for developers. Direct access to the storage
-outside from bluetoothd is highly discouraged.
-
-Adapter and remote device info are read form the storage during object
-initialization. Write to storage is performed immediately on every value
-change.
-
-Default storage directory is /var/lib/bluetooth. This can be adjusted
-by the --localstatedir configure switch. Default is --localstatedir=/var.
-
-All files are in ini-file format.
-
-
-Storage directory structure
-===========================
-
-There is one directory per adapter, named by its Bluetooth address, which
-contains:
- - a settings file for the local adapter
- - an attributes file containing attributes of supported LE services
- - a cache directory containing:
-    - one file per device, named by remote device address, which contains
-    device name
- - one directory per remote device, named by remote device address, which
-   contains:
-    - an info file
-    - an attributes file containing attributes of remote LE services
-    - a ccc file containing persistent Client Characteristic Configuration
-      (CCC) descriptor information for GATT characteristics
-
-So the directory structure is:
-    /var/lib/bluetooth/<adapter address>/
-        ./settings
-        ./attributes
-        ./cache/
-            ./<remote device address>
-            ./<remote device address>
-            ...
-        ./<remote device address>/
-            ./info
-            ./attributes
-            ./ccc
-        ./<remote device address>/
-            ./info
-            ./attributes
-        ...
-
-
-Settings file format
-====================
-
-Settings file contains one [General] group with adapter info like:
-
-  Alias                        String          Friendly user provided name advertised
-                                       for this adapter
-
-                                       This value overwrites the system
-                                       name (pretty hostname)
-
-  Discoverable         Boolean         Discoverability of the adapter
-
-  PairableTimeout      Integer         How long to stay in pairable mode
-                                       before going back to non-pairable.
-                                       The value is in seconds.
-                                       0 = disable timer, i.e. stay
-                                       pairable forever
-
-  DiscoverableTimeout  Integer         How long to stay in discoverable mode
-                                       before going back to non-discoverable.
-                                       The value is in seconds.
-                                       0 = disable timer, i.e. stay
-                                       discoverable forever
-
-Sample:
-  [General]
-  Name=My PC
-  Discoverable=false
-  Pairable=true
-  DiscoverableTimeout=0
-
-
-Attributes file format
-======================
-
-The attributes file lists all attributes supported by the local adapter or
-remote device.
-
-Attributes are stored using their handle as group name (decimal format).
-
-Each group contains:
-
-  UUID                 String          128-bit UUID of the attribute
-
-  Value                        String          Value of the attribute as hexadecimal encoded
-                                       string
-
-  EndGroupHandle       Integer         End group handle in decimal format
-
-Sample:
-  [1]
-  UUID=00002800-0000-1000-8000-00805f9b34fb
-  Value=0018
-
-  [4]
-  UUID=00002803-0000-1000-8000-00805f9b34fb
-  Value=020600002A
-
-  [6]
-  UUID=00002a00-0000-1000-8000-00805f9b34fb
-  Value=4578616D706C6520446576696365
-
-
-CCC file format
-======================
-
-The ccc file stores the current CCC descriptor values for GATT characteristics
-which have notification/indication enabled by the remote device.
-
-Information is stored using CCC attribute handle as group name (in decimal
-format).
-
-Each group contains:
-
-  Value                        String          CCC descriptor value encoded in
-                                       hexadecimal
-
-
-Cache directory file format
-============================
-
-Each file, named by remote device address, may includes multiple groups
-(General and ServiceRecords).
-
-In ServiceRecords, SDP records are stored using their handle as key
-(hexadecimal format).
-
-[General] group contains:
-
-  Name         String          Remote device friendly name
-
-  ShortName    String          Remote device shortened name
-
-[ServiceRecords] group contains
-
-  <0x...>      String          SDP record as hexadecimal encoded
-                               string
-
-
-Info file format
-================
-
-Info file may includes multiple groups (General, Device ID, Link key and
-Long term key) related to a remote device.
-
-[General] group contains:
-
-  Name                 String          Remote device friendly name
-
-  Alias                        String          Alias name
-
-  Class                        String          Device class in hexadecimal,
-                                       i.e. 0x000000
-
-  Appearance           String          Device appearance in hexadecimal,
-                                       i.e. 0x0000
-
-  SupportedTechnologies        List of         List of technologies supported by
-                       strings         device, separated by ";"
-                                       Technologies can be BR/EDR or LE
-
-  AddressType          String          An address can be "static" or "public"
-
-  Trusted              Boolean         True if the remote device is trusted
-
-  Blocked              Boolean         True if the remote device is blocked
-
-  Services             List of         List of service UUIDs advertised by
-                       strings         remote in 128-bits UUID format,
-                                       separated by ";"
-
-
-[DeviceID] group contains:
-
-  Source               Integer         Assigner of Device ID
-
-  Vendor               Integer         Device vendor
-
-  Product              Integer         Device product
-
-  Version              Integer         Device version
-
-
-[LinkKey] group contains:
-
-  Key                  String          Key in hexadecimal format
-
-  Type                 Integer         Type of link key
-
-  PINLength            Integer         Length of PIN
-
-
-[LongTermKey] group contains:
-
-  Key                  String          Long term key in hexadecimal format
-
-  Authenticated                Boolean         True if remote device has been
-                                       authenticated
-
-  Master               Boolean         True for master key
-
-  EncSize              Integer         Encrypted size
-
-  EDiv                 Integer         Encrypted diversifier
-
-  Rand                 Integer         Randomizer
index f98b52398b5caa1cf21a9dbc4e67b45208a242e6..5f04bd17bf2b92075acb263bea3c2da7aaab45ff 100644 (file)
@@ -30,6 +30,7 @@
 #include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
+#include <alloca.h>
 
 #include "monitor/bt.h"
 #include "btdev.h"
@@ -1072,6 +1073,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
        struct bt_hci_rsp_read_auth_enable rae;
        struct bt_hci_rsp_read_class_of_dev rcod;
        struct bt_hci_rsp_read_voice_setting rvs;
+       struct bt_hci_rsp_read_num_supported_iac rnsi;
+       struct bt_hci_rsp_read_current_iac_lap *rcil;
        struct bt_hci_rsp_read_inquiry_mode rim;
        struct bt_hci_rsp_read_afh_assessment_mode raam;
        struct bt_hci_rsp_read_ext_inquiry_response reir;
@@ -1415,6 +1418,26 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
                cmd_complete(btdev, opcode, &status, sizeof(status));
                break;
 
+       case BT_HCI_CMD_READ_NUM_SUPPORTED_IAC:
+               if (btdev->type == BTDEV_TYPE_LE)
+                       goto unsupported;
+               rnsi.status = BT_HCI_ERR_SUCCESS;
+               rnsi.num_iac = 0x01;
+               cmd_complete(btdev, opcode, &rnsi, sizeof(rnsi));
+               break;
+
+       case BT_HCI_CMD_READ_CURRENT_IAC_LAP:
+               if (btdev->type == BTDEV_TYPE_LE)
+                       goto unsupported;
+               rcil = alloca(sizeof(*rcil) + 3);
+               rcil->status = BT_HCI_ERR_SUCCESS;
+               rcil->num_iac = 0x01;
+               rcil->iac_lap[0] = 0x33;
+               rcil->iac_lap[1] = 0x8b;
+               rcil->iac_lap[2] = 0x9e;
+               cmd_complete(btdev, opcode, rcil, sizeof(*rcil) + 3);
+               break;
+
        case BT_HCI_CMD_WRITE_CURRENT_IAC_LAP:
                if (btdev->type == BTDEV_TYPE_LE)
                        goto unsupported;
index 7bffdad19d18f98f76649fad028505aa8b06f99b..be8cc2960e976488563ad2b817c55617298be005 100644 (file)
@@ -112,11 +112,6 @@ static gboolean modify_match(DBusConnection *conn, const char *member,
                return FALSE;
        }
 
-       if (call == NULL) {
-               dbus_message_unref(msg);
-               return FALSE;
-       }
-
        dbus_pending_call_set_notify(call, modify_match_reply, NULL, NULL);
        dbus_pending_call_unref(call);
 
index 0822fe88489260f9eebcabe049991782182cd360..268fed552e36296ef1fa8bd8e64dd75e120da6c9 100644 (file)
@@ -1510,11 +1510,20 @@ gboolean g_dbus_send_message_with_reply(DBusConnection *connection,
                                        DBusMessage *message,
                                        DBusPendingCall **call, int timeout)
 {
+       dbus_bool_t ret;
+
        /* Flush pending signal to guarantee message order */
        g_dbus_flush(connection);
 
-       return dbus_connection_send_with_reply(connection, message, call,
+       ret = dbus_connection_send_with_reply(connection, message, call,
                                                                timeout);
+
+       if (ret == TRUE && call != NULL && *call == NULL) {
+               error("Unable to send message (passing fd blocked?)");
+               return FALSE;
+       }
+
+       return ret;
 }
 
 gboolean g_dbus_send_error_valist(DBusConnection *connection,
index d82fddafeb6b005f434240336bb41409314a01e9..2245ab3122af90fa3a0cfa4185504e78cc5964bf 100644 (file)
@@ -741,8 +741,17 @@ struct bt_hci_rsp_read_num_supported_iac {
 } __attribute__ ((packed));
 
 #define BT_HCI_CMD_READ_CURRENT_IAC_LAP                0x0c39
+struct bt_hci_rsp_read_current_iac_lap {
+       uint8_t  status;
+       uint8_t  num_iac;
+       uint8_t  iac_lap[0];
+} __attribute__ ((packed));
 
 #define BT_HCI_CMD_WRITE_CURRENT_IAC_LAP       0x0c3a
+struct bt_hci_cmd_write_current_iac_lap {
+       uint8_t  num_iac;
+       uint8_t  iac_lap[0];
+} __attribute__ ((packed));
 
 #define BT_HCI_CMD_READ_PAGE_SCAN_PERIOD_MODE  0x0c3b
 struct bt_hci_rsp_read_page_scan_period_mode {
index b7f83145912be0de5b29af1de78c280e9e2061f7..55c9f0f05a35e2a55a540af093920cd43d585ef5 100644 (file)
@@ -3651,6 +3651,29 @@ static void read_num_supported_iac_rsp(const void *data, uint8_t size)
        print_field("Number of IAC: %d", rsp->num_iac);
 }
 
+static void read_current_iac_lap_rsp(const void *data, uint8_t size)
+{
+       const struct bt_hci_rsp_read_current_iac_lap *rsp = data;
+       uint8_t i;
+
+       print_status(rsp->status);
+       print_field("Number of IAC: %d", rsp->num_iac);
+
+       for (i = 0; i < rsp->num_iac; i++)
+               print_iac(rsp->iac_lap + (i * 3));
+}
+
+static void write_current_iac_lap_cmd(const void *data, uint8_t size)
+{
+       const struct bt_hci_cmd_write_current_iac_lap *cmd = data;
+       uint8_t i;
+
+       print_field("Number of IAC: %d", cmd->num_iac);
+
+       for (i = 0; i < cmd->num_iac; i++)
+               print_iac(cmd->iac_lap + (i * 3));
+}
+
 static void read_page_scan_period_mode_rsp(const void *data, uint8_t size)
 {
        const struct bt_hci_rsp_read_page_scan_period_mode *rsp = data;
@@ -4922,8 +4945,12 @@ static const struct opcode_data opcode_table[] = {
        { 0x0c38,  90, "Read Number of Supported IAC",
                                null_cmd, 0, true,
                                read_num_supported_iac_rsp, 2, true },
-       { 0x0c39,  91, "Read Current IAC LAP" },
-       { 0x0c3a,  92, "Write Current IAC LAP" },
+       { 0x0c39,  91, "Read Current IAC LAP",
+                               null_cmd, 0, true,
+                               read_current_iac_lap_rsp, 2, false },
+       { 0x0c3a,  92, "Write Current IAC LAP",
+                               write_current_iac_lap_cmd, 1, false,
+                               status_rsp, 1, true },
        { 0x0c3b,  93, "Read Page Scan Period Mode",
                                null_cmd, 0, true,
                                read_page_scan_period_mode_rsp, 2, true },
index 63692a12ee8cd42c56c0b2cd93a4c0daa107c301..7a56acdb1ebc7a06e9b30b42cc987c3b8cc77e74 100644 (file)
@@ -296,6 +296,16 @@ done:
        g_free(callback);
 }
 
+static void session_disconnected(GObex *obex, GError *err, gpointer user_data)
+{
+       struct obc_session *session = user_data;
+
+       if (err)
+               error("%s", err->message);
+
+       obc_session_shutdown(session);
+}
+
 static void transport_func(GIOChannel *io, GError *err, gpointer user_data)
 {
        struct callback_data *callback = user_data;
@@ -345,6 +355,8 @@ static void transport_func(GIOChannel *io, GError *err, gpointer user_data)
        session->obex = obex;
        sessions = g_slist_prepend(sessions, session);
 
+       g_obex_set_disconnect_function(obex, session_disconnected, session);
+
        return;
 done:
        callback->func(callback->session, NULL, err, callback->data);
diff --git a/obexd/plugins/messages-tracker.c b/obexd/plugins/messages-tracker.c
deleted file mode 100644 (file)
index 60f3a80..0000000
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- *
- *  OBEX Server
- *
- *  Copyright (C) 2010-2011  Nokia Corporation
- *
- *
- *  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 <glib.h>
-#include <string.h>
-
-#include "messages.h"
-
-struct message_folder {
-       char *name;
-       GSList *subfolders;
-       char *query;
-};
-
-struct session {
-       char *cwd;
-       struct message_folder *folder;
-       char *name;
-       uint16_t max;
-       uint16_t offset;
-       void *user_data;
-       void (*folder_list_cb)(void *session, int err, uint16_t size,
-                                       const char *name, void *user_data);
-};
-
-static struct message_folder *folder_tree = NULL;
-
-static struct message_folder *get_folder(const char *folder)
-{
-       GSList *folders = folder_tree->subfolders;
-       struct message_folder *last = NULL;
-       char **path;
-       int i;
-
-       if (g_strcmp0(folder, "/") == 0)
-               return folder_tree;
-
-       path = g_strsplit(folder, "/", 0);
-
-       for (i = 1; path[i] != NULL; i++) {
-               gboolean match_found = FALSE;
-               GSList *l;
-
-               for (l = folders; l != NULL; l = g_slist_next(l)) {
-                       struct message_folder *folder = l->data;
-
-                       if (g_strcmp0(folder->name, path[i]) == 0) {
-                               match_found = TRUE;
-                               last = l->data;
-                               folders = folder->subfolders;
-                               break;
-                       }
-               }
-
-               if (!match_found) {
-                       g_strfreev(path);
-                       return NULL;
-               }
-       }
-
-       g_strfreev(path);
-
-       return last;
-}
-
-static struct message_folder *create_folder(const char *name, const char *query)
-{
-       struct message_folder *folder = g_new0(struct message_folder, 1);
-
-       folder->name = g_strdup(name);
-       folder->query = g_strdup(query);
-
-       return folder;
-}
-
-static void destroy_folder_tree(void *root)
-{
-       struct message_folder *folder = root;
-       GSList *tmp, *next;
-
-       if (folder == NULL)
-               return;
-
-       g_free(folder->name);
-       g_free(folder->query);
-
-       tmp = folder->subfolders;
-       while (tmp != NULL) {
-               next = g_slist_next(tmp);
-               destroy_folder_tree(tmp->data);
-               tmp = next;
-       }
-
-       g_slist_free(folder->subfolders);
-       g_free(folder);
-}
-
-static void create_folder_tree(void)
-{
-       struct message_folder *parent, *child;
-
-       folder_tree = create_folder("/", "FILTER (!BOUND(?msg))");
-
-       parent = create_folder("telecom", "FILTER (!BOUND(?msg))");
-       folder_tree->subfolders = g_slist_append(folder_tree->subfolders,
-                                                               parent);
-
-       child = create_folder("msg", "FILTER (!BOUND(?msg))");
-       parent->subfolders = g_slist_append(parent->subfolders, child);
-
-       parent = child;
-
-       child = create_folder("inbox", "?msg nmo:isSent \"false\" ; "
-                               "nmo:isDeleted \"false\" ; "
-                               "nmo:isDraft \"false\". ");
-       parent->subfolders = g_slist_append(parent->subfolders, child);
-
-       child = create_folder("sent", "?msg nmo:isDeleted \"false\" ; "
-                               "nmo:isSent \"true\" . ");
-       parent->subfolders = g_slist_append(parent->subfolders, child);
-
-       child = create_folder("deleted", "?msg nmo:isDeleted \"true\" . ");
-       parent->subfolders = g_slist_append(parent->subfolders, child);
-}
-
-int messages_init(void)
-{
-       create_folder_tree();
-
-       return 0;
-}
-
-void messages_exit(void)
-{
-       destroy_folder_tree(folder_tree);
-}
-
-int messages_connect(void **s)
-{
-       struct session *session = g_new0(struct session, 1);
-
-       session->cwd = g_strdup("/");
-       session->folder = folder_tree;
-
-       *s = session;
-
-       return 0;
-}
-
-void messages_disconnect(void *s)
-{
-       struct session *session = s;
-
-       g_free(session->cwd);
-       g_free(session);
-}
-
-int messages_set_notification_registration(void *session,
-               void (*send_event)(void *session,
-                       const struct messages_event *event, void *user_data),
-               void *user_data)
-{
-       return -ENOSYS;
-}
-
-int messages_set_folder(void *s, const char *name, gboolean cdup)
-{
-       struct session *session = s;
-       char *newrel = NULL;
-       char *newabs;
-       char *tmp;
-
-       if (name && (strchr(name, '/') || strcmp(name, "..") == 0))
-               return -EBADR;
-
-       if (cdup) {
-               if (session->cwd[0] == 0)
-                       return -ENOENT;
-
-               newrel = g_path_get_dirname(session->cwd);
-
-               /* We use empty string for indication of the root directory */
-               if (newrel[0] == '.' && newrel[1] == 0)
-                       newrel[0] = 0;
-       }
-
-       tmp = newrel;
-       if (!cdup && (!name || name[0] == 0))
-               newrel = g_strdup("");
-       else
-               newrel = g_build_filename(newrel ? newrel : session->cwd, name,
-                                                                       NULL);
-       g_free(tmp);
-
-       if (newrel[0] != '/')
-               newabs = g_build_filename("/", newrel, NULL);
-       else
-               newabs = g_strdup(newrel);
-
-       session->folder = get_folder(newabs);
-       if (session->folder == NULL) {
-               g_free(newrel);
-               g_free(newabs);
-
-               return -ENOENT;
-       }
-
-       g_free(newrel);
-       g_free(session->cwd);
-       session->cwd = newabs;
-
-       return 0;
-}
-
-static gboolean async_get_folder_listing(void *s)
-{
-       struct session *session = s;
-       gboolean count = FALSE;
-       int folder_count = 0;
-       char *path = NULL;
-       struct message_folder *folder;
-       GSList *dir;
-
-       if (session->name && strchr(session->name, '/') != NULL)
-               goto done;
-
-       path = g_build_filename(session->cwd, session->name, NULL);
-
-       if (path == NULL || strlen(path) == 0)
-               goto done;
-
-       folder = get_folder(path);
-
-       if (folder == NULL)
-               goto done;
-
-       if (session->max == 0) {
-               session->max = 0xffff;
-               session->offset = 0;
-               count = TRUE;
-       }
-
-       for (dir = folder->subfolders; dir &&
-                               (folder_count - session->offset) < session->max;
-                               folder_count++, dir = g_slist_next(dir)) {
-               struct message_folder *dir_data = dir->data;
-
-               if (count == FALSE && session->offset <= folder_count)
-                       session->folder_list_cb(session, -EAGAIN, 0,
-                                       dir_data->name, session->user_data);
-       }
-
- done:
-       session->folder_list_cb(session, 0, folder_count, NULL,
-                                                       session->user_data);
-
-       g_free(path);
-       g_free(session->name);
-
-       return FALSE;
-}
-
-int messages_get_folder_listing(void *s, const char *name,
-                                       uint16_t max, uint16_t offset,
-                                       messages_folder_listing_cb callback,
-                                       void *user_data)
-{
-       struct session *session = s;
-       session->name = g_strdup(name);
-       session->max = max;
-       session->offset = offset;
-       session->folder_list_cb = callback;
-       session->user_data = user_data;
-
-       g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, async_get_folder_listing,
-                                               session, NULL);
-
-       return 0;
-}
-
-int messages_get_messages_listing(void *session, const char *name,
-                               uint16_t max, uint16_t offset,
-                               uint8_t subject_len,
-                               const struct messages_filter *filter,
-                               messages_get_messages_listing_cb callback,
-                               void *user_data)
-{
-       return -ENOSYS;
-}
-
-int messages_get_message(void *session, const char *handle,
-                               unsigned long flags,
-                               messages_get_message_cb callback,
-                               void *user_data)
-{
-       return -ENOSYS;
-}
-
-int messages_update_inbox(void *session, messages_status_cb callback,
-                                                       void *user_data)
-{
-       return -ENOSYS;
-}
-
-int messages_set_read(void *session, const char *handle, uint8_t value,
-                               messages_status_cb callback, void *user_data)
-{
-       return -ENOSYS;
-}
-
-int messages_set_delete(void *session, const char *handle, uint8_t value,
-                                       messages_status_cb callback,
-                                       void *user_data)
-{
-       return -ENOSYS;
-}
-
-void messages_abort(void *session)
-{
-}
diff --git a/obexd/plugins/phonebook-ebook.c b/obexd/plugins/phonebook-ebook.c
deleted file mode 100644 (file)
index 2e49576..0000000
+++ /dev/null
@@ -1,707 +0,0 @@
-/*
- *
- *  OBEX Server
- *
- *  Copyright (C) 2009-2010  Intel Corporation
- *  Copyright (C) 2007-2010  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 <string.h>
-#include <errno.h>
-#include <glib.h>
-#include <bluetooth/bluetooth.h>
-
-#include <libebook/e-book.h>
-
-#include "log.h"
-#include "obex.h"
-#include "service.h"
-#include "phonebook.h"
-
-#define QUERY_FN "(contains \"family_name\" \"%s\")"
-#define QUERY_NAME "(contains \"given_name\" \"%s\")"
-#define QUERY_PHONE "(contains \"phone\" \"%s\")"
-
-struct query_context {
-       const struct apparam_field *params;
-       phonebook_cb contacts_cb;
-       phonebook_entry_cb entry_cb;
-       phonebook_cache_ready_cb ready_cb;
-       EBookQuery *query;
-       unsigned int count;
-       GString *buf;
-       char *id;
-       unsigned queued_calls;
-       void *user_data;
-       GSList *ebooks;
-       gboolean canceled;
-};
-
-static char *attribute_mask[] = {
-/* 0 */                "VERSION",
-               "FN",
-               "N",
-               "PHOTO",
-               "BDAY",
-               "ADR",
-               "LABEL",
-               "TEL",
-/* 8 */                "EMAIL",
-               "MAILER",
-               "TZ",
-               "GEO",
-               "TITLE",
-               "ROLE",
-               "LOGO",
-               "AGENT",
-/* 16 */       "ORG",
-               "NOTE",
-               "REV",
-               "SOUND",
-               "URL",
-               "UID",
-               "KEY",
-               "NICKNAME",
-/* 24 */       "CATEGORIES",
-               "PROID",
-               "CLASS",
-               "SORT-STRING",
-/* 28 */       "X-IRMC-CALL-DATETIME",
-               NULL
-
-};
-
-static void close_ebooks(GSList *ebooks)
-{
-       g_slist_free_full(ebooks, g_object_unref);
-}
-
-static void free_query_context(struct query_context *data)
-{
-       g_free(data->id);
-
-       if (data->buf != NULL)
-               g_string_free(data->buf, TRUE);
-
-       if (data->query != NULL)
-               e_book_query_unref(data->query);
-
-       close_ebooks(data->ebooks);
-
-       g_free(data);
-}
-
-static char *evcard_to_string(EVCard *evcard, unsigned int format,
-                                                       uint64_t filter)
-{
-       EVCard *evcard2;
-       GList *l;
-       char *vcard;
-
-       if (!filter)
-               return e_vcard_to_string(evcard, EVC_FORMAT_VCARD_30);
-               /* XXX There is no support for VCARD 2.1 at this time */
-
-       /*
-        * Mandatory attributes for vCard 2.1 are VERSION ,N and TEL.
-        * Mandatory attributes for vCard 3.0 are VERSION, N, FN and TEL
-        */
-       filter = format == EVC_FORMAT_VCARD_30 ? filter | 0x87: filter | 0x85;
-
-       l = e_vcard_get_attributes(evcard);
-       evcard2 = e_vcard_new();
-       for (; l; l = g_list_next(l)) {
-               EVCardAttribute *attrib = l->data;
-               const char *name;
-               int i;
-
-               if (!attrib)
-                       continue;
-
-               name = e_vcard_attribute_get_name(attrib);
-
-               for (i = 0; attribute_mask[i] != NULL; i++) {
-                       if (!(filter & (1 << i)))
-                               continue;
-                       if (g_strcmp0(name, attribute_mask[i]) != 0)
-                               continue;
-
-                       e_vcard_add_attribute(evcard2,
-                                       e_vcard_attribute_copy(attrib));
-               }
-       }
-
-       vcard = e_vcard_to_string(evcard2, format);
-       g_object_unref(evcard2);
-
-       return vcard;
-}
-
-static void ebookpull_cb(EBook *book, const GError *gerr, GList *contacts,
-                                                       void *user_data)
-{
-       struct query_context *data = user_data;
-       GList *l;
-       unsigned int count, maxcount;
-
-       data->queued_calls--;
-
-       if (data->canceled)
-               goto canceled;
-
-       if (gerr != NULL) {
-               error("E-Book query failed: %s", gerr->message);
-               goto done;
-       }
-
-       DBG("");
-
-       /*
-        * When MaxListCount is zero, PCE wants to know the number of used
-        * indexes in the phonebook of interest. All other parameters that
-        * may be present in the request shall be ignored.
-        */
-       maxcount = data->params->maxlistcount;
-       if (maxcount == 0) {
-               data->count += g_list_length(contacts);
-               goto done;
-       }
-
-       l = g_list_nth(contacts, data->params->liststartoffset);
-
-       for (count = 0; l && count + data->count < maxcount; l = g_list_next(l),
-                                                               count++) {
-               EContact *contact = E_CONTACT(l->data);
-               EVCard *evcard = E_VCARD(contact);
-               char *vcard;
-
-               vcard = evcard_to_string(evcard, EVC_FORMAT_VCARD_30,
-                                               data->params->filter);
-
-               data->buf = g_string_append(data->buf, vcard);
-               data->buf = g_string_append(data->buf, "\r\n");
-               g_free(vcard);
-       }
-
-       DBG("collected %d vcards", count);
-
-       data->count += count;
-
-       g_list_free_full(contacts, g_object_unref);
-
-done:
-       if (data->queued_calls == 0) {
-               GString *buf = data->buf;
-               data->buf = NULL;
-
-               data->contacts_cb(buf->str, buf->len, data->count,
-                                               0, TRUE, data->user_data);
-
-               g_string_free(buf, TRUE);
-
-       }
-
-       return;
-
-canceled:
-       if (data->queued_calls == 0)
-               free_query_context(data);
-}
-
-static void ebook_entry_cb(EBook *book, const GError *gerr,
-                               EContact *contact, void *user_data)
-{
-       struct query_context *data = user_data;
-       EVCard *evcard;
-       char *vcard;
-       size_t len;
-
-       data->queued_calls--;
-
-       if (data->canceled)
-               goto done;
-
-       if (gerr != NULL) {
-               error("E-Book query failed: %s", gerr->message);
-               goto done;
-       }
-
-       DBG("");
-
-       evcard = E_VCARD(contact);
-
-       vcard = evcard_to_string(evcard, EVC_FORMAT_VCARD_30,
-                                       data->params->filter);
-
-       len = vcard ? strlen(vcard) : 0;
-
-       data->count++;
-       data->contacts_cb(vcard, len, 1, 0, TRUE, data->user_data);
-
-       g_free(vcard);
-       g_object_unref(contact);
-
-       return;
-
-done:
-       if (data->queued_calls == 0) {
-               if (data->count == 0)
-                       data->contacts_cb(NULL, 0, 1, 0, TRUE,
-                                               data->user_data);
-               else if (data->canceled)
-                       free_query_context(data);
-       }
-}
-
-static char *evcard_name_attribute_to_string(EVCard *evcard)
-{
-       EVCardAttribute *attrib;
-       GList *l;
-       GString *name = NULL;
-
-       attrib = e_vcard_get_attribute(evcard, EVC_N);
-       if (!attrib)
-               return NULL;
-
-       for (l = e_vcard_attribute_get_values(attrib); l; l = l->next) {
-               const char *value = l->data;
-
-               if (!strlen(value))
-                       continue;
-
-               if (!name)
-                       name = g_string_new(value);
-               else {
-                       name = g_string_append(name, ";");
-                       name = g_string_append(name, l->data);
-               }
-       }
-
-       if (!name)
-               return NULL;
-
-       return g_string_free(name, FALSE);
-}
-
-static void cache_cb(EBook *book, const GError *gerr, GList *contacts,
-                                                       void *user_data)
-{
-       struct query_context *data = user_data;
-       GList *l;
-
-       data->queued_calls--;
-
-       if (data->canceled)
-               goto canceled;
-
-       if (gerr != NULL) {
-               error("E-Book operation failed: %s", gerr->message);
-               goto done;
-       }
-
-       DBG("");
-
-       for (l = contacts; l; l = g_list_next(l)) {
-               EContact *contact = E_CONTACT(l->data);
-               EVCard *evcard = E_VCARD(contact);
-               EVCardAttribute *attrib;
-               char *uid, *tel, *name;
-
-               name = evcard_name_attribute_to_string(evcard);
-               if (!name)
-                       continue;
-
-               attrib = e_vcard_get_attribute(evcard, EVC_UID);
-               if (!attrib)
-                       continue;
-
-               uid = e_vcard_attribute_get_value(attrib);
-               if (!uid)
-                       continue;
-
-               attrib = e_vcard_get_attribute(evcard, EVC_TEL);
-               if (attrib)
-                       tel = e_vcard_attribute_get_value(attrib);
-               else
-                       tel = g_strdup("");
-
-               data->entry_cb(uid, PHONEBOOK_INVALID_HANDLE, name, NULL,
-                                                       tel, data->user_data);
-
-               g_free(name);
-               g_free(uid);
-               g_free(tel);
-       }
-
-       g_list_free_full(contacts, g_object_unref);
-
-done:
-       if (data->queued_calls == 0)
-               data->ready_cb(data->user_data);
-
-       return;
-
-canceled:
-       if (data->queued_calls == 0)
-               free_query_context(data);
-}
-
-static GSList *traverse_sources(GSList *ebooks, GSList *sources,
-                                                       char **default_src) {
-       GError *gerr = NULL;
-
-       for (; sources != NULL; sources = g_slist_next(sources)) {
-               char *uri;
-               ESource *source = E_SOURCE(sources->data);
-               EBook *ebook = e_book_new(source, &gerr);
-
-               if (ebook == NULL) {
-                       error("Can't create user's address book: %s",
-                                                               gerr->message);
-                       g_clear_error(&gerr);
-                       continue;
-               }
-
-               uri = e_source_get_uri(source);
-               if (g_strcmp0(*default_src, uri) == 0) {
-                       g_free(uri);
-                       continue;
-               }
-               g_free(uri);
-
-               if (e_book_open(ebook, FALSE, &gerr) == FALSE) {
-                       error("Can't open e-book address book: %s",
-                                                       gerr->message);
-                       g_object_unref(ebook);
-                       g_clear_error(&gerr);
-                       continue;
-               }
-
-               if (*default_src == NULL)
-                       *default_src = e_source_get_uri(source);
-
-               DBG("%s address book opened", e_source_peek_name(source));
-
-               ebooks = g_slist_append(ebooks, ebook);
-       }
-
-       return ebooks;
-}
-
-int phonebook_init(void)
-{
-       g_type_init();
-
-       return 0;
-}
-
-static GSList *open_ebooks(void)
-{
-       GError *gerr = NULL;
-       ESourceList *src_list;
-       GSList *list;
-       char *default_src = NULL;
-       GSList *ebooks = NULL;
-
-       if (e_book_get_addressbooks(&src_list, &gerr) == FALSE) {
-               error("Can't list user's address books: %s", gerr->message);
-               g_error_free(gerr);
-               return NULL;
-       }
-
-       list = e_source_list_peek_groups(src_list);
-       while (list != NULL) {
-               ESourceGroup *group = E_SOURCE_GROUP(list->data);
-               GSList *sources = e_source_group_peek_sources(group);
-
-               ebooks = traverse_sources(ebooks, sources, &default_src);
-
-               list = list->next;
-       }
-
-       g_free(default_src);
-       g_object_unref(src_list);
-
-       return ebooks;
-}
-
-void phonebook_exit(void)
-{
-}
-
-char *phonebook_set_folder(const char *current_folder,
-               const char *new_folder, uint8_t flags, int *err)
-{
-       gboolean root, child;
-       char *fullname = NULL, *tmp1, *tmp2, *base;
-       int ret = 0, len;
-
-       root = (g_strcmp0("/", current_folder) == 0);
-       child = (new_folder && strlen(new_folder) != 0);
-
-       /* Evolution back-end will support /telecom/pb folder only */
-
-       switch (flags) {
-       case 0x02:
-               /* Go back to root */
-               if (!child) {
-                       fullname = g_strdup("/");
-                       goto done;
-               }
-
-               /* Go down 1 level */
-               fullname = g_build_filename(current_folder, new_folder, NULL);
-               if (strcmp(PB_TELECOM_FOLDER, fullname) != 0 &&
-                               strcmp(PB_CONTACTS_FOLDER, fullname) != 0) {
-                       g_free(fullname);
-                       fullname = NULL;
-                       ret = -ENOENT;
-               }
-
-               break;
-       case 0x03:
-               /* Go up 1 level */
-               if (root) {
-                       /* Already root */
-                       ret = -EBADR;
-                       goto done;
-               }
-
-               /*
-                * Removing one level of the current folder. Current folder
-                * contains AT LEAST one level since it is not at root folder.
-                * Use glib utility functions to handle invalid chars in the
-                * folder path properly.
-                */
-               tmp1 = g_path_get_basename(current_folder);
-               tmp2 = g_strrstr(current_folder, tmp1);
-               len = tmp2 - (current_folder + 1);
-
-               g_free(tmp1);
-
-               if (len == 0)
-                       base = g_strdup("/");
-               else
-                       base = g_strndup(current_folder, len);
-
-               /* Return one level only */
-               if (!child) {
-                       fullname = base;
-                       goto done;
-               }
-
-               fullname = g_build_filename(base, new_folder, NULL);
-               if (strcmp(fullname, PB_TELECOM_FOLDER) != 0 &&
-                               strcmp(fullname, PB_CONTACTS_FOLDER) != 0) {
-                       g_free(fullname);
-                       fullname = NULL;
-                       ret = -ENOENT;
-               }
-
-               g_free(base);
-
-               break;
-       default:
-               ret = -EBADR;
-               break;
-       }
-
-done:
-       if (err)
-               *err = ret;
-
-       return fullname;
-}
-
-void phonebook_req_finalize(void *request)
-{
-       struct query_context *data = request;
-
-       if (data->queued_calls == 0)
-               free_query_context(data);
-       else
-               data->canceled = TRUE;
-}
-
-void *phonebook_pull(const char *name, const struct apparam_field *params,
-                               phonebook_cb cb, void *user_data, int *err)
-{
-       struct query_context *data;
-
-       if (g_strcmp0(PB_CONTACTS, name) != 0) {
-               if (err)
-                       *err = -ENOENT;
-
-               return NULL;
-       }
-
-       data = g_new0(struct query_context, 1);
-       data->contacts_cb = cb;
-       data->params = params;
-       data->user_data = user_data;
-       data->buf = g_string_new("");
-       data->query = e_book_query_any_field_contains("");
-       data->ebooks = open_ebooks();
-
-       if (err)
-               *err = data->ebooks == NULL ? -EIO : 0;
-
-       return data;
-}
-
-int phonebook_pull_read(void *request)
-{
-       struct query_context *data = request;
-       GSList *l;
-
-       if (!data)
-               return -ENOENT;
-
-       for (l = data->ebooks; l != NULL; l = g_slist_next(l)) {
-               EBook *ebook = l->data;
-
-               if (e_book_is_opened(ebook) == FALSE)
-                       continue;
-
-               if (e_book_get_contacts_async(ebook, data->query,
-                                               ebookpull_cb, data) == TRUE)
-                       data->queued_calls++;
-       }
-
-       if (data->queued_calls == 0)
-               return -ENOENT;
-
-       return 0;
-}
-
-void *phonebook_get_entry(const char *folder, const char *id,
-                               const struct apparam_field *params,
-                               phonebook_cb cb, void *user_data, int *err)
-{
-       struct query_context *data;
-       GSList *l;
-
-       data = g_new0(struct query_context, 1);
-       data->contacts_cb = cb;
-       data->params = params;
-       data->user_data = user_data;
-       data->id = g_strdup(id);
-       data->ebooks = open_ebooks();
-
-       for (l = data->ebooks; l != NULL; l = g_slist_next(l)) {
-               EBook *ebook = l->data;
-
-               if (e_book_is_opened(ebook) == FALSE)
-                       continue;
-
-               if (e_book_get_contact_async(ebook, data->id,
-                                               ebook_entry_cb, data) == TRUE)
-                       data->queued_calls++;
-       }
-
-       if (err)
-               *err = (data->queued_calls == 0 ? -ENOENT : 0);
-
-       return data;
-}
-
-void *phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb,
-               phonebook_cache_ready_cb ready_cb, void *user_data, int *err)
-{
-       struct query_context *data;
-       EBookQuery *query;
-       GSList *l;
-       EContact *me;
-       EVCard *evcard;
-       GError *gerr = NULL;
-       EBook *eb;
-       EVCardAttribute *attrib;
-       char *uid, *tel, *cname;
-
-       if (g_strcmp0(PB_CONTACTS_FOLDER, name) != 0) {
-               if (err)
-                       *err = -ENOENT;
-
-               return NULL;
-       }
-
-       DBG("");
-
-       query = e_book_query_any_field_contains("");
-
-       data = g_new0(struct query_context, 1);
-       data->entry_cb = entry_cb;
-       data->ready_cb = ready_cb;
-       data->user_data = user_data;
-       data->query = query;
-       data->ebooks = open_ebooks();
-
-       /* Add 0.vcf */
-       if (e_book_get_self(&me, &eb, &gerr) == FALSE) {
-               g_error_free(gerr);
-               goto next;
-       }
-
-       evcard = E_VCARD(me);
-
-       cname = evcard_name_attribute_to_string(evcard);
-       if (!cname)
-               cname = g_strdup("");
-
-       attrib = e_vcard_get_attribute(evcard, EVC_UID);
-       uid = e_vcard_attribute_get_value(attrib);
-       if (!uid)
-               uid = g_strdup("");
-
-       attrib = e_vcard_get_attribute(evcard, EVC_TEL);
-       if (attrib)
-               tel =  e_vcard_attribute_get_value(attrib);
-       else
-               tel = g_strdup("");
-
-       data->entry_cb(uid, 0, cname, NULL, tel, data->user_data);
-
-       data->count++;
-
-       g_free(cname);
-       g_free(uid);
-       g_free(tel);
-       g_object_unref(eb);
-
-next:
-       for (l = data->ebooks; l != NULL; l = g_slist_next(l)) {
-               EBook *ebook = l->data;
-
-               if (e_book_is_opened(ebook) == FALSE)
-                       continue;
-
-               if (e_book_get_contacts_async(ebook, query,
-                                               cache_cb, data) == TRUE)
-                       data->queued_calls++;
-       }
-
-       if (err)
-               *err = (data->queued_calls == 0 ? -ENOENT : 0);
-
-       return data;
-}
diff --git a/obexd/plugins/phonebook-tracker.c b/obexd/plugins/phonebook-tracker.c
deleted file mode 100644 (file)
index 433f95a..0000000
+++ /dev/null
@@ -1,1718 +0,0 @@
-/*
- *  Phonebook access through D-Bus vCard and call history service
- *
- *  Copyright (C) 2010  Nokia Corporation
- *
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-#include <stdlib.h>
-#include <time.h>
-#include <stdio.h>
-#include <errno.h>
-#include <glib.h>
-#include <dbus/dbus.h>
-#include <libtracker-sparql/tracker-sparql.h>
-
-#include "log.h"
-#include "obex.h"
-#include "service.h"
-#include "mimetype.h"
-#include "phonebook.h"
-#include "vcard.h"
-
-#define TRACKER_SERVICE "org.freedesktop.Tracker1"
-#define TRACKER_RESOURCES_PATH "/org/freedesktop/Tracker1/Resources"
-#define TRACKER_RESOURCES_INTERFACE "org.freedesktop.Tracker1.Resources"
-
-#define TRACKER_DEFAULT_CONTACT_ME "http://www.semanticdesktop.org/ontologies/2007/03/22/nco#default-contact-me"
-#define AFFILATION_HOME "Home"
-#define AFFILATION_WORK "Work"
-#define ADDR_FIELD_AMOUNT 7
-#define PULL_QUERY_COL_AMOUNT 23
-#define COUNT_QUERY_COL_AMOUNT 1
-
-#define COL_PHONE_AFF 0 /* work/home phone numbers */
-#define COL_FULL_NAME 1
-#define COL_FAMILY_NAME 2
-#define COL_GIVEN_NAME 3
-#define COL_ADDITIONAL_NAME 4
-#define COL_NAME_PREFIX 5
-#define COL_NAME_SUFFIX 6
-#define COL_ADDR_AFF 7 /* addresses from affilation */
-#define COL_BIRTH_DATE 8
-#define COL_NICKNAME 9
-#define COL_URL 10
-#define COL_PHOTO 11
-#define COL_ORG_ROLE 12
-#define COL_UID 13
-#define COL_TITLE 14
-#define COL_AFF_TYPE 15
-#define COL_ORG_NAME 16
-#define COL_ORG_DEPARTMENT 17
-#define COL_EMAIL_AFF 18 /* email's from affilation (work/home) */
-#define COL_DATE 19
-#define COL_SENT 20
-#define COL_ANSWERED 21
-#define CONTACTS_ID_COL 22
-#define CONTACT_ID_PREFIX "urn:uuid:"
-#define CALL_ID_PREFIX "message:"
-
-#define FAX_NUM_TYPE "http://www.semanticdesktop.org/ontologies/2007/03/22/nco#FaxNumber"
-#define MOBILE_NUM_TYPE "http://www.semanticdesktop.org/ontologies/2007/03/22/nco#CellPhoneNumber"
-
-#define MAIN_DELIM "\30" /* Main delimiter between phones, addresses, emails*/
-#define SUB_DELIM "\31" /* Delimiter used in telephone number strings*/
-#define ADDR_DELIM "\37" /* Delimiter used for address data fields */
-#define MAX_FIELDS 100 /* Max amount of fields to be concatenated at once*/
-#define VCARDS_PART_COUNT 50 /* amount of vcards sent at once to PBAP core */
-#define QUERY_OFFSET_FORMAT "%s OFFSET %d"
-
-#define CONTACTS_QUERY_ALL                                             \
-"SELECT "                                                              \
-"(SELECT GROUP_CONCAT(fn:concat(rdf:type(?aff_number),"                        \
-"\"\31\", nco:phoneNumber(?aff_number)), \"\30\")"                     \
-"WHERE {"                                                              \
-"      ?_role nco:hasPhoneNumber ?aff_number"                          \
-"}) "                                                                  \
-"nco:fullname(?_contact) "                                             \
-"nco:nameFamily(?_contact) "                                           \
-"nco:nameGiven(?_contact) "                                            \
-"nco:nameAdditional(?_contact) "                                       \
-"nco:nameHonorificPrefix(?_contact) "                                  \
-"nco:nameHonorificSuffix(?_contact) "                                  \
-"(SELECT GROUP_CONCAT(fn:concat("                                      \
-"tracker:coalesce(nco:pobox(?aff_addr), \"\"), \"\37\","               \
-"tracker:coalesce(nco:extendedAddress(?aff_addr), \"\"), \"\37\","     \
-"tracker:coalesce(nco:streetAddress(?aff_addr), \"\"), \"\37\","       \
-"tracker:coalesce(nco:locality(?aff_addr), \"\"), \"\37\","            \
-"tracker:coalesce(nco:region(?aff_addr), \"\"), \"\37\","              \
-"tracker:coalesce(nco:postalcode(?aff_addr), \"\"), \"\37\","          \
-"tracker:coalesce(nco:country(?aff_addr), \"\"), "                     \
-"\"\31\", rdfs:label(?_role) ), "                                      \
-"\"\30\") "                                                            \
-"WHERE {"                                                              \
-"?_role nco:hasPostalAddress ?aff_addr"                                        \
-"}) "                                                                  \
-"nco:birthDate(?_contact) "                                            \
-"(SELECT "                                                             \
-"      ?nick "                                                         \
-"      WHERE { "                                                       \
-"              { "                                                     \
-"                      ?_contact nco:nickname ?nick "                  \
-"              } UNION { "                                             \
-"                      ?_contact nco:hasAffiliation ?role . "          \
-"                      ?role nco:hasIMAddress ?im . "                  \
-"                      ?im nco:imNickname ?nick "                      \
-"              } "                                                     \
-"      } "                                                             \
-") "                                                                   \
-"(SELECT GROUP_CONCAT(fn:concat( "                                     \
-       "?url_val, \"\31\", tracker:coalesce(rdfs:label(?_role), \"\") "\
-       "), \"\30\") "                                                  \
-       "WHERE {"                                                       \
-               "?_role nco:url ?url_val . "                            \
-"})"                                                                   \
-"nie:url(nco:photo(?_contact)) "                                       \
-"nco:role(?_role) "                                                    \
-"nco:contactUID(?_contact) "                                           \
-"nco:title(?_role) "                                                   \
-"rdfs:label(?_role) "                                                  \
-"nco:fullname(nco:org(?_role))"                                                \
-"nco:department(?_role) "                                              \
-"(SELECT GROUP_CONCAT(fn:concat(?emailaddress,\"\31\","                        \
-       "tracker:coalesce(rdfs:label(?_role), \"\")),"                  \
-       "\"\30\") "                                                     \
-       "WHERE { "                                                      \
-       "?_role nco:hasEmailAddress "                                   \
-       "               [ nco:emailAddress ?emailaddress ] "            \
-       "}) "                                                           \
-"\"NOTACALL\" \"false\" \"false\" "                                    \
-"?_contact "                                                           \
-"WHERE {"                                                              \
-"      ?_contact a nco:PersonContact ."                                \
-"      OPTIONAL {?_contact nco:hasAffiliation ?_role .}"               \
-"}"                                                                    \
-"ORDER BY tracker:id(?_contact)"
-
-#define CONTACTS_QUERY_ALL_LIST                                                \
-       "SELECT ?c nco:nameFamily(?c) "                                 \
-       "nco:nameGiven(?c) nco:nameAdditional(?c) "                     \
-       "nco:nameHonorificPrefix(?c) nco:nameHonorificSuffix(?c) "      \
-       "(SELECT "                                                      \
-               "?nick "                                                \
-               "WHERE { "                                              \
-                       "{ "                                            \
-                               "?c nco:nickname ?nick "                \
-                       "} UNION { "                                    \
-                               "?c nco:hasAffiliation ?role . "        \
-                               "?role nco:hasIMAddress ?im . "         \
-                               "?im nco:imNickname ?nick "             \
-                       "} "                                            \
-               "} "                                                    \
-       ") "                                                            \
-       "nco:phoneNumber(?h) "                                          \
-       "WHERE { "                                                      \
-               "?c a nco:PersonContact . "                             \
-       "OPTIONAL { ?c nco:hasPhoneNumber ?h . } "                      \
-       "OPTIONAL { "                                                   \
-               "?c nco:hasAffiliation ?a . "                           \
-               "?a nco:hasPhoneNumber ?h . "                           \
-       "} "                                                            \
-       "} GROUP BY ?c"
-
-#define CALLS_CONSTRAINTS(CONSTRAINT)                                  \
-" WHERE { "                                                            \
-       "?_call a nmo:Call . "                                          \
-       "?_unb_contact a nco:Contact . "                                \
-       "?_unb_contact nco:hasPhoneNumber ?_cpn . "                     \
-CONSTRAINT                                                             \
-       "OPTIONAL { "                                                   \
-               "{ SELECT ?_contact ?_no ?_role ?_number "              \
-                       "count(?_contact) as ?cnt "                     \
-               "WHERE { "                                              \
-                       "?_contact a nco:PersonContact . "              \
-                       "{ "                                            \
-                               "?_contact nco:hasAffiliation ?_role . "\
-                               "?_role nco:hasPhoneNumber ?_number . " \
-                       "} UNION { "                                    \
-                               "?_contact nco:hasPhoneNumber ?_number" \
-                       "} "                                            \
-                       "?_number maemo:localPhoneNumber ?_no . "       \
-               "} GROUP BY ?_no } "                                    \
-               "FILTER(?cnt = 1) "                                     \
-               "?_cpn maemo:localPhoneNumber ?_no . "                  \
-       "} "                                                            \
-"} "
-
-#define CALLS_LIST(CONSTRAINT)                                         \
-"SELECT ?_call nco:nameFamily(?_contact) "                             \
-       "nco:nameGiven(?_contact) nco:nameAdditional(?_contact) "       \
-       "nco:nameHonorificPrefix(?_contact) "                           \
-       "nco:nameHonorificSuffix(?_contact) "                           \
-       "(SELECT "                                                      \
-               "?nick "                                                \
-               "WHERE { "                                              \
-                       "{ "                                            \
-                               "?_contact nco:nickname ?nick "         \
-                       "} UNION { "                                    \
-                               "?_contact nco:hasAffiliation ?role . " \
-                               "?role nco:hasIMAddress ?im . "         \
-                               "?im nco:imNickname ?nick "             \
-                       "} "                                            \
-               "} "                                                    \
-       ") "                                                            \
-       "nco:phoneNumber(?_cpn) "                                       \
-CALLS_CONSTRAINTS(CONSTRAINT)                                          \
-"ORDER BY DESC(nmo:sentDate(?_call)) "
-
-#define CALLS_QUERY(CONSTRAINT)                                                \
-"SELECT "                                                              \
-"(SELECT fn:concat(rdf:type(?role_number),"                            \
-       "\"\31\", nco:phoneNumber(?role_number))"                       \
-       "WHERE {"                                                       \
-       "{"                                                             \
-       "       ?_role nco:hasPhoneNumber ?role_number "                \
-       "       FILTER (?role_number = ?_number)"                       \
-       "} UNION { "                                                    \
-               "?_unb_contact nco:hasPhoneNumber ?role_number . "      \
-       "       FILTER (!bound(?_role)) "                               \
-       "}"                                                             \
-"} GROUP BY nco:phoneNumber(?role_number) ) "                          \
-       "nco:fullname(?_contact) "                                      \
-       "nco:nameFamily(?_contact) "                                    \
-       "nco:nameGiven(?_contact) "                                     \
-       "nco:nameAdditional(?_contact) "                                \
-       "nco:nameHonorificPrefix(?_contact) "                           \
-       "nco:nameHonorificSuffix(?_contact) "                           \
-"(SELECT GROUP_CONCAT(fn:concat("                                      \
-       "tracker:coalesce(nco:pobox(?aff_addr), \"\"), \"\37\","        \
-       "tracker:coalesce(nco:extendedAddress(?aff_addr), \"\"), \"\37\","\
-       "tracker:coalesce(nco:streetAddress(?aff_addr), \"\"), \"\37\","\
-       "tracker:coalesce(nco:locality(?aff_addr), \"\"), \"\37\","     \
-       "tracker:coalesce(nco:region(?aff_addr), \"\"), \"\37\","       \
-       "tracker:coalesce(nco:postalcode(?aff_addr), \"\"), \"\37\","   \
-       "tracker:coalesce(nco:country(?aff_addr), \"\"), "              \
-       "\"\31\", rdfs:label(?c_role) ), "                              \
-       "\"\30\") "                                                     \
-       "WHERE {"                                                       \
-       "?_contact nco:hasAffiliation ?c_role . "                       \
-       "?c_role nco:hasPostalAddress ?aff_addr"                        \
-       "}) "                                                           \
-       "nco:birthDate(?_contact) "                                     \
-"(SELECT "                                                             \
-       "?nick "                                                        \
-       "WHERE { "                                                      \
-       "       { "                                                     \
-       "       ?_contact nco:nickname ?nick "                          \
-       "               } UNION { "                                     \
-       "                       ?_contact nco:hasAffiliation ?role . "  \
-       "                       ?role nco:hasIMAddress ?im . "          \
-       "                       ?im nco:imNickname ?nick "              \
-       "               } "                                             \
-       "       } "                                                     \
-       ") "                                                            \
-"(SELECT GROUP_CONCAT(fn:concat(?url_value, \"\31\", "                 \
-       "tracker:coalesce(rdfs:label(?c_role), \"\")), \"\30\") "       \
-       "WHERE {"                                                       \
-               "?_contact nco:hasAffiliation ?c_role . "               \
-               "?c_role nco:url ?url_value . "                         \
-"})"                                                                   \
-       "nie:url(nco:photo(?_contact)) "                                \
-       "nco:role(?_role) "                                             \
-       "nco:contactUID(?_contact) "                                    \
-       "nco:title(?_role) "                                            \
-       "rdfs:label(?_role) "                                           \
-       "nco:fullname(nco:org(?_role)) "                                \
-       "nco:department(?_role) "                                       \
-"(SELECT GROUP_CONCAT(fn:concat(?emailaddress,\"\31\","                        \
-       "tracker:coalesce(rdfs:label(?c_role), \"\")),"                 \
-       "\"\30\") "                                                     \
-       "WHERE { "                                                      \
-       "?_contact nco:hasAffiliation ?c_role . "                       \
-       "?c_role nco:hasEmailAddress "                                  \
-       "               [ nco:emailAddress ?emailaddress ] "            \
-       "}) "                                                           \
-       "nmo:receivedDate(?_call) "                                     \
-       "nmo:isSent(?_call) "                                           \
-       "nmo:isAnswered(?_call) "                                       \
-       "?_call "                                                       \
-CALLS_CONSTRAINTS(CONSTRAINT)                                          \
-"ORDER BY DESC(nmo:sentDate(?_call)) "
-
-#define MISSED_CONSTRAINT              \
-"?_call nmo:from ?_unb_contact . "     \
-"?_call nmo:isSent false . "           \
-"?_call nmo:isAnswered false . "
-
-#define INCOMING_CONSTRAINT            \
-"?_call nmo:from ?_unb_contact . "     \
-"?_call nmo:isSent false . "           \
-"?_call nmo:isAnswered true . "
-
-#define OUTGOING_CONSTRAINT            \
-"?_call nmo:to ?_unb_contact . "       \
-"?_call nmo:isSent true . "
-
-#define COMBINED_CONSTRAINT                    \
-"{ "                                           \
-"      ?_call nmo:from ?_unb_contact .  "      \
-"      ?_call nmo:isSent false "               \
-"} UNION { "                                   \
-"      ?_call nmo:to ?_unb_contact . "         \
-"      ?_call nmo:isSent true "                \
-"} "
-
-#define CALL_URI_CONSTRAINT    \
-COMBINED_CONSTRAINT            \
-"FILTER (?_call = <%s>) "
-
-#define MISSED_CALLS_QUERY CALLS_QUERY(MISSED_CONSTRAINT)
-#define MISSED_CALLS_LIST CALLS_LIST(MISSED_CONSTRAINT)
-#define INCOMING_CALLS_QUERY CALLS_QUERY(INCOMING_CONSTRAINT)
-#define INCOMING_CALLS_LIST CALLS_LIST(INCOMING_CONSTRAINT)
-#define OUTGOING_CALLS_QUERY CALLS_QUERY(OUTGOING_CONSTRAINT)
-#define OUTGOING_CALLS_LIST CALLS_LIST(OUTGOING_CONSTRAINT)
-#define COMBINED_CALLS_QUERY CALLS_QUERY(COMBINED_CONSTRAINT)
-#define COMBINED_CALLS_LIST CALLS_LIST(COMBINED_CONSTRAINT)
-#define CONTACT_FROM_CALL_QUERY CALLS_QUERY(CALL_URI_CONSTRAINT)
-
-#define CONTACTS_QUERY_FROM_URI                                                \
-"SELECT "                                                              \
-"(SELECT GROUP_CONCAT(fn:concat(rdf:type(?aff_number),"                        \
-"\"\31\", nco:phoneNumber(?aff_number)), \"\30\")"                     \
-"WHERE {"                                                              \
-"      ?_role nco:hasPhoneNumber ?aff_number"                          \
-"}) "                                                                  \
-"nco:fullname(<%s>) "                                                  \
-"nco:nameFamily(<%s>) "                                                        \
-"nco:nameGiven(<%s>) "                                                 \
-"nco:nameAdditional(<%s>) "                                            \
-"nco:nameHonorificPrefix(<%s>) "                                       \
-"nco:nameHonorificSuffix(<%s>) "                                       \
-"(SELECT GROUP_CONCAT(fn:concat("                                      \
-"tracker:coalesce(nco:pobox(?aff_addr), \"\"), \"\37\","               \
-"tracker:coalesce(nco:extendedAddress(?aff_addr), \"\"), \"\37\","     \
-"tracker:coalesce(nco:streetAddress(?aff_addr), \"\"), \"\37\","       \
-"tracker:coalesce(nco:locality(?aff_addr), \"\"), \"\37\","            \
-"tracker:coalesce(nco:region(?aff_addr), \"\"), \"\37\","              \
-"tracker:coalesce(nco:postalcode(?aff_addr), \"\"), \"\37\","          \
-"tracker:coalesce(nco:country(?aff_addr), \"\"), "                     \
-"\"\31\", rdfs:label(?_role) ), "                                      \
-"\"\30\") "                                                            \
-"WHERE {"                                                              \
-"?_role nco:hasPostalAddress ?aff_addr"                                        \
-"}) "                                                                  \
-"nco:birthDate(<%s>) "                                                 \
-"(SELECT "                                                             \
-"      ?nick "                                                         \
-"      WHERE { "                                                       \
-"              { "                                                     \
-"                      ?_contact nco:nickname ?nick "                  \
-"              } UNION { "                                             \
-"                      ?_contact nco:hasAffiliation ?role . "          \
-"                      ?role nco:hasIMAddress ?im . "                  \
-"                      ?im nco:imNickname ?nick "                      \
-"              } "                                                     \
-"              FILTER (?_contact = <%s>)"                              \
-"      } "                                                             \
-") "                                                                   \
-"(SELECT GROUP_CONCAT(fn:concat( "                                     \
-       "?url_val, \"\31\", tracker:coalesce(rdfs:label(?_role), \"\") "\
-       "), \"\30\") "                                                  \
-       "WHERE {"                                                       \
-               "?_role nco:url ?url_val . "                            \
-"})"                                                                   \
-"nie:url(nco:photo(<%s>)) "                                            \
-"nco:role(?_role) "                                                    \
-"nco:contactUID(<%s>) "                                                        \
-"nco:title(?_role) "                                                   \
-"rdfs:label(?_role) "                                                  \
-"nco:fullname(nco:org(?_role))"                                                \
-"nco:department(?_role) "                                              \
-"(SELECT GROUP_CONCAT(fn:concat(?emailaddress,\"\31\","                        \
-       "tracker:coalesce(rdfs:label(?_role), \"\")),"                  \
-       "\"\30\") "                                                     \
-       "WHERE { "                                                      \
-       "?_role nco:hasEmailAddress "                                   \
-       "               [ nco:emailAddress ?emailaddress ] "            \
-       "}) "                                                           \
-"\"NOTACALL\" \"false\" \"false\" "                                    \
-"<%s> "                                                                        \
-"WHERE {"                                                              \
-"      <%s> a nco:PersonContact ."                                     \
-"      OPTIONAL {<%s> nco:hasAffiliation ?_role .}"                    \
-"}"
-
-#define CONTACTS_OTHER_QUERY_FROM_URI                                  \
-       "SELECT fn:concat(\"TYPE_OTHER\", \"\31\", nco:phoneNumber(?t))"\
-       "\"\" \"\" \"\" \"\" \"\" \"\" \"\" \"\" "                      \
-       "\"\" \"\" \"\" \"\" \"\" \"\" \"\" \"\" \"\" \"\" "            \
-       " \"NOTACALL\" \"false\" \"false\" <%s> "                       \
-       "WHERE { "                                                      \
-               "<%s> a nco:Contact . "                                 \
-               "OPTIONAL { <%s> nco:hasPhoneNumber ?t . } "            \
-       "} "
-
-#define CONTACTS_COUNT_QUERY                                           \
-       "SELECT COUNT(?c) "                                             \
-       "WHERE {"                                                       \
-               "?c a nco:PersonContact ."                              \
-       "}"
-
-#define MISSED_CALLS_COUNT_QUERY                                       \
-       "SELECT COUNT(?call) WHERE {"                                   \
-               "?c a nco:Contact ;"                                    \
-               "nco:hasPhoneNumber ?h ."                               \
-               "?call a nmo:Call ;"                                    \
-               "nmo:isSent false ;"                                    \
-               "nmo:from ?c ;"                                         \
-               "nmo:isAnswered false ."                                \
-       "}"
-
-#define INCOMING_CALLS_COUNT_QUERY                                     \
-       "SELECT COUNT(?call) WHERE {"                                   \
-               "?c a nco:Contact ;"                                    \
-               "nco:hasPhoneNumber ?h ."                               \
-               "?call a nmo:Call ;"                                    \
-               "nmo:isSent false ;"                                    \
-               "nmo:from ?c ;"                                         \
-               "nmo:isAnswered true ."                                 \
-       "}"
-
-#define OUTGOING_CALLS_COUNT_QUERY                                     \
-       "SELECT COUNT(?call) WHERE {"                                   \
-               "?c a nco:Contact ;"                                    \
-               "nco:hasPhoneNumber ?h ."                               \
-               "?call a nmo:Call ;"                                    \
-               "nmo:isSent true ;"                                     \
-               "nmo:to ?c ."                                           \
-       "}"
-
-#define COMBINED_CALLS_COUNT_QUERY                                     \
-       "SELECT COUNT(?call) WHERE {"                                   \
-       "{"                                                             \
-               "?c a nco:Contact ;"                                    \
-               "nco:hasPhoneNumber ?h ."                               \
-               "?call a nmo:Call ;"                                    \
-               "nmo:isSent true ;"                                     \
-               "nmo:to ?c ."                                           \
-       "}UNION {"                                                      \
-               "?c a nco:Contact ;"                                    \
-               "nco:hasPhoneNumber ?h ."                               \
-               "?call a nmo:Call ;"                                    \
-               "nmo:from ?c ."                                         \
-       "}"                                                             \
-       "}"
-
-#define NEW_MISSED_CALLS_COUNT_QUERY                                   \
-       "SELECT COUNT(?call) WHERE {"                                   \
-               "?c a nco:Contact ;"                                    \
-               "nco:hasPhoneNumber ?h ."                               \
-               "?call a nmo:Call ;"                                    \
-               "nmo:isSent false ;"                                    \
-               "nmo:from ?c ;"                                         \
-               "nmo:isAnswered false ;"                                \
-               "nmo:isRead false ."                                    \
-       "}"
-
-typedef int (*reply_list_foreach_t) (const char **reply, int num_fields,
-                                                       void *user_data);
-
-typedef void (*add_field_t) (struct phonebook_contact *contact,
-                                               const char *value, int type);
-
-struct pending_reply {
-       reply_list_foreach_t callback;
-       void *user_data;
-       int num_fields;
-};
-
-struct contact_data {
-       char *id;
-       struct phonebook_contact *contact;
-};
-
-struct phonebook_data {
-       phonebook_cb cb;
-       void *user_data;
-       int index;
-       gboolean vcardentry;
-       const struct apparam_field *params;
-       GSList *contacts;
-       phonebook_cache_ready_cb ready_cb;
-       phonebook_entry_cb entry_cb;
-       int newmissedcalls;
-       GCancellable *query_canc;
-       char *req_name;
-       int vcard_part_count;
-       int tracker_index;
-};
-
-struct phonebook_index {
-       GArray *phonebook;
-       int index;
-};
-
-static TrackerSparqlConnection *connection = NULL;
-
-static const char *name2query(const char *name)
-{
-       if (g_str_equal(name, PB_CONTACTS))
-               return CONTACTS_QUERY_ALL;
-       else if (g_str_equal(name, PB_CALLS_INCOMING))
-               return INCOMING_CALLS_QUERY;
-       else if (g_str_equal(name, PB_CALLS_OUTGOING))
-               return OUTGOING_CALLS_QUERY;
-       else if (g_str_equal(name, PB_CALLS_MISSED))
-               return MISSED_CALLS_QUERY;
-       else if (g_str_equal(name, PB_CALLS_COMBINED))
-               return COMBINED_CALLS_QUERY;
-
-       return NULL;
-}
-
-static const char *name2count_query(const char *name)
-{
-       if (g_str_equal(name, PB_CONTACTS))
-               return CONTACTS_COUNT_QUERY;
-       else if (g_str_equal(name, PB_CALLS_INCOMING))
-               return INCOMING_CALLS_COUNT_QUERY;
-       else if (g_str_equal(name, PB_CALLS_OUTGOING))
-               return OUTGOING_CALLS_COUNT_QUERY;
-       else if (g_str_equal(name, PB_CALLS_MISSED))
-               return MISSED_CALLS_COUNT_QUERY;
-       else if (g_str_equal(name, PB_CALLS_COMBINED))
-               return COMBINED_CALLS_COUNT_QUERY;
-
-       return NULL;
-}
-
-static gboolean folder_is_valid(const char *folder)
-{
-       if (folder == NULL)
-               return FALSE;
-
-       if (g_str_equal(folder, "/"))
-               return TRUE;
-       else if (g_str_equal(folder, PB_TELECOM_FOLDER))
-               return TRUE;
-       else if (g_str_equal(folder, PB_CONTACTS_FOLDER))
-               return TRUE;
-       else if (g_str_equal(folder, PB_CALLS_INCOMING_FOLDER))
-               return TRUE;
-       else if (g_str_equal(folder, PB_CALLS_OUTGOING_FOLDER))
-               return TRUE;
-       else if (g_str_equal(folder, PB_CALLS_MISSED_FOLDER))
-               return TRUE;
-       else if (g_str_equal(folder, PB_CALLS_COMBINED_FOLDER))
-               return TRUE;
-
-       return FALSE;
-}
-
-static const char *folder2query(const char *folder)
-{
-       if (g_str_equal(folder, PB_CONTACTS_FOLDER))
-               return CONTACTS_QUERY_ALL_LIST;
-       else if (g_str_equal(folder, PB_CALLS_INCOMING_FOLDER))
-               return INCOMING_CALLS_LIST;
-       else if (g_str_equal(folder, PB_CALLS_OUTGOING_FOLDER))
-               return OUTGOING_CALLS_LIST;
-       else if (g_str_equal(folder, PB_CALLS_MISSED_FOLDER))
-               return MISSED_CALLS_LIST;
-       else if (g_str_equal(folder, PB_CALLS_COMBINED_FOLDER))
-               return COMBINED_CALLS_LIST;
-
-       return NULL;
-}
-
-static const char **string_array_from_cursor(TrackerSparqlCursor *cursor,
-                                                               int array_len)
-{
-       const char **result;
-       int i;
-
-       result = g_new0(const char *, array_len);
-
-       for (i = 0; i < array_len; ++i) {
-               TrackerSparqlValueType type;
-
-               type = tracker_sparql_cursor_get_value_type(cursor, i);
-
-               if (type == TRACKER_SPARQL_VALUE_TYPE_BLANK_NODE ||
-                               type == TRACKER_SPARQL_VALUE_TYPE_UNBOUND)
-                       /* For null/unbound type filling result part with ""*/
-                       result[i] = "";
-               else
-                       /* Filling with string representation of content*/
-                       result[i] = tracker_sparql_cursor_get_string(cursor, i,
-                                                                       NULL);
-       }
-
-       return result;
-}
-
-static void update_cancellable(struct phonebook_data *pdata,
-                                                       GCancellable *canc)
-{
-       if (pdata->query_canc)
-               g_object_unref(pdata->query_canc);
-
-       pdata->query_canc = canc;
-}
-
-static void async_query_cursor_next_cb(GObject *source, GAsyncResult *result,
-                                                       gpointer user_data)
-{
-       struct pending_reply *pending = user_data;
-       TrackerSparqlCursor *cursor = TRACKER_SPARQL_CURSOR(source);
-       GCancellable *cancellable;
-       GError *error = NULL;
-       gboolean success;
-       const char **node;
-       int err;
-
-       success = tracker_sparql_cursor_next_finish(
-                                               TRACKER_SPARQL_CURSOR(source),
-                                               result, &error);
-
-       if (!success) {
-               if (error) {
-                       DBG("cursor_next error: %s", error->message);
-                       g_error_free(error);
-               } else
-                       /* When tracker_sparql_cursor_next_finish ends with
-                        * failure and no error is set, that means end of
-                        * results returned by query */
-                       pending->callback(NULL, 0, pending->user_data);
-
-               goto failed;
-       }
-
-       node = string_array_from_cursor(cursor, pending->num_fields);
-       err = pending->callback(node, pending->num_fields, pending->user_data);
-       g_free(node);
-
-       /* Fetch next result only if processing current chunk ended with
-        * success. Sometimes during processing data, we are able to determine
-        * if there is no need to get more data from tracker - by example
-        * stored amount of data parts is big enough for sending and we might
-        * want to suspend processing or just some error occurred. */
-       if (!err) {
-               cancellable = g_cancellable_new();
-               update_cancellable(pending->user_data, cancellable);
-               tracker_sparql_cursor_next_async(cursor, cancellable,
-                                               async_query_cursor_next_cb,
-                                               pending);
-               return;
-       }
-
-failed:
-       g_object_unref(cursor);
-       g_free(pending);
-}
-
-static int query_tracker(const char *query, int num_fields,
-                               reply_list_foreach_t callback, void *user_data)
-{
-       struct pending_reply *pending;
-       GCancellable *cancellable;
-       TrackerSparqlCursor *cursor;
-       GError *error = NULL;
-
-       DBG("");
-
-       if (connection == NULL)
-               connection = tracker_sparql_connection_get_direct(
-                                                               NULL, &error);
-
-       if (!connection) {
-               if (error) {
-                       DBG("direct-connection error: %s", error->message);
-                       g_error_free(error);
-               }
-
-               return -EINTR;
-       }
-
-       cancellable = g_cancellable_new();
-       update_cancellable(user_data, cancellable);
-       cursor = tracker_sparql_connection_query(connection, query,
-                                                       cancellable, &error);
-
-       if (cursor == NULL) {
-               if (error) {
-                       DBG("connection_query error: %s", error->message);
-                       g_error_free(error);
-               }
-
-               g_object_unref(cancellable);
-
-               return -EINTR;
-       }
-
-       pending = g_new0(struct pending_reply, 1);
-       pending->callback = callback;
-       pending->user_data = user_data;
-       pending->num_fields = num_fields;
-
-       /* Now asynchronously going through each row of results - callback
-        * async_query_cursor_next_cb will be called ALWAYS, even if async
-        * request was canceled */
-       tracker_sparql_cursor_next_async(cursor, cancellable,
-                                               async_query_cursor_next_cb,
-                                               pending);
-
-       return 0;
-}
-
-static char *iso8601_utc_to_localtime(const char *datetime)
-{
-       time_t time;
-       struct tm tm, *local;
-       char localdate[32];
-       int nr;
-
-       memset(&tm, 0, sizeof(tm));
-
-       nr = sscanf(datetime, "%04u-%02u-%02uT%02u:%02u:%02u",
-                       &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
-                       &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
-       if (nr < 6) {
-               /* Invalid time format */
-               error("sscanf(): %s (%d)", strerror(errno), errno);
-               return g_strdup("");
-       }
-
-       /* Time already in localtime */
-       if (!g_str_has_suffix(datetime, "Z")) {
-               strftime(localdate, sizeof(localdate), "%Y%m%dT%H%M%S", &tm);
-               return g_strdup(localdate);
-       }
-
-       tm.tm_year -= 1900;     /* Year since 1900 */
-       tm.tm_mon--;            /* Months since January, values 0-11 */
-
-       time = mktime(&tm);
-       time -= timezone;
-
-       local = localtime(&time);
-
-       strftime(localdate, sizeof(localdate), "%Y%m%dT%H%M%S", local);
-
-       return g_strdup(localdate);
-}
-
-static void set_call_type(struct phonebook_contact *contact,
-                               const char *datetime, const char *is_sent,
-                               const char *is_answered)
-{
-       gboolean sent, answered;
-
-       if (g_strcmp0(datetime, "NOTACALL") == 0) {
-               contact->calltype = CALL_TYPE_NOT_A_CALL;
-               return;
-       }
-
-       sent = g_str_equal(is_sent, "true");
-       answered = g_str_equal(is_answered, "true");
-
-       if (sent == FALSE) {
-               if (answered == FALSE)
-                       contact->calltype = CALL_TYPE_MISSED;
-               else
-                       contact->calltype = CALL_TYPE_INCOMING;
-       } else
-               contact->calltype = CALL_TYPE_OUTGOING;
-
-       /* Tracker gives time in the ISO 8601 format, UTC time */
-       contact->datetime = iso8601_utc_to_localtime(datetime);
-}
-
-static gboolean contact_matches(struct contact_data *c_data, const char *id,
-                                                       const char *datetime)
-{
-       char *localtime;
-       int cmp_ret;
-
-       if (g_strcmp0(c_data->id, id) != 0)
-               return FALSE;
-
-       /* id is equal and not call history entry => contact matches */
-       if (c_data->contact->calltype == CALL_TYPE_NOT_A_CALL)
-               return TRUE;
-
-       /* for call history entries have to compare also timestamps of calls */
-       localtime = iso8601_utc_to_localtime(datetime);
-       cmp_ret = g_strcmp0(c_data->contact->datetime, localtime);
-       g_free(localtime);
-
-       return (cmp_ret == 0) ? TRUE : FALSE;
-}
-
-static struct phonebook_contact *find_contact(GSList *contacts, const char *id,
-                                                       const char *datetime)
-{
-       GSList *l;
-
-       for (l = contacts; l; l = l->next) {
-               struct contact_data *c_data = l->data;
-
-               if (contact_matches(c_data, id, datetime))
-                       return c_data->contact;
-       }
-
-       return NULL;
-}
-
-static struct phonebook_field *find_field(GSList *fields, const char *value,
-                                                               int type)
-{
-       GSList *l;
-
-       for (l = fields; l; l = l->next) {
-               struct phonebook_field *field = l->data;
-               /* Returning phonebook number if phone values and type values
-                * are equal */
-               if (g_strcmp0(field->text, value) == 0 && field->type == type)
-                       return field;
-       }
-
-       return NULL;
-}
-
-static void add_phone_number(struct phonebook_contact *contact,
-                                               const char *phone, int type)
-{
-       struct phonebook_field *number;
-
-       if (phone == NULL || strlen(phone) == 0)
-               return;
-
-       /* Not adding number if there is already added with the same value */
-       if (find_field(contact->numbers, phone, type))
-               return;
-
-       number = g_new0(struct phonebook_field, 1);
-       number->text = g_strdup(phone);
-       number->type = type;
-
-       contact->numbers = g_slist_append(contact->numbers, number);
-}
-
-static void add_email(struct phonebook_contact *contact, const char *address,
-                                                               int type)
-{
-       struct phonebook_field *email;
-
-       if (address == NULL || strlen(address) == 0)
-               return;
-
-       /* Not adding email if there is already added with the same value */
-       if (find_field(contact->emails, address, type))
-               return;
-
-       email = g_new0(struct phonebook_field, 1);
-       email->text = g_strdup(address);
-       email->type = type;
-
-       contact->emails = g_slist_append(contact->emails, email);
-}
-
-static gboolean addr_matches(struct phonebook_addr *a, struct phonebook_addr *b)
-{
-       GSList *la, *lb;
-
-       if (a->type != b->type)
-               return FALSE;
-
-       for (la = a->fields, lb = b->fields; la && lb;
-                                               la = la->next, lb = lb->next) {
-               char *field_a = la->data;
-               char *field_b = lb->data;
-
-               if (g_strcmp0(field_a, field_b) != 0)
-                       return FALSE;
-       }
-
-       return TRUE;
-}
-
-/* generates phonebook_addr struct from tracker address data string. */
-static struct phonebook_addr *gen_addr(const char *address, int type)
-{
-       struct phonebook_addr *addr;
-       GSList *fields = NULL;
-       char **addr_parts;
-       int i;
-
-       /* This test handles cases when address points to empty string
-        * (or address is NULL pointer) or string containing only six
-        * separators. It indicates that none of address fields is present
-        * and there is no sense to create dummy phonebook_addr struct */
-       if (address == NULL || strlen(address) < ADDR_FIELD_AMOUNT)
-               return NULL;
-
-       addr_parts = g_strsplit(address, ADDR_DELIM, ADDR_FIELD_AMOUNT);
-
-       for (i = 0; i < ADDR_FIELD_AMOUNT; ++i)
-               fields = g_slist_append(fields, g_strdup(addr_parts[i]));
-
-       g_strfreev(addr_parts);
-
-       addr = g_new0(struct phonebook_addr, 1);
-       addr->fields = fields;
-       addr->type = type;
-
-       return addr;
-}
-
-static void add_address(struct phonebook_contact *contact,
-                                       const char *address, int type)
-{
-       struct phonebook_addr *addr;
-       GSList *l;
-
-       addr = gen_addr(address, type);
-       if (addr == NULL)
-               return;
-
-       /* Not adding address if there is already added with the same value.
-        * These type of checks have to be done because sometimes tracker
-        * returns results for contact data in more than 1 row - then the same
-        * address may be returned more than once in query results */
-       for (l = contact->addresses; l; l = l->next) {
-               struct phonebook_addr *tmp = l->data;
-
-               if (addr_matches(tmp, addr)) {
-                       phonebook_addr_free(addr);
-                       return;
-               }
-       }
-
-       contact->addresses = g_slist_append(contact->addresses, addr);
-}
-
-static void add_url(struct phonebook_contact *contact, const char *url_val,
-                                                               int type)
-{
-       struct phonebook_field *url;
-
-       if (url_val == NULL || strlen(url_val) == 0)
-               return;
-
-       /* Not adding url if there is already added with the same value */
-       if (find_field(contact->urls, url_val, type))
-               return;
-
-       url = g_new0(struct phonebook_field, 1);
-
-       url->text = g_strdup(url_val);
-       url->type = type;
-
-       contact->urls = g_slist_append(contact->urls, url);
-}
-
-static GString *gen_vcards(GSList *contacts,
-                                       const struct apparam_field *params)
-{
-       GSList *l;
-       GString *vcards;
-
-       vcards = g_string_new(NULL);
-
-       /* Generating VCARD string from contacts and freeing used contacts */
-       for (l = contacts; l; l = l->next) {
-               struct contact_data *c_data = l->data;
-               phonebook_add_contact(vcards, c_data->contact,
-                                       params->filter, params->format);
-       }
-
-       return vcards;
-}
-
-static int pull_contacts_size(const char **reply, int num_fields,
-                                                       void *user_data)
-{
-       struct phonebook_data *data = user_data;
-
-       if (num_fields < 0) {
-               data->cb(NULL, 0, num_fields, 0, TRUE, data->user_data);
-               return -EINTR;
-       }
-
-       if (reply != NULL) {
-               data->index = atoi(reply[0]);
-               return 0;
-       }
-
-       data->cb(NULL, 0, data->index, data->newmissedcalls, TRUE,
-                                                       data->user_data);
-
-       return 0;
-       /*
-        * phonebook_data is freed in phonebook_req_finalize. Useful in
-        * cases when call is terminated.
-        */
-}
-
-static void add_affiliation(char **field, const char *value)
-{
-       if (strlen(*field) > 0 || value == NULL || strlen(value) == 0)
-               return;
-
-       g_free(*field);
-
-       *field = g_strdup(value);
-}
-
-static void contact_init(struct phonebook_contact *contact,
-                                                       const char **reply)
-{
-       if (reply[COL_FAMILY_NAME][0] == '\0' &&
-                       reply[COL_GIVEN_NAME][0] == '\0' &&
-                       reply[COL_ADDITIONAL_NAME][0] == '\0' &&
-                       reply[COL_NAME_PREFIX][0] == '\0' &&
-                       reply[COL_NAME_SUFFIX][0] == '\0') {
-               if (reply[COL_FULL_NAME][0] != '\0')
-                       contact->family = g_strdup(reply[COL_FULL_NAME]);
-               else
-                       contact->family = g_strdup(reply[COL_NICKNAME]);
-       } else {
-               contact->family = g_strdup(reply[COL_FAMILY_NAME]);
-               contact->given = g_strdup(reply[COL_GIVEN_NAME]);
-               contact->additional = g_strdup(reply[COL_ADDITIONAL_NAME]);
-               contact->prefix = g_strdup(reply[COL_NAME_PREFIX]);
-               contact->suffix = g_strdup(reply[COL_NAME_SUFFIX]);
-       }
-       contact->fullname = g_strdup(reply[COL_FULL_NAME]);
-       contact->birthday = g_strdup(reply[COL_BIRTH_DATE]);
-       contact->nickname = g_strdup(reply[COL_NICKNAME]);
-       contact->photo = g_strdup(reply[COL_PHOTO]);
-       contact->company = g_strdup(reply[COL_ORG_NAME]);
-       contact->department = g_strdup(reply[COL_ORG_DEPARTMENT]);
-       contact->role = g_strdup(reply[COL_ORG_ROLE]);
-       contact->uid = g_strdup(reply[COL_UID]);
-       contact->title = g_strdup(reply[COL_TITLE]);
-
-       set_call_type(contact, reply[COL_DATE], reply[COL_SENT],
-                                                       reply[COL_ANSWERED]);
-}
-
-static enum phonebook_number_type get_phone_type(const char *affilation)
-{
-       if (g_strcmp0(AFFILATION_HOME, affilation) == 0)
-               return TEL_TYPE_HOME;
-       else if (g_strcmp0(AFFILATION_WORK, affilation) == 0)
-               return TEL_TYPE_WORK;
-
-       return TEL_TYPE_OTHER;
-}
-
-static void add_aff_number(struct phonebook_contact *contact,
-                               const char *pnumber, const char *aff_type)
-{
-       char **num_parts;
-       char *type, *number;
-
-       /* For phone taken directly from contacts data, phone number string
-        * is represented as number type and number string - those strings are
-        * separated by SUB_DELIM string */
-       num_parts = g_strsplit(pnumber, SUB_DELIM, 2);
-
-       if (!num_parts)
-               return;
-
-       if (num_parts[0])
-               type = num_parts[0];
-       else
-               goto failed;
-
-       if (num_parts[1])
-               number = num_parts[1];
-       else
-               goto failed;
-
-       if (g_strrstr(type, FAX_NUM_TYPE))
-               add_phone_number(contact, number, TEL_TYPE_FAX);
-       else if (g_strrstr(type, MOBILE_NUM_TYPE))
-               add_phone_number(contact, number, TEL_TYPE_MOBILE);
-       else
-               /* if this is no fax/mobile phone, then adding phone number
-                * type based on type of the affilation field */
-               add_phone_number(contact, number, get_phone_type(aff_type));
-
-failed:
-       g_strfreev(num_parts);
-}
-
-static void contact_add_numbers(struct phonebook_contact *contact,
-                                                       const char **reply)
-{
-       char **aff_numbers;
-       int i;
-
-       /* Filling phone numbers from contact's affilation */
-       aff_numbers = g_strsplit(reply[COL_PHONE_AFF], MAIN_DELIM, MAX_FIELDS);
-
-       if (aff_numbers)
-               for (i = 0; aff_numbers[i]; ++i)
-                       add_aff_number(contact, aff_numbers[i],
-                                                       reply[COL_AFF_TYPE]);
-
-       g_strfreev(aff_numbers);
-}
-
-static enum phonebook_field_type get_field_type(const char *affilation)
-{
-       if (g_strcmp0(AFFILATION_HOME, affilation) == 0)
-               return FIELD_TYPE_HOME;
-       else if (g_strcmp0(AFFILATION_WORK, affilation) == 0)
-               return FIELD_TYPE_WORK;
-
-       return FIELD_TYPE_OTHER;
-}
-
-static void add_aff_field(struct phonebook_contact *contact,
-                       const char *aff_email, add_field_t add_field_cb)
-{
-       char **email_parts;
-       char *type, *email;
-
-       /* Emails from affilation data, are represented as real email
-        * string and affilation type - those strings are separated by
-        * SUB_DELIM string */
-       email_parts = g_strsplit(aff_email, SUB_DELIM, 2);
-
-       if (!email_parts)
-               return;
-
-       if (email_parts[0])
-               email = email_parts[0];
-       else
-               goto failed;
-
-       if (email_parts[1])
-               type = email_parts[1];
-       else
-               goto failed;
-
-       add_field_cb(contact, email, get_field_type(type));
-
-failed:
-       g_strfreev(email_parts);
-}
-
-static void contact_add_emails(struct phonebook_contact *contact,
-                                                       const char **reply)
-{
-       char **aff_emails;
-       int i;
-
-       /* Emails from affilation */
-       aff_emails = g_strsplit(reply[COL_EMAIL_AFF], MAIN_DELIM, MAX_FIELDS);
-
-       if (aff_emails)
-               for (i = 0; aff_emails[i] != NULL; ++i)
-                       add_aff_field(contact, aff_emails[i], add_email);
-
-       g_strfreev(aff_emails);
-}
-
-static void contact_add_addresses(struct phonebook_contact *contact,
-                                                       const char **reply)
-{
-       char **aff_addr;
-       int i;
-
-       /* Addresses from affilation */
-       aff_addr = g_strsplit(reply[COL_ADDR_AFF], MAIN_DELIM, MAX_FIELDS);
-
-       if (aff_addr)
-               for (i = 0; aff_addr[i] != NULL; ++i)
-                       add_aff_field(contact, aff_addr[i], add_address);
-
-       g_strfreev(aff_addr);
-}
-
-static void contact_add_urls(struct phonebook_contact *contact,
-                                                       const char **reply)
-{
-       char **aff_url;
-       int i;
-
-       /* Addresses from affilation */
-       aff_url = g_strsplit(reply[COL_URL], MAIN_DELIM, MAX_FIELDS);
-
-       if (aff_url)
-               for (i = 0; aff_url[i] != NULL; ++i)
-                       add_aff_field(contact, aff_url[i], add_url);
-
-       g_strfreev(aff_url);
-}
-
-static void contact_add_organization(struct phonebook_contact *contact,
-                                                       const char **reply)
-{
-       /* Adding fields connected by nco:hasAffiliation - they may be in
-        * separate replies */
-       add_affiliation(&contact->title, reply[COL_TITLE]);
-       add_affiliation(&contact->company, reply[COL_ORG_NAME]);
-       add_affiliation(&contact->department, reply[COL_ORG_DEPARTMENT]);
-       add_affiliation(&contact->role, reply[COL_ORG_ROLE]);
-}
-
-static void free_data_contacts(struct phonebook_data *data)
-{
-       GSList *l;
-
-       /* freeing contacts */
-       for (l = data->contacts; l; l = l->next) {
-               struct contact_data *c_data = l->data;
-
-               g_free(c_data->id);
-               phonebook_contact_free(c_data->contact);
-               g_free(c_data);
-       }
-
-       g_slist_free(data->contacts);
-       data->contacts = NULL;
-}
-
-static void send_pull_part(struct phonebook_data *data,
-                       const struct apparam_field *params, gboolean lastpart)
-{
-       GString *vcards;
-
-       DBG("");
-       vcards = gen_vcards(data->contacts, params);
-       data->cb(vcards->str, vcards->len, g_slist_length(data->contacts),
-                       data->newmissedcalls, lastpart, data->user_data);
-
-       if (!lastpart)
-               free_data_contacts(data);
-       g_string_free(vcards, TRUE);
-}
-
-static int pull_contacts(const char **reply, int num_fields, void *user_data)
-{
-       struct phonebook_data *data = user_data;
-       const struct apparam_field *params = data->params;
-       struct phonebook_contact *contact;
-       struct contact_data *contact_data;
-       int last_index, i;
-       gboolean cdata_present = FALSE, part_sent = FALSE;
-       static char *temp_id = NULL;
-
-       if (num_fields < 0) {
-               data->cb(NULL, 0, num_fields, 0, TRUE, data->user_data);
-               goto fail;
-       }
-
-       DBG("reply %p", reply);
-       data->tracker_index++;
-
-       if (reply == NULL)
-               goto done;
-
-       /* Trying to find contact in recently added contacts. It is needed for
-        * contacts that have more than one telephone number filled */
-       contact = find_contact(data->contacts, reply[CONTACTS_ID_COL],
-                                                       reply[COL_DATE]);
-
-       /* If contact is already created then adding only new phone numbers */
-       if (contact) {
-               cdata_present = TRUE;
-               goto add_numbers;
-       }
-
-       /* We are doing a PullvCardEntry, no need for those checks */
-       if (data->vcardentry)
-               goto add_entry;
-
-       /* Last four fields are always present, ignoring them */
-       for (i = 0; i < num_fields - 4; i++) {
-               if (reply[i][0] != '\0')
-                       break;
-       }
-
-       if (i == num_fields - 4 && !g_str_equal(reply[CONTACTS_ID_COL],
-                                               TRACKER_DEFAULT_CONTACT_ME))
-               return 0;
-
-       if (g_strcmp0(temp_id, reply[CONTACTS_ID_COL])) {
-               data->index++;
-               g_free(temp_id);
-               temp_id = g_strdup(reply[CONTACTS_ID_COL]);
-
-               /* Incrementing counter for vcards in current part of data,
-                * but only if liststartoffset has been already reached */
-               if (data->index > params->liststartoffset)
-                       data->vcard_part_count++;
-       }
-
-       if (data->vcard_part_count > VCARDS_PART_COUNT) {
-               DBG("Part of vcard data ready for sending...");
-               data->vcard_part_count = 0;
-               /* Sending part of data to PBAP core - more data can be still
-                * fetched, so marking lastpart as FALSE */
-               send_pull_part(data, params, FALSE);
-
-               /* Later, after adding contact data, need to return -EINTR to
-                * stop fetching more data for this request. Data will be
-                * downloaded again from this point, when phonebook_pull_read
-                * will be called again with current request as a parameter*/
-               part_sent = TRUE;
-       }
-
-       last_index = params->liststartoffset + params->maxlistcount;
-
-       if (data->index <= params->liststartoffset)
-               return 0;
-
-       /* max number of results achieved - need send vcards data that was
-        * already collected and stop further data processing (these operations
-        * will be invoked in "done" section) */
-       if (data->index > last_index && params->maxlistcount > 0) {
-               DBG("Maxlistcount achieved");
-               goto done;
-       }
-
-add_entry:
-       contact = g_new0(struct phonebook_contact, 1);
-       contact_init(contact, reply);
-
-add_numbers:
-       contact_add_numbers(contact, reply);
-       contact_add_emails(contact, reply);
-       contact_add_addresses(contact, reply);
-       contact_add_urls(contact, reply);
-       contact_add_organization(contact, reply);
-
-       DBG("contact %p", contact);
-
-       /* Adding contacts data to wrapper struct - this data will be used to
-        * generate vcard list */
-       if (!cdata_present) {
-               contact_data = g_new0(struct contact_data, 1);
-               contact_data->contact = contact;
-               contact_data->id = g_strdup(reply[CONTACTS_ID_COL]);
-               data->contacts = g_slist_append(data->contacts, contact_data);
-       }
-
-       if (part_sent)
-               return -EINTR;
-
-       return 0;
-
-done:
-       /* Processing is end, this is definitely last part of transmission
-        * (marking lastpart as TRUE) */
-       send_pull_part(data, params, TRUE);
-
-fail:
-       g_free(temp_id);
-       temp_id = NULL;
-
-       return -EINTR;
-       /*
-        * phonebook_data is freed in phonebook_req_finalize. Useful in
-        * cases when call is terminated.
-        */
-}
-
-static int add_to_cache(const char **reply, int num_fields, void *user_data)
-{
-       struct phonebook_data *data = user_data;
-       char *formatted;
-       int i;
-
-       if (reply == NULL || num_fields < 0)
-               goto done;
-
-       /* the first element is the URI, always not empty */
-       for (i = 1; i < num_fields; i++) {
-               if (reply[i][0] != '\0')
-                       break;
-       }
-
-       if (i == num_fields &&
-                       !g_str_equal(reply[0], TRACKER_DEFAULT_CONTACT_ME))
-               return 0;
-
-       if (i == 7)
-               formatted = g_strdup(reply[7]);
-       else if (i == 6)
-               formatted = g_strdup(reply[6]);
-       else
-               formatted = g_strdup_printf("%s;%s;%s;%s;%s",
-                                       reply[1], reply[2], reply[3], reply[4],
-                                       reply[5]);
-
-       /* The owner vCard must have the 0 handle */
-       if (strcmp(reply[0], TRACKER_DEFAULT_CONTACT_ME) == 0)
-               data->entry_cb(reply[0], 0, formatted, "",
-                                               reply[6], data->user_data);
-       else
-               data->entry_cb(reply[0], PHONEBOOK_INVALID_HANDLE, formatted,
-                                       "", reply[6], data->user_data);
-
-       g_free(formatted);
-
-       return 0;
-
-done:
-       if (num_fields <= 0)
-               data->ready_cb(data->user_data);
-
-       return -EINTR;
-       /*
-        * phonebook_data is freed in phonebook_req_finalize. Useful in
-        * cases when call is terminated.
-        */
-}
-
-int phonebook_init(void)
-{
-       g_thread_init(NULL);
-       g_type_init();
-
-       return 0;
-}
-
-void phonebook_exit(void)
-{
-}
-
-char *phonebook_set_folder(const char *current_folder, const char *new_folder,
-                                               uint8_t flags, int *err)
-{
-       char *tmp1, *tmp2, *base, *path = NULL;
-       gboolean root, child;
-       int ret = 0;
-       int len;
-
-       root = (g_strcmp0("/", current_folder) == 0);
-       child = (new_folder && strlen(new_folder) != 0);
-
-       switch (flags) {
-       case 0x02:
-               /* Go back to root */
-               if (!child) {
-                       path = g_strdup("/");
-                       goto done;
-               }
-
-               path = g_build_filename(current_folder, new_folder, NULL);
-               break;
-       case 0x03:
-               /* Go up 1 level */
-               if (root) {
-                       /* Already root */
-                       path = g_strdup("/");
-                       goto done;
-               }
-
-               /*
-                * Removing one level of the current folder. Current folder
-                * contains AT LEAST one level since it is not at root folder.
-                * Use glib utility functions to handle invalid chars in the
-                * folder path properly.
-                */
-               tmp1 = g_path_get_basename(current_folder);
-               tmp2 = g_strrstr(current_folder, tmp1);
-               len = tmp2 - (current_folder + 1);
-
-               g_free(tmp1);
-
-               if (len == 0)
-                       base = g_strdup("/");
-               else
-                       base = g_strndup(current_folder, len);
-
-               /* Return: one level only */
-               if (!child) {
-                       path = base;
-                       goto done;
-               }
-
-               path = g_build_filename(base, new_folder, NULL);
-               g_free(base);
-
-               break;
-       default:
-               ret = -EBADR;
-               break;
-       }
-
-done:
-       if (path && !folder_is_valid(path))
-               ret = -ENOENT;
-
-       if (ret < 0) {
-               g_free(path);
-               path = NULL;
-       }
-
-       if (err)
-               *err = ret;
-
-       return path;
-}
-
-static int pull_newmissedcalls(const char **reply, int num_fields,
-                                                       void *user_data)
-{
-       struct phonebook_data *data = user_data;
-       reply_list_foreach_t pull_cb;
-       int col_amount, err;
-       const char *query;
-       int nmissed;
-
-       if (num_fields < 0) {
-               data->cb(NULL, 0, num_fields, 0, TRUE, data->user_data);
-
-               return -EINTR;
-       }
-
-       if (reply != NULL) {
-               nmissed = atoi(reply[0]);
-               data->newmissedcalls =
-                       nmissed <= UINT8_MAX ? nmissed : UINT8_MAX;
-               DBG("newmissedcalls %d", data->newmissedcalls);
-
-               return 0;
-       }
-
-       if (data->params->maxlistcount == 0) {
-               query = name2count_query(PB_CALLS_MISSED);
-               col_amount = COUNT_QUERY_COL_AMOUNT;
-               pull_cb = pull_contacts_size;
-       } else {
-               query = name2query(PB_CALLS_MISSED);
-               col_amount = PULL_QUERY_COL_AMOUNT;
-               pull_cb = pull_contacts;
-       }
-
-       err = query_tracker(query, col_amount, pull_cb, data);
-       if (err < 0) {
-               data->cb(NULL, 0, err, 0, TRUE, data->user_data);
-
-               return -EINTR;
-       }
-
-       return 0;
-}
-
-void phonebook_req_finalize(void *request)
-{
-       struct phonebook_data *data = request;
-
-       DBG("");
-
-       if (!data)
-               return;
-
-       /* canceling asynchronous operation on tracker if any is active */
-       if (data->query_canc) {
-               g_cancellable_cancel(data->query_canc);
-               g_object_unref(data->query_canc);
-       }
-
-       free_data_contacts(data);
-       g_free(data->req_name);
-       g_free(data);
-}
-
-void *phonebook_pull(const char *name, const struct apparam_field *params,
-                               phonebook_cb cb, void *user_data, int *err)
-{
-       struct phonebook_data *data;
-
-       DBG("name %s", name);
-
-       data = g_new0(struct phonebook_data, 1);
-       data->params = params;
-       data->user_data = user_data;
-       data->cb = cb;
-       data->req_name = g_strdup(name);
-
-       if (err)
-               *err = 0;
-
-       return data;
-}
-
-int phonebook_pull_read(void *request)
-{
-       struct phonebook_data *data = request;
-       reply_list_foreach_t pull_cb;
-       const char *query;
-       char *offset_query;
-       int col_amount;
-       int ret;
-
-       if (!data)
-               return -ENOENT;
-
-       data->newmissedcalls = 0;
-
-       if (g_strcmp0(data->req_name, PB_CALLS_MISSED) == 0 &&
-                                               data->tracker_index == 0) {
-               /* new missed calls amount should be counted only once - it
-                * will be done during generating first part of results of
-                * missed calls history */
-               query = NEW_MISSED_CALLS_COUNT_QUERY;
-               col_amount = COUNT_QUERY_COL_AMOUNT;
-               pull_cb = pull_newmissedcalls;
-       } else if (data->params->maxlistcount == 0) {
-               query = name2count_query(data->req_name);
-               col_amount = COUNT_QUERY_COL_AMOUNT;
-               pull_cb = pull_contacts_size;
-       } else {
-               query = name2query(data->req_name);
-               col_amount = PULL_QUERY_COL_AMOUNT;
-               pull_cb = pull_contacts;
-       }
-
-       if (query == NULL)
-               return -ENOENT;
-
-       if (pull_cb == pull_contacts && data->tracker_index > 0) {
-               /* Adding offset to pull query to download next parts of data
-                * from tracker (phonebook_pull_read may be called many times
-                * from PBAP core to fetch data partially) */
-               offset_query = g_strdup_printf(QUERY_OFFSET_FORMAT, query,
-                                                       data->tracker_index);
-               ret = query_tracker(offset_query, col_amount, pull_cb, data);
-
-               g_free(offset_query);
-
-               return ret;
-       }
-
-       return query_tracker(query, col_amount, pull_cb, data);
-}
-
-void *phonebook_get_entry(const char *folder, const char *id,
-                               const struct apparam_field *params,
-                               phonebook_cb cb, void *user_data, int *err)
-{
-       struct phonebook_data *data;
-       char *query;
-       int ret;
-
-       DBG("folder %s id %s", folder, id);
-
-       data = g_new0(struct phonebook_data, 1);
-       data->user_data = user_data;
-       data->params = params;
-       data->cb = cb;
-       data->vcardentry = TRUE;
-
-       if (g_str_has_prefix(id, CONTACT_ID_PREFIX) == TRUE ||
-                               g_strcmp0(id, TRACKER_DEFAULT_CONTACT_ME) == 0)
-               query = g_strdup_printf(CONTACTS_QUERY_FROM_URI, id, id, id, id,
-                                       id, id, id, id, id, id, id, id, id);
-       else if (g_str_has_prefix(id, CALL_ID_PREFIX) == TRUE)
-               query = g_strdup_printf(CONTACT_FROM_CALL_QUERY, id);
-       else
-               query = g_strdup_printf(CONTACTS_OTHER_QUERY_FROM_URI,
-                                                               id, id, id);
-
-       ret = query_tracker(query, PULL_QUERY_COL_AMOUNT, pull_contacts, data);
-       if (err)
-               *err = ret;
-
-       g_free(query);
-
-       return data;
-}
-
-void *phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb,
-               phonebook_cache_ready_cb ready_cb, void *user_data, int *err)
-{
-       struct phonebook_data *data;
-       const char *query;
-       int ret;
-
-       DBG("name %s", name);
-
-       query = folder2query(name);
-       if (query == NULL) {
-               if (err)
-                       *err = -ENOENT;
-               return NULL;
-       }
-
-       data = g_new0(struct phonebook_data, 1);
-       data->entry_cb = entry_cb;
-       data->ready_cb = ready_cb;
-       data->user_data = user_data;
-
-       ret = query_tracker(query, 8, add_to_cache, data);
-       if (err)
-               *err = ret;
-
-       return data;
-}
diff --git a/obexd/plugins/syncevolution.c b/obexd/plugins/syncevolution.c
deleted file mode 100644 (file)
index edc00c8..0000000
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- *
- *  OBEX Server
- *
- *  Copyright (C) 2007-2010  Intel Corporation
- *  Copyright (C) 2007-2010  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 <string.h>
-#include <stdio.h>
-#include <errno.h>
-#include <sys/types.h>
-
-#include <glib.h>
-#include <dbus/dbus.h>
-
-#include <bluetooth/bluetooth.h>
-
-#include <btio/btio.h>
-#include <gdbus/gdbus.h>
-#include "plugin.h"
-#include "obex.h"
-#include "service.h"
-#include "mimetype.h"
-#include "log.h"
-#include "manager.h"
-#include "obexd.h"
-#include "filesystem.h"
-
-#define SYNCML_TARGET_SIZE 11
-
-static const uint8_t SYNCML_TARGET[SYNCML_TARGET_SIZE] = {
-                       0x53, 0x59, 0x4E, 0x43, 0x4D, 0x4C, 0x2D, 0x53,
-                       0x59, 0x4E, 0x43 };
-
-#define SYNCEVOLUTION_CHANNEL  19
-
-#define SYNCEVOLUTION_RECORD "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\
-<record>                                                               \
- <attribute id=\"0x0001\">                                             \
-    <sequence>                                                         \
-      <uuid value=\"00000002-0000-1000-8000-0002ee000002\"/>           \
-    </sequence>                                                        \
- </attribute>                                                          \
-                                                                       \
- <attribute id=\"0x0004\">                                             \
-    <sequence>                                                         \
-      <sequence>                                                       \
-        <uuid value=\"0x0100\"/>                                       \
-      </sequence>                                                      \
-      <sequence>                                                       \
-        <uuid value=\"0x0003\"/>                                       \
-        <uint8 value=\"%u\" name=\"channel\"/>                         \
-      </sequence>                                                      \
-      <sequence>                                                       \
-        <uuid value=\"0x0008\"/>                                       \
-      </sequence>                                                      \
-    </sequence>                                                        \
- </attribute>                                                          \
-                                                                       \
- <attribute id=\"0x0100\">                                             \
-    <text value=\"%s\" name=\"name\"/>                                 \
- </attribute>                                                          \
-</record>"
-
-#define SYNCE_BUS_NAME "org.syncevolution"
-#define SYNCE_PATH     "/org/syncevolution/Server"
-#define SYNCE_SERVER_INTERFACE "org.syncevolution.Server"
-#define SYNCE_CONN_INTERFACE   "org.syncevolution.Connection"
-
-struct synce_context {
-       struct obex_session *os;
-       DBusConnection *dbus_conn;
-       char *conn_obj;
-       unsigned int reply_watch;
-       unsigned int abort_watch;
-       GString *buffer;
-       int lasterr;
-       char *id;
-};
-
-static void append_dict_entry(DBusMessageIter *dict, const char *key,
-                                                       int type, void *val)
-{
-       DBusMessageIter entry;
-
-       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_append_basic(&entry, DBUS_TYPE_STRING, &val);
-       dbus_message_iter_close_container(dict, &entry);
-}
-
-static gboolean reply_signal(DBusConnection *conn, DBusMessage *msg,
-                                                               void *data)
-{
-       struct synce_context *context = data;
-       const char *path = dbus_message_get_path(msg);
-       DBusMessageIter iter, array_iter;
-       char *value;
-       int length;
-
-       if (strcmp(context->conn_obj, path) != 0) {
-               obex_object_set_io_flags(context, G_IO_ERR, -EPERM);
-               context->lasterr = -EPERM;
-               return FALSE;
-       }
-
-       dbus_message_iter_init(msg, &iter);
-
-       dbus_message_iter_recurse(&iter, &array_iter);
-       dbus_message_iter_get_fixed_array(&array_iter, &value, &length);
-
-       context->buffer = g_string_new_len(value, length);
-       obex_object_set_io_flags(context, G_IO_IN, 0);
-       context->lasterr = 0;
-
-       return TRUE;
-}
-
-static gboolean abort_signal(DBusConnection *conn, DBusMessage *msg,
-                                                               void *data)
-{
-       struct synce_context *context = data;
-
-       obex_object_set_io_flags(context, G_IO_ERR, -EPERM);
-       context->lasterr = -EPERM;
-
-       return TRUE;
-}
-
-static void connect_cb(DBusPendingCall *call, void *user_data)
-{
-       struct synce_context *context = user_data;
-       DBusConnection *conn;
-       DBusMessage *reply;
-       DBusError err;
-       char *path;
-
-       conn = context->dbus_conn;
-
-       reply = dbus_pending_call_steal_reply(call);
-
-       dbus_error_init(&err);
-       if (dbus_message_get_args(reply, &err, DBUS_TYPE_OBJECT_PATH, &path,
-                                               DBUS_TYPE_INVALID) == FALSE) {
-               error("%s", err.message);
-               dbus_error_free(&err);
-               goto failed;
-       }
-
-       DBG("Got conn object %s from syncevolution", path);
-       context->conn_obj = g_strdup(path);
-
-       context->reply_watch = g_dbus_add_signal_watch(conn, NULL, path,
-                                               SYNCE_CONN_INTERFACE, "Reply",
-                                               reply_signal, context, NULL);
-
-       context->abort_watch = g_dbus_add_signal_watch(conn, NULL, path,
-                                               SYNCE_CONN_INTERFACE, "Abort",
-                                               abort_signal, context, NULL);
-
-       dbus_message_unref(reply);
-
-       return;
-
-failed:
-       obex_object_set_io_flags(context, G_IO_ERR, -EPERM);
-       context->lasterr = -EPERM;
-}
-
-static void process_cb(DBusPendingCall *call, void *user_data)
-{
-       struct synce_context *context = user_data;
-       DBusMessage *reply;
-       DBusError derr;
-
-       reply = dbus_pending_call_steal_reply(call);
-       dbus_error_init(&derr);
-       if (dbus_set_error_from_message(&derr, reply)) {
-               error("process_cb(): syncevolution replied with an error:"
-                                       " %s, %s", derr.name, derr.message);
-               dbus_error_free(&derr);
-
-               obex_object_set_io_flags(context, G_IO_ERR, -EPERM);
-               context->lasterr = -EPERM;
-               goto done;
-       }
-
-       obex_object_set_io_flags(context, G_IO_OUT, 0);
-       context->lasterr = 0;
-
-done:
-       dbus_message_unref(reply);
-}
-
-static void *synce_connect(struct obex_session *os, int *err)
-{
-       DBusConnection *conn;
-       struct synce_context *context;
-       char *address;
-
-       manager_register_session(os);
-
-       conn = manager_dbus_get_connection();
-       if (!conn)
-               goto failed;
-
-       context = g_new0(struct synce_context, 1);
-       context->dbus_conn = conn;
-       context->lasterr = -EAGAIN;
-       context->os = os;
-
-       if (obex_getpeername(os, &address) == 0) {
-               context->id = g_strdup_printf("%s+%d", address,
-                                                       SYNCEVOLUTION_CHANNEL);
-               g_free(address);
-       }
-
-       if (err)
-               *err = 0;
-
-       return context;
-
-failed:
-       if (err)
-               *err = -EPERM;
-
-       return NULL;
-}
-
-static int synce_put(struct obex_session *os, void *user_data)
-{
-       return 0;
-}
-
-static int synce_get(struct obex_session *os, void *user_data)
-{
-       return obex_get_stream_start(os, NULL);
-}
-
-static void close_cb(DBusPendingCall *call, void *user_data)
-{
-       DBusMessage *reply;
-       DBusError derr;
-
-       reply = dbus_pending_call_steal_reply(call);
-       dbus_error_init(&derr);
-       if (dbus_set_error_from_message(&derr, reply)) {
-               error("close_cb(): syncevolution replied with an error:"
-                                       " %s, %s", derr.name, derr.message);
-               dbus_error_free(&derr);
-       }
-
-       dbus_message_unref(reply);
-}
-
-static void synce_disconnect(struct obex_session *os, void *user_data)
-{
-       struct synce_context *context = user_data;
-
-       g_free(context);
-}
-
-static void *synce_open(const char *name, int oflag, mode_t mode,
-                               void *user_data, size_t *size, int *err)
-{
-       struct synce_context *context = user_data;
-
-       if (err)
-               *err = context ? 0 : -EFAULT;
-
-       return user_data;
-}
-
-static int synce_close(void *object)
-{
-       struct synce_context *context = object;
-       DBusMessage *msg;
-       const char *error;
-       gboolean normal;
-       DBusPendingCall *call;
-
-       if (!context->conn_obj)
-               goto done;
-
-       msg = dbus_message_new_method_call(SYNCE_BUS_NAME, context->conn_obj,
-                                               SYNCE_CONN_INTERFACE, "Close");
-       if (!msg)
-               goto failed;
-
-       normal = TRUE;
-       error = "none";
-       dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &normal,
-                               DBUS_TYPE_STRING, &error, DBUS_TYPE_INVALID);
-
-       g_dbus_send_message_with_reply(context->dbus_conn, msg, &call, -1);
-       dbus_pending_call_set_notify(call, close_cb, NULL, NULL);
-       dbus_message_unref(msg);
-       dbus_pending_call_unref(call);
-
-failed:
-       g_dbus_remove_watch(context->dbus_conn, context->reply_watch);
-       context->reply_watch = 0;
-       g_dbus_remove_watch(context->dbus_conn, context->abort_watch);
-       context->abort_watch = 0;
-
-       g_free(context->conn_obj);
-       context->conn_obj = NULL;
-
-done:
-       dbus_connection_unref(context->dbus_conn);
-       g_free(context);
-       return 0;
-}
-
-static ssize_t synce_read(void *object, void *buf, size_t count)
-{
-       struct synce_context *context = object;
-       DBusConnection *conn;
-       char transport[36], transport_description[24];
-       const char *session;
-       DBusMessage *msg;
-       DBusMessageIter iter, dict;
-       gboolean authenticate;
-       DBusPendingCall *call;
-
-       if (context->buffer)
-               return string_read(context->buffer, buf, count);
-
-       conn = manager_dbus_get_connection();
-       if (conn == NULL)
-               return -EPERM;
-
-       msg = dbus_message_new_method_call(SYNCE_BUS_NAME, SYNCE_PATH,
-                               SYNCE_SERVER_INTERFACE, "Connect");
-       if (!msg)
-               return -EPERM;
-
-       dbus_message_iter_init_append(msg, &iter);
-       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);
-
-       append_dict_entry(&dict, "id", DBUS_TYPE_STRING, context->id);
-
-       snprintf(transport, sizeof(transport), "%s.obexd", OBEXD_SERVICE);
-       append_dict_entry(&dict, "transport", DBUS_TYPE_STRING, transport);
-
-       snprintf(transport_description, sizeof(transport_description),
-                                               "version %s", VERSION);
-       append_dict_entry(&dict, "transport_description", DBUS_TYPE_STRING,
-                                                       transport_description);
-
-       dbus_message_iter_close_container(&iter, &dict);
-
-       authenticate = FALSE;
-       session = "";
-       dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &authenticate,
-                       DBUS_TYPE_STRING, &session, DBUS_TYPE_INVALID);
-
-       if (!g_dbus_send_message_with_reply(conn, msg, &call, -1)) {
-               error("D-Bus call to %s failed.", SYNCE_SERVER_INTERFACE);
-               dbus_message_unref(msg);
-               return -EPERM;
-       }
-
-       dbus_pending_call_set_notify(call, connect_cb, context, NULL);
-
-       dbus_pending_call_unref(call);
-       dbus_message_unref(msg);
-
-       return -EAGAIN;
-}
-
-static ssize_t synce_write(void *object, const void *buf, size_t count)
-{
-       struct synce_context *context = object;
-       DBusMessage *msg;
-       DBusMessageIter iter, array_iter;
-       DBusPendingCall *call;
-       const char *type = obex_get_type(context->os);
-
-       if (context->lasterr == 0)
-               return count;
-
-       if (!context->conn_obj)
-               return -EFAULT;
-
-       msg = dbus_message_new_method_call(SYNCE_BUS_NAME, context->conn_obj,
-                                       SYNCE_CONN_INTERFACE, "Process");
-       if (!msg)
-               return -EFAULT;
-
-       dbus_message_iter_init_append(msg, &iter);
-       dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
-                               DBUS_TYPE_BYTE_AS_STRING, &array_iter);
-
-       dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
-                                               &buf, count);
-       dbus_message_iter_close_container(&iter, &array_iter);
-
-       dbus_message_append_args(msg, DBUS_TYPE_STRING, &type,
-                                               DBUS_TYPE_INVALID);
-
-       if (!g_dbus_send_message_with_reply(context->dbus_conn, msg,
-                                                               &call, -1)) {
-               error("D-Bus call to %s failed.", SYNCE_CONN_INTERFACE);
-               dbus_message_unref(msg);
-               return -EPERM;
-       }
-
-       dbus_pending_call_set_notify(call, process_cb, context, NULL);
-
-       dbus_message_unref(msg);
-       dbus_pending_call_unref(call);
-
-       return -EAGAIN;
-}
-
-static struct obex_mime_type_driver synce_driver = {
-       .target = SYNCML_TARGET,
-       .target_size = SYNCML_TARGET_SIZE,
-       .open = synce_open,
-       .close = synce_close,
-       .read = synce_read,
-       .write = synce_write,
-};
-
-static struct obex_service_driver synce = {
-       .name = "OBEX server for SyncML, using SyncEvolution",
-       .service = OBEX_SYNCEVOLUTION,
-       .channel = SYNCEVOLUTION_CHANNEL,
-       .secure = TRUE,
-       .record = SYNCEVOLUTION_RECORD,
-       .target = SYNCML_TARGET,
-       .target_size = SYNCML_TARGET_SIZE,
-       .get = synce_get,
-       .put = synce_put,
-       .connect = synce_connect,
-       .disconnect = synce_disconnect,
-};
-
-static int synce_init(void)
-{
-       int err;
-
-       err = obex_mime_type_driver_register(&synce_driver);
-       if (err < 0)
-               return err;
-
-       return obex_service_driver_register(&synce);
-}
-
-static void synce_exit(void)
-{
-       obex_service_driver_unregister(&synce);
-       obex_mime_type_driver_unregister(&synce_driver);
-}
-
-OBEX_PLUGIN_DEFINE(syncevolution, synce_init, synce_exit)
old mode 100644 (file)
new mode 100755 (executable)
index e5592f35770006fd4481f1e840d868dc147190b6..0395ca5f744f0a1c8006afbb2cf71de32737f53d 100644 (file)
@@ -20,7 +20,7 @@ BuildRequires:  udev
 BuildRequires:  pkgconfig(libnl-1)
 BuildRequires:  libical-devel
 Url:            http://www.bluez.org
-Version:        5.9
+Version:        5.10
 Release:        0
 Summary:        Bluetooth Stack for Linux
 License:        GPL-2.0+
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
diff --git a/profiles/audio/1.patch b/profiles/audio/1.patch
deleted file mode 100644 (file)
index fa44d32..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-commit e6e654d70e07b9cb2bf0237787725a294aa791cb
-Author: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
-Date:   Thu Mar 7 11:41:22 2013 +0200
-
-    audio: Remove profile enabling/disabling logic
-    
-    This should be handle by the core for all profiles
-
-diff --git a/profiles/audio/audio.conf b/profiles/audio/audio.conf
-index f556610..067b3fc 100644
---- a/profiles/audio/audio.conf
-+++ b/profiles/audio/audio.conf
-@@ -6,7 +6,3 @@
- # Switch to master role for incoming connections (defaults to true)
- #Master=true
--
--# If we want to disable support for specific services
--# Defaults to supporting the services: Sink, Control
--#Disable=Source
-diff --git a/profiles/audio/manager.c b/profiles/audio/manager.c
-index 934227e..42a2b58 100644
---- a/profiles/audio/manager.c
-+++ b/profiles/audio/manager.c
-@@ -70,12 +70,6 @@
- static GKeyFile *config = NULL;
- static GSList *devices = NULL;
--static struct enabled_interfaces enabled = {
--      .sink           = TRUE,
--      .source         = FALSE,
--      .control        = TRUE,
--};
--
- static struct audio_device *get_audio_dev(struct btd_device *device)
- {
-       return manager_get_audio_device(device, TRUE);
-@@ -410,47 +404,12 @@ void audio_control_disconnected(struct btd_device *dev, int err)
- int audio_manager_init(GKeyFile *conf)
- {
--      char **list;
--      int i;
--
--      if (!conf)
--              goto proceed;
--
--      config = conf;
--
--      list = g_key_file_get_string_list(config, "General", "Enable",
--                                              NULL, NULL);
--      for (i = 0; list && list[i] != NULL; i++) {
--              if (g_str_equal(list[i], "Sink"))
--                      enabled.sink = TRUE;
--              else if (g_str_equal(list[i], "Source"))
--                      enabled.source = TRUE;
--              else if (g_str_equal(list[i], "Control"))
--                      enabled.control = TRUE;
--      }
--      g_strfreev(list);
-+      if (conf)
-+              config = conf;
--      list = g_key_file_get_string_list(config, "General", "Disable",
--                                              NULL, NULL);
--      for (i = 0; list && list[i] != NULL; i++) {
--              if (g_str_equal(list[i], "Sink"))
--                      enabled.sink = FALSE;
--              else if (g_str_equal(list[i], "Source"))
--                      enabled.source = FALSE;
--              else if (g_str_equal(list[i], "Control"))
--                      enabled.control = FALSE;
--      }
--      g_strfreev(list);
--
--proceed:
--      if (enabled.source)
--              btd_profile_register(&a2dp_source_profile);
--
--      if (enabled.sink)
--              btd_profile_register(&a2dp_sink_profile);
--
--      if (enabled.control)
--              btd_profile_register(&avrcp_profile);
-+      btd_profile_register(&a2dp_source_profile);
-+      btd_profile_register(&a2dp_sink_profile);
-+      btd_profile_register(&avrcp_profile);
-       btd_register_adapter_driver(&media_driver);
-@@ -464,14 +423,9 @@ void audio_manager_exit(void)
-               config = NULL;
-       }
--      if (enabled.source)
--              btd_profile_unregister(&a2dp_source_profile);
--
--      if (enabled.sink)
--              btd_profile_unregister(&a2dp_sink_profile);
--
--      if (enabled.control)
--              btd_profile_unregister(&avrcp_profile);
-+      btd_profile_unregister(&a2dp_source_profile);
-+      btd_profile_unregister(&a2dp_sink_profile);
-+      btd_profile_unregister(&avrcp_profile);
-       btd_unregister_adapter_driver(&media_driver);
- }
index 845027f99f5fe90f691efa6ccddbe20619d47528..dac7a66c552a2604987af3c3c3921e2bead6e336 100644 (file)
@@ -1480,7 +1480,28 @@ static struct avctp_pending_req *pending_create(struct avctp_channel *chan,
                                                GDestroyNotify destroy)
 {
        struct avctp_pending_req *p;
+       GSList *l, *tmp;
 
+       if (!chan->processed)
+               goto done;
+
+       tmp = g_slist_copy(chan->processed);
+
+       /* Find first unused transaction id */
+       for (l = tmp; l; l = l->next) {
+               struct avctp_pending_req *req = l->data;
+
+               if (req->transaction == chan->transaction) {
+                       chan->transaction++;
+                       chan->transaction %= 16;
+                       tmp = g_slist_delete_link(tmp, l);
+                       l = tmp;
+               }
+       }
+
+       g_slist_free(tmp);
+
+done:
        p = g_new0(struct avctp_pending_req, 1);
        p->chan = chan;
        p->transaction = chan->transaction;
index 622dff8138f7fc575fb5b9e29d72940868cd6662..dab8f1c807de9cff1dba2be265e12a87f72d8854 100644 (file)
@@ -354,6 +354,12 @@ struct avdtp_state_callback {
        void *user_data;
 };
 
+struct discover_callback {
+       unsigned int id;
+       avdtp_discover_cb_t cb;
+       void *user_data;
+};
+
 struct avdtp_stream {
        GIOChannel *io;
        uint16_t imtu;
@@ -412,9 +418,7 @@ struct avdtp {
 
        char *buf;
 
-       avdtp_discover_cb_t discov_cb;
-       void *user_data;
-
+       struct discover_callback *discover;
        struct pending_req *req;
 
        guint dc_timer;
@@ -1041,19 +1045,21 @@ static void avdtp_sep_set_state(struct avdtp *session,
 
 static void finalize_discovery(struct avdtp *session, int err)
 {
+       struct discover_callback *discover = session->discover;
        struct avdtp_error avdtp_err;
 
-       avdtp_error_init(&avdtp_err, AVDTP_ERRNO, err);
-
-       if (!session->discov_cb)
+       if (!discover)
                return;
 
-       session->discov_cb(session, session->seps,
-                               err ? &avdtp_err : NULL,
-                               session->user_data);
+       avdtp_error_init(&avdtp_err, AVDTP_ERRNO, err);
+
+       if (discover->id > 0)
+               g_source_remove(discover->id);
 
-       session->discov_cb = NULL;
-       session->user_data = NULL;
+       discover->cb(session, session->seps, err ? &avdtp_err : NULL,
+                                                       discover->user_data);
+       g_free(discover);
+       session->discover = NULL;
 }
 
 static void release_stream(struct avdtp_stream *stream, struct avdtp *session)
@@ -3322,6 +3328,8 @@ static gboolean process_discover(gpointer data)
 {
        struct avdtp *session = data;
 
+       session->discover->id = 0;
+
        finalize_discovery(session, 0);
 
        return FALSE;
@@ -3332,20 +3340,22 @@ int avdtp_discover(struct avdtp *session, avdtp_discover_cb_t cb,
 {
        int err;
 
-       if (session->discov_cb)
+       if (session->discover)
                return -EBUSY;
 
+       session->discover = g_new0(struct discover_callback, 1);
+
        if (session->seps) {
-               session->discov_cb = cb;
-               session->user_data = user_data;
-               g_idle_add(process_discover, session);
+               session->discover->cb = cb;
+               session->discover->user_data = user_data;
+               session->discover->id = g_idle_add(process_discover, session);
                return 0;
        }
 
        err = send_request(session, FALSE, NULL, AVDTP_DISCOVER, NULL, 0);
        if (err == 0) {
-               session->discov_cb = cb;
-               session->user_data = user_data;
+               session->discover->cb = cb;
+               session->discover->user_data = user_data;
        }
 
        return err;
index 9c72b8dc44bd46d7fe0856f144b0e3dd301e0c2e..5edd3dee114270424536788003f3aed39a883ddb 100644 (file)
@@ -95,7 +95,7 @@ struct media_player {
        GHashTable              *track;         /* Player current track */
        guint                   watch;
        guint                   properties_watch;
-       guint                   track_watch;
+       guint                   seek_watch;
        char                    *status;
        uint32_t                position;
        uint32_t                duration;
@@ -948,7 +948,7 @@ static void media_player_free(gpointer data)
 
        g_dbus_remove_watch(conn, mp->watch);
        g_dbus_remove_watch(conn, mp->properties_watch);
-       g_dbus_remove_watch(conn, mp->track_watch);
+       g_dbus_remove_watch(conn, mp->seek_watch);
 
        if (mp->track)
                g_hash_table_unref(mp->track);
@@ -1304,13 +1304,21 @@ static gboolean set_status(struct media_player *mp, DBusMessageIter *iter)
 static gboolean set_position(struct media_player *mp, DBusMessageIter *iter)
 {
        uint64_t value;
+       const char *status;
 
        if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INT64)
                        return FALSE;
 
        dbus_message_iter_get_basic(iter, &value);
 
-       mp->position = value / 1000;
+       value /= 1000;
+
+       if (value > get_position(mp))
+               status = "forward-seek";
+       else
+               status = "reverse-seek";
+
+       mp->position = value;
        g_timer_start(mp->timer);
 
        DBG("Position=%u", mp->position);
@@ -1325,9 +1333,14 @@ static gboolean set_position(struct media_player *mp, DBusMessageIter *iter)
         * If position is the maximum value allowed or greater than track's
         * duration, we send a track-reached-end event.
         */
-       if (mp->position == UINT32_MAX || mp->position >= mp->duration)
+       if (mp->position == UINT32_MAX || mp->position >= mp->duration) {
                avrcp_player_event(mp->player, AVRCP_EVENT_TRACK_REACHED_END,
                                                                        NULL);
+               return TRUE;
+       }
+
+       /* Send a status change to force resync the position */
+       avrcp_player_event(mp->player, AVRCP_EVENT_STATUS_CHANGED, status);
 
        return TRUE;
 }
@@ -1681,6 +1694,21 @@ static gboolean properties_changed(DBusConnection *connection, DBusMessage *msg,
        return TRUE;
 }
 
+static gboolean position_changed(DBusConnection *connection, DBusMessage *msg,
+                                                       void *user_data)
+{
+       struct media_player *mp = user_data;
+       DBusMessageIter iter;
+
+       DBG("sender=%s path=%s", mp->sender, mp->path);
+
+       dbus_message_iter_init(msg, &iter);
+
+       set_position(mp, &iter);
+
+       return TRUE;
+}
+
 static struct media_player *media_player_create(struct media_adapter *adapter,
                                                const char *sender,
                                                const char *path,
@@ -1702,6 +1730,10 @@ static struct media_player *media_player_create(struct media_adapter *adapter,
                                                path, MEDIA_PLAYER_INTERFACE,
                                                properties_changed,
                                                mp, NULL);
+       mp->seek_watch = g_dbus_add_signal_watch(conn, sender,
+                                               path, MEDIA_PLAYER_INTERFACE,
+                                               "Seeked", position_changed,
+                                               mp, NULL);
        mp->player = avrcp_register_player(adapter->btd_adapter, &player_cb,
                                                        mp, media_player_free);
        if (!mp->player) {
diff --git a/test/exchange-business-cards b/test/exchange-business-cards
deleted file mode 100755 (executable)
index 6805cf7..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-
-import sys
-import dbus
-
-bus = dbus.SessionBus()
-client = dbus.Interface(bus.get_object("org.bluez.obex", "/org/bluez/obex"),
-                                       "org.bluez.obex.Client")
-
-if (len(sys.argv) < 4):
-       print "Usage: %s <device> <clientfile> <file>" % (sys.argv[0])
-       sys.exit(1)
-
-print "Creating Session"
-path = client.CreateSession(sys.argv[1], { "Target": "OPP" })
-opp = dbus.Interface(bus.get_object("org.bluez.obex", path),
-                                       "org.bluez.obex.ObjectPush")
-
-opp.ExchangeBusinessCards(sys.argv[2], sys.argv[3])
diff --git a/test/ftp-client b/test/ftp-client
deleted file mode 100755 (executable)
index ae3cbcb..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-#!/usr/bin/python
-
-from __future__ import absolute_import, print_function, unicode_literals
-
-import gobject
-
-import sys
-import dbus
-import dbus.service
-import dbus.mainloop.glib
-import os.path
-from optparse import OptionParser
-
-BUS_NAME='org.bluez.obex'
-PATH = '/org/bluez/obex'
-CLIENT_INTERFACE='org.bluez.obex.Client1'
-SESSION_INTERFACE='org.bluez.obex.Session1'
-FILE_TRASNFER_INTERFACE='org.bluez.obex.FileTransfer1'
-TRANSFER_INTERFACE='org.bluez.obex.Transfer1'
-
-def parse_options():
-       parser.add_option("-d", "--device", dest="device",
-                       help="Device to connect", metavar="DEVICE")
-       parser.add_option("-c", "--chdir", dest="new_dir",
-                       help="Change current directory to DIR", metavar="DIR")
-       parser.add_option("-l", "--list", action="store_true", dest="list_dir",
-                       help="List the current directory")
-       parser.add_option("-g", "--get", dest="get_file",
-                       help="Get FILE", metavar="FILE")
-       parser.add_option("-p", "--put", dest="put_file",
-                       help="Put FILE", metavar="FILE")
-       parser.add_option("-y", "--copy", dest="copy_file",
-                       help="Copy FILE", metavar="FILE")
-       parser.add_option("-m", "--move", dest="move_file",
-                       help="Move FILE", metavar="FILE")
-       parser.add_option("-n", "--destname", dest="dest_file",
-                       help="Destination FILE", metavar="FILE")
-       parser.add_option("-r", "--remove", dest="remove_file",
-                       help="Remove FILE", metavar="FILE")
-       parser.add_option("-v", "--verbose", action="store_true",
-                       dest="verbose")
-
-       return parser.parse_args()
-
-class FtpClient:
-       def __init__(self, session_path, verbose=False):
-               self.transferred = 0
-               self.transfer_path = None
-               self.transfer_size = 0
-               self.verbose = verbose
-               bus = dbus.SessionBus()
-               obj = bus.get_object(BUS_NAME, session_path)
-               self.session = dbus.Interface(obj, SESSION_INTERFACE)
-               self.ftp = dbus.Interface(obj, FILE_TRASNFER_INTERFACE)
-               bus.add_signal_receiver(self.properties_changed,
-                       dbus_interface="org.freedesktop.DBus.Properties",
-                       signal_name="PropertiesChanged",
-                       path_keyword="path")
-
-       def create_transfer_reply(self, path, properties):
-               self.transfer_path = path
-               self.transfer_size = properties["Size"]
-               if self.verbose:
-                       print("Transfer created: %s" % path)
-
-       def generic_reply(self):
-               if self.verbose:
-                       print("Operation succeeded")
-
-       def error(self, err):
-               print(err)
-               mainloop.quit()
-
-       def properties_changed(self, interface, properties, invalidated, path):
-               if path != self.transfer_path:
-                       return
-
-               if properties['Status'] == 'complete' or \
-                               properties['Status'] == 'error':
-                       if self.verbose:
-                               print("Transfer %s" % properties['Status'])
-                       mainloop.quit()
-                       return
-
-               if properties["Transferred"] == None:
-                       return
-
-               speed = (value - self.transferred) / 1000
-               print("Transfer progress %d/%d at %d kBps" % (value,
-                                                       self.transfer_size,
-                                                       speed))
-               self.transferred = value
-
-       def change_folder(self, new_dir):
-               for node in new_dir.split("/"):
-                       self.ftp.ChangeFolder(node)
-
-       def list_folder(self):
-               for i in self.ftp.ListFolder():
-                       if i["Type"] == "folder":
-                               print("%s/" % (i["Name"]))
-                       else:
-                               print("%s" % (i["Name"]))
-
-       def put_file(self, filename):
-               self.ftp.PutFile(os.path.abspath(filename),
-                               os.path.basename(filename),
-                               reply_handler=self.create_transfer_reply,
-                               error_handler=self.error)
-
-       def get_file(self, filename):
-               self.ftp.GetFile(os.path.abspath(filename),
-                               os.path.basename(filename),
-                               reply_handler=self.create_transfer_reply,
-                               error_handler=self.error)
-
-       def remove_file(self, filename):
-               self.ftp.Delete(filename,
-                               reply_handler=self.generic_reply,
-                               error_handler=self.error)
-
-       def move_file(self, filename, destname):
-               self.ftp.MoveFile(filename, destname,
-                               reply_handler=self.generic_reply,
-                               error_handler=self.error)
-
-       def copy_file(self, filename, destname):
-               self.ftp.CopyFile(filename, destname,
-                               reply_handler=self.generic_reply,
-                               error_handler=self.error)
-
-if  __name__ == '__main__':
-
-       dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
-
-       parser = OptionParser()
-
-       (options, args) = parse_options()
-
-       if not options.device:
-               parser.print_help()
-               sys.exit(0)
-
-       bus = dbus.SessionBus()
-       mainloop = gobject.MainLoop()
-
-       client = dbus.Interface(bus.get_object(BUS_NAME, PATH,),
-                                                       CLIENT_INTERFACE)
-
-       print("Creating Session")
-       path = client.CreateSession(options.device, { "Target": "ftp" })
-
-       ftp_client = FtpClient(path, options.verbose)
-
-       if options.new_dir:
-               ftp_client.change_folder(options.new_dir)
-
-       if options.list_dir:
-               ftp_client.list_folder()
-
-       if options.get_file:
-               ftp_client.get_file(options.get_file)
-
-       if options.put_file:
-               ftp_client.put_file(options.put_file)
-
-       if options.move_file:
-               ftp_client.move_file(options.move_file, options.dest_file)
-
-       if options.copy_file:
-               ftp_client.copy_file(options.copy_file, options.dest_file)
-
-       if options.remove_file:
-               ftp_client.remove_file(options.remove_file)
-
-       mainloop.run()
diff --git a/test/get-managed-objects b/test/get-managed-objects
deleted file mode 100755 (executable)
index 3156f65..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/python
-
-from __future__ import absolute_import, print_function, unicode_literals
-
-import dbus
-
-bus = dbus.SystemBus()
-
-manager = dbus.Interface(bus.get_object("org.bluez", "/"),
-                                       "org.freedesktop.DBus.ObjectManager")
-
-objects = manager.GetManagedObjects()
-
-for path in objects.keys():
-       print("[ %s ]" % (path))
-
-       interfaces = objects[path]
-
-       for interface in interfaces.keys():
-               if interface in ["org.freedesktop.DBus.Introspectable",
-                                       "org.freedesktop.DBus.Properties"]:
-                       continue
-
-               print("    %s" % (interface))
-
-               properties = interfaces[interface]
-
-               for key in properties.keys():
-                       print("      %s = %s" % (key, properties[key]))
diff --git a/test/get-obex-capabilities b/test/get-obex-capabilities
deleted file mode 100755 (executable)
index e8afbad..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-
-import sys
-import dbus
-
-bus = dbus.SessionBus()
-client = dbus.Interface(bus.get_object("org.bluez.obex", "/org/bluez/obex"),
-                                       "org.bluez.obex.Client")
-
-if (len(sys.argv) < 3):
-       print "Usage: %s <device> <target>" % (sys.argv[0])
-       sys.exit(1)
-
-print "Creating Session"
-session_path = client.CreateSession(sys.argv[1], { "Target": sys.argv[2] })
-session = dbus.Interface(bus.get_object("org.bluez.obex", session_path),
-                                       "org.bluez.obex.Session")
-
-print session.GetCapabilities()
diff --git a/test/list-folders b/test/list-folders
deleted file mode 100755 (executable)
index 7321a15..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/python
-
-import sys
-import dbus
-
-
-def list_folder(folder):
-       bus = dbus.SessionBus()
-       client = dbus.Interface(bus.get_object("org.bluez.obex",
-                                               "/org/bluez/obex"),
-                                               "org.bluez.obex.Client")
-
-       path = client.CreateSession(sys.argv[1], { "Target": "ftp" })
-
-       ftp = dbus.Interface(bus.get_object("org.bluez.obex", path),
-                               "org.bluez.obex.FileTransfer")
-
-       if folder:
-               for node in folder.split("/"):
-                       ftp.ChangeFolder(node)
-
-       for i in ftp.ListFolder():
-               if i["Type"] == "folder":
-                       print "%s/" % (i["Name"])
-               else:
-                       print "%s" % (i["Name"])
-
-
-if __name__ == '__main__':
-
-       if len(sys.argv) < 2:
-               print "Usage: %s <device> [folder]" % (sys.argv[0])
-               sys.exit(1)
-
-       folder = None
-       if len(sys.argv) == 3:
-               folder = sys.argv[2]
-
-       list_folder(folder)
diff --git a/test/map-client b/test/map-client
deleted file mode 100755 (executable)
index f3c657f..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-#!/usr/bin/python
-
-from __future__ import absolute_import, print_function, unicode_literals
-
-import gobject
-
-import sys
-import os
-import dbus
-import dbus.mainloop.glib
-from optparse import OptionParser
-
-from pprint import pformat
-
-BUS_NAME='org.bluez.obex'
-PATH = '/org/bluez/obex'
-CLIENT_INTERFACE = 'org.bluez.obex.Client1'
-SESSION_INTERFACE = 'org.bluez.obex.Session1'
-MESSAGE_ACCESS_INTERFACE = 'org.bluez.obex.MessageAccess1'
-MESSAGE_INTERFACE = 'org.bluez.obex.Message1'
-TRANSFER_INTERFACE = 'org.bluez.obex.Transfer1'
-
-def unwrap(x):
-    """Hack to unwrap D-Bus values, so that they're easier to read when
-    printed. Taken from d-feet """
-
-    if isinstance(x, list):
-        return map(unwrap, x)
-
-    if isinstance(x, tuple):
-        return tuple(map(unwrap, x))
-
-    if isinstance(x, dict):
-        return dict([(unwrap(k), unwrap(v)) for k, v in x.iteritems()])
-
-    for t in [unicode, str, long, int, float, bool]:
-        if isinstance(x, t):
-            return t(x)
-
-    return x
-
-def parse_options():
-       parser.add_option("-d", "--device", dest="device",
-                       help="Device to connect", metavar="DEVICE")
-       parser.add_option("-c", "--chdir", dest="new_dir",
-                       help="Change current directory to DIR", metavar="DIR")
-       parser.add_option("-l", "--lsdir", action="store_true", dest="ls_dir",
-                       help="List folders in current directory")
-       parser.add_option("-v", "--verbose", action="store_true", dest="verbose")
-       parser.add_option("-L", "--lsmsg", action="store", dest="ls_msg",
-                       help="List messages in supplied CWD subdir")
-       parser.add_option("-g", "--get", action="store", dest="get_msg",
-                       help="Get message contents")
-       parser.add_option("-p", "--push", action="store", dest="push_msg",
-                       help="Push message")
-       parser.add_option("--get-properties", action="store", dest="get_msg_properties",
-                       help="Get message properties")
-       parser.add_option("--mark-read", action="store", dest="mark_msg_read",
-                       help="Marks the messages as read")
-       parser.add_option("--mark-unread", action="store", dest="mark_msg_unread",
-                       help="Marks the messages as unread")
-       parser.add_option("--mark-deleted", action="store", dest="mark_msg_deleted",
-                       help="Deletes the message from the folder")
-       parser.add_option("--mark-undeleted", action="store", dest="mark_msg_undeleted",
-                       help="Undeletes the message")
-       parser.add_option("-u", "--update-inbox", action="store_true", dest="update_inbox",
-                       help="Checks for new mails")
-
-       return parser.parse_args()
-
-def set_folder(session, new_dir):
-       session.SetFolder(new_dir)
-
-class MapClient:
-       def __init__(self, session_path, verbose=False):
-               self.progress = 0
-               self.transfer_path = None
-               self.props = dict()
-               self.verbose = verbose
-               self.path = session_path
-               bus = dbus.SessionBus()
-               obj = bus.get_object(BUS_NAME, session_path)
-               self.session = dbus.Interface(obj, SESSION_INTERFACE)
-               self.map = dbus.Interface(obj, MESSAGE_ACCESS_INTERFACE)
-               bus.add_signal_receiver(self.properties_changed,
-                       dbus_interface="org.freedesktop.DBus.Properties",
-                       signal_name="PropertiesChanged",
-                       path_keyword="path")
-
-       def create_transfer_reply(self, path, properties):
-               self.transfer_path = path
-               self.props[path] = properties
-               if self.verbose:
-                       print("Transfer created: %s (file %s)" % (path,
-                                                       properties["Filename"]))
-
-       def generic_reply(self):
-               if self.verbose:
-                       print("Operation succeeded")
-
-       def error(self, err):
-               print(err)
-               mainloop.quit()
-
-       def transfer_complete(self, path):
-               if self.verbose:
-                       print("Transfer finished")
-               properties = self.props.get(path)
-               if properties == None:
-                       return
-               f = open(properties["Filename"], "r")
-               os.remove(properties["Filename"])
-               print(f.readlines())
-
-       def transfer_error(self, path):
-               print("Transfer %s error" % path)
-               mainloop.quit()
-
-       def properties_changed(self, interface, properties, invalidated, path):
-               req = self.props.get(path)
-               if req == None:
-                       return
-
-               if properties['Status'] == 'complete':
-                       self.transfer_complete(path)
-                       return
-
-               if properties['Status'] == 'error':
-                       self.transfer_error(path)
-                       return
-
-       def set_folder(self, new_dir):
-               self.map.SetFolder(new_dir)
-
-       def list_folders(self):
-               for i in self.map.ListFolders(dict()):
-                       print("%s/" % (i["Name"]))
-
-       def list_messages(self, folder):
-               ret = self.map.ListMessages(folder, dict())
-               print(pformat(unwrap(ret)))
-
-       def get_message(self, handle):
-               self.map.ListMessages("", dict())
-               path = self.path + "/message" + handle
-               obj = bus.get_object(BUS_NAME, path)
-               msg = dbus.Interface(obj, MESSAGE_INTERFACE)
-               msg.Get("", True, reply_handler=self.create_transfer_reply,
-                                               error_handler=self.error)
-
-       def push_message(self, filename):
-               self.map.PushMessage(filename, "telecom/msg/outbox", dict(),
-                               reply_handler=self.create_transfer_reply,
-                               error_handler=self.error)
-
-       def get_message_properties(self, handle):
-               self.map.ListMessages("", dict())
-               path = self.path + "/message" + handle
-               obj = bus.get_object(BUS_NAME, path)
-               msg = dbus.Interface(obj, "org.freedesktop.DBus.Properties")
-               ret = msg.GetAll(MESSAGE_INTERFACE)
-               print(pformat(unwrap(ret)))
-
-       def set_message_property(self, handle, prop, flag):
-               self.map.ListMessages("", dict())
-               path = self.path + "/message" + handle
-               obj = bus.get_object(BUS_NAME, path)
-               msg = dbus.Interface(obj, MESSAGE_INTERFACE)
-               msg.SetProperty (prop, flag);
-
-       def update_inbox(self):
-               self.map.UpdateInbox()
-
-
-if  __name__ == '__main__':
-
-       dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
-
-       parser = OptionParser()
-
-       (options, args) = parse_options()
-
-       if not options.device:
-               parser.print_help()
-               exit(0)
-
-       bus = dbus.SessionBus()
-       mainloop = gobject.MainLoop()
-
-       client = dbus.Interface(bus.get_object(BUS_NAME, PATH),
-                                                       CLIENT_INTERFACE)
-
-       print("Creating Session")
-       path = client.CreateSession(options.device, { "Target": "map" })
-
-       map_client = MapClient(path, options.verbose)
-
-       if options.new_dir:
-               map_client.set_folder(options.new_dir)
-
-       if options.ls_dir:
-               map_client.list_folders()
-
-       if options.ls_msg is not None:
-               map_client.list_messages(options.ls_msg)
-
-       if options.get_msg is not None:
-               map_client.get_message(options.get_msg)
-
-       if options.push_msg is not None:
-               map_client.push_message(options.push_msg)
-
-       if options.get_msg_properties is not None:
-               map_client.get_message_properties(options.get_msg_properties)
-
-       if options.mark_msg_read is not None:
-               map_client.set_message_property(options.mark_msg_read, "Read", True)
-
-       if options.mark_msg_unread is not None:
-               map_client.set_message_property(options.mark_msg_unread, "Read", False)
-
-       if options.mark_msg_deleted is not None:
-               map_client.set_message_property(options.mark_msg_deleted, "Deleted", True)
-
-       if options.mark_msg_undeleted is not None:
-               map_client.set_message_property(options.mark_msg_undeleted, "Deleted", False)
-
-       if options.update_inbox:
-               map_client.update_inbox()
-
-       mainloop.run()
diff --git a/test/opp-client b/test/opp-client
deleted file mode 100755 (executable)
index 878c263..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-#!/usr/bin/python
-
-from __future__ import absolute_import, print_function, unicode_literals
-
-import sys
-import dbus
-import gobject
-import dbus.mainloop.glib
-import os.path
-from optparse import OptionParser
-
-BUS_NAME='org.bluez.obex'
-PATH = '/org/bluez/obex'
-CLIENT_INTERFACE='org.bluez.obex.Client1'
-SESSION_INTERFACE='org.bluez.obex.Session1'
-OBJECT_PUSH_INTERFACE='org.bluez.obex.ObjectPush1'
-TRANSFER_INTERFACE='org.bluez.obex.Transfer1'
-
-def parse_options():
-       parser.add_option("-d", "--device", dest="device",
-                       help="Device to connect", metavar="DEVICE")
-       parser.add_option("-p", "--pull", dest="pull_to_file",
-                       help="Pull vcard and store in FILE", metavar="FILE")
-       parser.add_option("-s", "--send", dest="send_file",
-                       help="Send FILE", metavar="FILE")
-       parser.add_option("-v", "--verbose", action="store_true",
-                       dest="verbose")
-
-       return parser.parse_args()
-
-class OppClient:
-       def __init__(self, session_path, verbose=False):
-               self.transferred = 0
-               self.transfer_path = None
-               self.verbose = verbose
-               bus = dbus.SessionBus()
-               obj = bus.get_object(BUS_NAME, session_path)
-               self.session = dbus.Interface(obj, SESSION_INTERFACE)
-               self.opp = dbus.Interface(obj, OBJECT_PUSH_INTERFACE)
-               bus.add_signal_receiver(self.properties_changed,
-                       dbus_interface="org.freedesktop.DBus.Properties",
-                       signal_name="PropertiesChanged",
-                       path_keyword="path")
-
-       def create_transfer_reply(self, path, properties):
-               self.transfer_path = path
-               self.transfer_size = properties["Size"]
-               if self.verbose:
-                       print("Transfer created: %s" % path)
-
-       def error(self, err):
-               print(err)
-               mainloop.quit()
-
-       def properties_changed(self, interface, properties, invalidated, path):
-               if path != self.transfer_path:
-                       return
-
-               if "Status" in properties and \
-                               (properties["Status"] == "complete" or \
-                               properties["Status"] == "error"):
-                       if self.verbose:
-                               print("Transfer %s" % properties["Status"])
-                       mainloop.quit()
-                       return
-
-               if "Transferred" not in properties:
-                       return
-
-               value = properties["Transferred"]
-               speed = (value - self.transferred) / 1000
-               print("Transfer progress %d/%d at %d kBps" % (value,
-                                                       self.transfer_size,
-                                                       speed))
-               self.transferred = value
-
-       def pull_business_card(self, filename):
-               self.opp.PullBusinessCard(os.path.abspath(filename),
-                               reply_handler=self.create_transfer_reply,
-                               error_handler=self.error)
-
-       def send_file(self, filename):
-               self.opp.SendFile(os.path.abspath(filename),
-                               reply_handler=self.create_transfer_reply,
-                               error_handler=self.error)
-
-if  __name__ == '__main__':
-
-       dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
-
-       parser = OptionParser()
-
-       (options, args) = parse_options()
-
-       if not options.device:
-               parser.print_help()
-               sys.exit(0)
-
-       bus = dbus.SessionBus()
-       mainloop = gobject.MainLoop()
-
-       client = dbus.Interface(bus.get_object(BUS_NAME, PATH),
-                                                       CLIENT_INTERFACE)
-
-       print("Creating Session")
-       path = client.CreateSession(options.device, { "Target": "OPP" })
-
-       opp_client = OppClient(path, options.verbose)
-
-       if options.pull_to_file:
-               opp_client.pull_business_card(options.pull_to_file)
-
-       if options.send_file:
-               opp_client.send_file(options.send_file)
-
-       mainloop.run()
diff --git a/test/pbap-client b/test/pbap-client
deleted file mode 100755 (executable)
index c02833b..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-#!/usr/bin/python
-
-from __future__ import absolute_import, print_function, unicode_literals
-
-import gobject
-
-import sys
-import os
-import dbus
-import dbus.service
-import dbus.mainloop.glib
-
-BUS_NAME='org.bluez.obex'
-PATH = '/org/bluez/obex'
-CLIENT_INTERFACE = 'org.bluez.obex.Client1'
-SESSION_INTERFACE = 'org.bluez.obex.Session1'
-PHONEBOOK_ACCESS_INTERFACE = 'org.bluez.obex.PhonebookAccess1'
-TRANSFER_INTERFACE = 'org.bluez.obex.Transfer1'
-
-class Transfer:
-       def __init__(self, callback_func):
-               self.callback_func = callback_func
-               self.path = None
-               self.filename = None
-
-class PbapClient:
-       def __init__(self, session_path):
-               self.transfers = 0
-               self.props = dict()
-               self.flush_func = None
-               bus = dbus.SessionBus()
-               obj = bus.get_object(BUS_NAME, session_path)
-               self.session = dbus.Interface(obj, SESSION_INTERFACE)
-               self.pbap = dbus.Interface(obj, PHONEBOOK_ACCESS_INTERFACE)
-               bus.add_signal_receiver(self.properties_changed,
-                       dbus_interface="org.freedesktop.DBus.Properties",
-                       signal_name="PropertiesChanged",
-                       path_keyword="path")
-
-       def register(self, path, properties, transfer):
-               transfer.path = path
-               transfer.filename = properties["Filename"]
-               self.props[path] = transfer
-               print("Transfer created: %s (file %s)" % (path,
-                                                       transfer.filename))
-
-       def error(self, err):
-               print(err)
-               mainloop.quit()
-
-       def transfer_complete(self, path):
-               req = self.props.get(path)
-               if req == None:
-                       return
-               self.transfers -= 1
-               print("Transfer %s complete" % path)
-               try:
-                       f = open(req.filename, "r")
-                       os.remove(req.filename)
-                       lines = f.readlines()
-                       del self.props[path]
-                       req.callback_func(lines)
-               except:
-                       pass
-
-               if (len(self.props) == 0) and (self.transfers == 0):
-                       if self.flush_func != None:
-                               f = self.flush_func
-                               self.flush_func = None
-                               f()
-
-       def transfer_error(self, path):
-               print("Transfer %s error" % path)
-               mainloop.quit()
-
-       def properties_changed(self, interface, properties, invalidated, path):
-               req = self.props.get(path)
-               if req == None:
-                       return
-
-               if properties['Status'] == 'complete':
-                       self.transfer_complete(path)
-                       return
-
-               if properties['Status'] == 'error':
-                       self.transfer_error(path)
-                       return
-
-       def pull(self, vcard, params, func):
-               req = Transfer(func)
-               self.pbap.Pull(vcard, "", params,
-                       reply_handler=lambda o, p: self.register(o, p, req),
-                       error_handler=self.error)
-               self.transfers += 1
-
-       def pull_all(self, params, func):
-               req = Transfer(func)
-               self.pbap.PullAll("", params,
-                       reply_handler=lambda o, p: self.register(o, p, req),
-                       error_handler=self.error)
-               self.transfers += 1
-
-       def flush_transfers(self, func):
-               if (len(self.props) == 0) and (self.transfers == 0):
-                       return
-               self.flush_func = func
-
-       def interface(self):
-               return self.pbap
-
-if  __name__ == '__main__':
-
-       dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
-
-       bus = dbus.SessionBus()
-       mainloop = gobject.MainLoop()
-
-       client = dbus.Interface(bus.get_object(BUS_NAME, PATH),
-                                                       CLIENT_INTERFACE)
-
-       if (len(sys.argv) < 2):
-               print("Usage: %s <device>" % (sys.argv[0]))
-               sys.exit(1)
-
-       print("Creating Session")
-       session_path = client.CreateSession(sys.argv[1], { "Target": "PBAP" })
-
-       pbap_client = PbapClient(session_path)
-
-       def process_result(lines, header):
-               if header != None:
-                       print(header)
-               for line in lines:
-                       print(line),
-               print
-
-       def test_paths(paths):
-               if len(paths) == 0:
-                       print
-                       print("FINISHED")
-                       mainloop.quit()
-                       return
-
-               path = paths[0]
-
-               print("\n--- Select Phonebook %s ---\n" % (path))
-               pbap_client.interface().Select("int", path)
-
-               print("\n--- GetSize ---\n")
-               ret = pbap_client.interface().GetSize()
-               print("Size = %d\n" % (ret))
-
-               print("\n--- List vCard ---\n")
-               try:
-                       ret = pbap_client.interface().List(dbus.Dictionary())
-               except:
-                       ret = []
-
-               params = dbus.Dictionary({ "Format" : "vcard30",
-                                               "Fields" : ["PHOTO"] })
-               for item in ret:
-                       print("%s : %s" % (item[0], item[1]))
-                       pbap_client.pull(item[0], params,
-                                       lambda x: process_result(x, None))
-
-               pbap_client.pull_all(params, lambda x: process_result(x,
-                                                       "\n--- PullAll ---\n"))
-
-               pbap_client.flush_transfers(lambda: test_paths(paths[1:]))
-
-       test_paths(["PB", "ICH", "OCH", "MCH", "CCH"])
-
-       mainloop.run()
diff --git a/test/simple-obex-agent b/test/simple-obex-agent
deleted file mode 100755 (executable)
index f15e9d1..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/usr/bin/python
-
-from __future__ import absolute_import, print_function, unicode_literals
-
-import gobject
-
-import sys
-import dbus
-import dbus.service
-import dbus.mainloop.glib
-
-BUS_NAME = 'org.bluez.obex'
-PATH = '/org/bluez/obex'
-AGENT_MANAGER_INTERFACE = 'org.bluez.obex.AgentManager1'
-AGENT_INTERFACE = 'org.bluez.obex.Agent1'
-TRANSFER_INTERFACE = 'org.bluez.obex.Transfer1'
-
-def ask(prompt):
-       try:
-               return raw_input(prompt)
-       except:
-               return input(prompt)
-
-class Agent(dbus.service.Object):
-       def __init__(self, conn=None, obj_path=None):
-               dbus.service.Object.__init__(self, conn, obj_path)
-               self.pending_auth = False
-
-       @dbus.service.method(AGENT_INTERFACE, in_signature="o",
-                                                       out_signature="s")
-       def AuthorizePush(self, path):
-               transfer = dbus.Interface(bus.get_object(BUS_NAME, path),
-                                       'org.freedesktop.DBus.Properties')
-               properties = transfer.GetAll(TRANSFER_INTERFACE);
-
-               self.pending_auth = True
-               auth = ask("Authorize (%s, %s) (Y/n):" % (path,
-                                                       properties['Name']))
-
-               if auth == "n" or auth == "N":
-                       self.pending_auth = False
-                       raise dbus.DBusException(
-                                       "org.bluez.obex.Error.Rejected: "
-                                       "Not Authorized")
-
-               self.pending_auth = False
-
-               return properties['Name']
-
-       @dbus.service.method(AGENT_INTERFACE, in_signature="",
-                                                       out_signature="")
-       def Cancel(self):
-               print("Authorization Canceled")
-               self.pending_auth = False
-
-if __name__ == '__main__':
-       dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
-
-       bus = dbus.SessionBus()
-       manager = dbus.Interface(bus.get_object(BUS_NAME, PATH),
-                                               AGENT_MANAGER_INTERFACE)
-
-       path = "/test/agent"
-       agent = Agent(bus, path)
-
-       mainloop = gobject.MainLoop()
-
-       manager.RegisterAgent(path)
-       print("Agent registered")
-
-       cont = True
-       while cont:
-               try:
-                       mainloop.run()
-               except KeyboardInterrupt:
-                       if agent.pending_auth:
-                               agent.Cancel()
-                       elif len(transfers) > 0:
-                               for a in transfers:
-                                       a.cancel()
-                       else:
-                               cont = False
-
-       # manager.UnregisterAgent(path)
-       # print "Agent unregistered"
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
diff --git a/tools/bdaddr.1 b/tools/bdaddr.1
deleted file mode 100644 (file)
index efb77d2..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-.TH BDADDR 1 "Sep 27 2005" BlueZ "Linux System Administration"
-.SH NAME
-bdaddr \- Utility for changing the Bluetooth device address
-.SH SYNOPSIS
-.B bdaddr
-.br
-.B bdaddr -h
-.br
-.B bdaddr [-i <dev>] [-r] [-t] [new bdaddr]
-
-.SH DESCRIPTION
-.LP
-.B
-bdaddr
-is used to query or set the local Bluetooth device address (BD_ADDR). If run
-with no arguments,
-.B
-bdaddr
-prints the chip manufacturer's name, and the current BD_ADDR. If the IEEE OUI
-index file "oui.txt" is installed on the system, the BD_ADDR owner will be
-displayed. If the optional [new bdaddr] argument is given, the device will be
-reprogrammed with that address. This can either be permanent or temporary, as
-specified by the -t flag. In both cases, the device must be reset before the
-new address will become active. This can be done with a 'soft' reset by
-specifying the -r flag, or a 'hard' reset by removing and replugging the
-device. A 'hard' reset will cause the address to revert to the current
-non-volatile value.
-.PP
-.B
-bdaddr
-uses manufacturer specific commands to set the address, and is therefore
-device specific. For this reason, not all devices are supported, and not all
-options are supported on all devices.
-Current supported manufacturers are:
-.B Ericsson, Cambridge Silicon Radio (CSR), Texas Instruments (TI), Zeevo
-and
-.B ST Microelectronics (ST)
-
-.SH OPTIONS
-.TP
-.BI -h
-Gives a list of possible commands.
-.TP
-.BI -i\ <dev>
-Specify a particular device to operate on. If not specified, default is the
-first available device.
-.TP
-.BI -r
-Reset device and make new BD_ADDR active.
-.B
-CSR
-devices only.
-.TP
-.BI -t
-Temporary change. Do not write to non-volatile memory.
-.B
-CSR
-devices only.
-.SH FILES
-.TP
-.I
-/usr/share/misc/oui.txt
-IEEE Organizationally Unique Identifier master file.
-Manually update from: http://standards.ieee.org/regauth/oui/oui.txt
-.SH AUTHORS
-Written by Marcel Holtmann <marcel@holtmann.org>,
-man page by Adam Laurie <adam@algroup.co.uk>
-.PP
index 513322783c895ffc76953a4dadea86c4a02dbb1d..1d71d74f584464b00154aa406ba236e58159da17 100644 (file)
@@ -900,7 +900,7 @@ static void cmd_discov(struct mgmt *mgmt, uint16_t index, int argc,
        struct mgmt_cp_set_discoverable cp;
 
        if (argc < 2) {
-               printf("Usage: btmgmt %s <yes/no> [timeout]\n", argv[0]);
+               printf("Usage: btmgmt %s <yes/no/limited> [timeout]\n", argv[0]);
                exit(EXIT_FAILURE);
        }
 
@@ -910,6 +910,8 @@ static void cmd_discov(struct mgmt *mgmt, uint16_t index, int argc,
                cp.val = 1;
        else if (strcasecmp(argv[1], "off") == 0)
                cp.val = 0;
+       else if (strcasecmp(argv[1], "limited") == 0)
+               cp.val = 2;
        else
                cp.val = atoi(argv[1]);
 
diff --git a/tools/example.psr b/tools/example.psr
deleted file mode 100644 (file)
index bbbec73..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// PSKEY_BDADDR
-&0001 = 0001 2821 005b 6789
-// PSKEY_ANA_FTRIM
-&01f6 = 0025
-// PSKEY_HOST_INTERFACE
-&01f9 = 0001
-// PSKEY_UART_BAUD_RATE
-&0204 = 01d8
-// PSKEY_ANA_FREQ
-&01fe = 0004
-// PSKEY_UART_CONFIG
-&0205 = 0006
index 90eae67e8bc571bae85122f98e88d4db6a59eca8..2ef72cfef79f9bfa1b8228d8e797eb2b35f33a6e 100644 (file)
@@ -1880,6 +1880,32 @@ static const struct generic_data unblock_device_invalid_param_test_1 = {
        .expect_len = sizeof(unblock_device_invalid_param_rsp_1),
 };
 
+static const char set_static_addr_valid_param[] = {
+                       0x11, 0x22, 0x33, 0x44, 0x55, 0xc0 };
+
+static const struct generic_data set_static_addr_success_test = {
+       .send_opcode = MGMT_OP_SET_STATIC_ADDRESS,
+       .send_param = set_static_addr_valid_param,
+       .send_len = sizeof(set_static_addr_valid_param),
+       .expect_status = MGMT_STATUS_SUCCESS,
+};
+
+static const struct generic_data set_static_addr_failure_test = {
+       .send_opcode = MGMT_OP_SET_STATIC_ADDRESS,
+       .send_param = set_static_addr_valid_param,
+       .send_len = sizeof(set_static_addr_valid_param),
+       .expect_status = MGMT_STATUS_REJECTED,
+};
+
+static const char set_scan_params_valid_param[] = { 0x60, 0x00, 0x30, 0x00 };
+
+static const struct generic_data set_scan_params_success_test = {
+       .send_opcode = MGMT_OP_SET_SCAN_PARAMS,
+       .send_param = set_scan_params_valid_param,
+       .send_len = sizeof(set_scan_params_valid_param),
+       .expect_status = MGMT_STATUS_SUCCESS,
+};
+
 static void powered_delay(void *user_data)
 {
        tester_setup_complete();
@@ -3067,5 +3093,16 @@ int main(int argc, char *argv[])
                                &unblock_device_invalid_param_test_1,
                                NULL, test_command_generic);
 
+       test_bredrle("Set Static Address - Success",
+                               &set_static_addr_success_test,
+                               NULL, test_command_generic);
+       test_bredrle("Set Static Address - Failure",
+                               &set_static_addr_failure_test,
+                               setup_powered, test_command_generic);
+
+       test_bredrle("Set Scan Parameters - Success",
+                               &set_scan_params_success_test,
+                               NULL, test_command_generic);
+
        return tester_run();
 }
index 03b8875dc629d984f0e612a06f31202a05da028f..c94330cbc1697337b62a35e7f84bea60f1deea2b 100644 (file)
@@ -543,8 +543,8 @@ static void remove_player(DBusConnection *conn, const char *sender)
        g_free(owner);
 }
 
-static gboolean properties_changed(DBusConnection *conn,
-                                       DBusMessage *msg, void *user_data)
+static gboolean player_signal(DBusConnection *conn, DBusMessage *msg,
+                                                               void *user_data)
 {
        DBusMessage *signal;
        DBusMessageIter iter, args;
@@ -558,17 +558,15 @@ static gboolean properties_changed(DBusConnection *conn,
        if (owner == NULL)
                goto done;
 
-       signal = dbus_message_new_signal(path, DBUS_INTERFACE_PROPERTIES,
-                                                       "PropertiesChanged");
+       signal = dbus_message_new_signal(path, dbus_message_get_interface(msg),
+                                               dbus_message_get_member(msg));
        if (signal == NULL) {
-               fprintf(stderr, "Unable to allocate new %s.PropertisChanged"
-                                       " signal", DBUS_INTERFACE_PROPERTIES);
+               fprintf(stderr, "Unable to allocate new %s.%s signal",
+                                               dbus_message_get_interface(msg),
+                                               dbus_message_get_member(msg));
                goto done;
        }
 
-       if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
-               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
        dbus_message_iter_init_append(signal, &args);
 
        append_iter(&args, &iter);
@@ -2512,7 +2510,7 @@ int main(int argc, char *argv[])
 {
        GOptionContext *context;
        GError *error = NULL;
-       guint owner_watch, properties_watch;
+       guint owner_watch, properties_watch, signal_watch;
        struct sigaction sa;
 
        context = g_option_context_new(NULL);
@@ -2554,10 +2552,14 @@ int main(int argc, char *argv[])
                                                name_owner_changed,
                                                NULL, NULL);
 
-
        properties_watch = g_dbus_add_properties_watch(session, NULL, NULL,
                                                        MPRIS_PLAYER_INTERFACE,
-                                                       properties_changed,
+                                                       player_signal,
+                                                       NULL, NULL);
+
+       signal_watch = g_dbus_add_signal_watch(session, NULL, NULL,
+                                                       MPRIS_PLAYER_INTERFACE,
+                                                       NULL, player_signal,
                                                        NULL, NULL);
 
        memset(&sa, 0, sizeof(sa));
@@ -2578,6 +2580,7 @@ int main(int argc, char *argv[])
 
        g_dbus_remove_watch(session, owner_watch);
        g_dbus_remove_watch(session, properties_watch);
+       g_dbus_remove_watch(session, signal_watch);
 
        g_dbus_client_unref(client);
 
diff --git a/tools/obexctl.c b/tools/obexctl.c
new file mode 100644 (file)
index 0000000..0491b51
--- /dev/null
@@ -0,0 +1,2400 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2013  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 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 <stdbool.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/signalfd.h>
+#include <inttypes.h>
+
+#include <readline/readline.h>
+#include <readline/history.h>
+#include <glib.h>
+#include <gdbus.h>
+
+#include <client/display.h>
+
+/* String display constants */
+#define COLORED_NEW    COLOR_GREEN "NEW" COLOR_OFF
+#define COLORED_CHG    COLOR_YELLOW "CHG" COLOR_OFF
+#define COLORED_DEL    COLOR_RED "DEL" COLOR_OFF
+
+#define PROMPT_ON      COLOR_BLUE "[obex]" COLOR_OFF "# "
+#define PROMPT_OFF     "[obex]# "
+
+#define OBEX_SESSION_INTERFACE "org.bluez.obex.Session1"
+#define OBEX_TRANSFER_INTERFACE "org.bluez.obex.Transfer1"
+#define OBEX_CLIENT_INTERFACE "org.bluez.obex.Client1"
+#define OBEX_OPP_INTERFACE "org.bluez.obex.ObjectPush1"
+#define OBEX_FTP_INTERFACE "org.bluez.obex.FileTransfer1"
+#define OBEX_PBAP_INTERFACE "org.bluez.obex.PhonebookAccess1"
+#define OBEX_MAP_INTERFACE "org.bluez.obex.MessageAccess1"
+#define OBEX_MSG_INTERFACE "org.bluez.obex.Message1"
+
+static GMainLoop *main_loop;
+static DBusConnection *dbus_conn;
+static GDBusProxy *default_session;
+static GSList *sessions = NULL;
+static GSList *opps = NULL;
+static GSList *ftps = NULL;
+static GSList *pbaps = NULL;
+static GSList *maps = NULL;
+static GSList *msgs = NULL;
+static GSList *transfers = NULL;
+static GDBusProxy *client = NULL;
+
+struct transfer_data {
+       uint64_t transferred;
+       uint64_t size;
+};
+
+static void connect_handler(DBusConnection *connection, void *user_data)
+{
+       rl_set_prompt(PROMPT_ON);
+       printf("\r");
+       rl_on_new_line();
+       rl_redisplay();
+}
+
+static void disconnect_handler(DBusConnection *connection, void *user_data)
+{
+       rl_set_prompt(PROMPT_OFF);
+       printf("\r");
+       rl_on_new_line();
+       rl_redisplay();
+}
+
+static void cmd_quit(int argc, char *argv[])
+{
+       g_main_loop_quit(main_loop);
+}
+
+static void connect_reply(DBusMessage *message, void *user_data)
+{
+       DBusError error;
+
+       dbus_error_init(&error);
+
+       if (dbus_set_error_from_message(&error, message) == TRUE) {
+               rl_printf("Failed to connect: %s\n", error.name);
+               dbus_error_free(&error);
+               return;
+       }
+
+       rl_printf("Connection successful\n");
+}
+
+static void append_variant(DBusMessageIter *iter, int type, void *val)
+{
+       DBusMessageIter value;
+       char sig[2] = { type, '\0' };
+
+       dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, sig, &value);
+
+       dbus_message_iter_append_basic(&value, type, val);
+
+       dbus_message_iter_close_container(iter, &value);
+}
+
+static void dict_append_entry(DBusMessageIter *dict, const char *key,
+                                                       int type, void *val)
+{
+       DBusMessageIter entry;
+
+       if (type == DBUS_TYPE_STRING) {
+               const char *str = *((const char **) val);
+               if (str == NULL)
+                       return;
+       }
+
+       dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
+                                                       NULL, &entry);
+
+       dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+
+       append_variant(&entry, type, val);
+
+       dbus_message_iter_close_container(dict, &entry);
+}
+
+struct connect_args {
+       char *dev;
+       char *target;
+};
+
+static void connect_args_free(void *data)
+{
+       struct connect_args *args = data;
+
+       g_free(args->dev);
+       g_free(args->target);
+       g_free(args);
+}
+
+static void connect_setup(DBusMessageIter *iter, void *user_data)
+{
+       struct connect_args *args = user_data;
+       DBusMessageIter dict;
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &args->dev);
+
+       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);
+
+       if (args->target == NULL)
+               goto done;
+
+       dict_append_entry(&dict, "Target", DBUS_TYPE_STRING, &args->target);
+
+done:
+       dbus_message_iter_close_container(iter, &dict);
+}
+
+static void cmd_connect(int argc, char *argv[])
+{
+       struct connect_args *args;
+       const char *target = "opp";
+
+       if (argc < 2) {
+               rl_printf("Missing device address argument\n");
+               return;
+       }
+
+       if (!client) {
+               rl_printf("Client proxy not available\n");
+               return;
+       }
+
+       if (argc > 2)
+               target = argv[2];
+
+       args = g_new0(struct connect_args, 1);
+       args->dev = g_strdup(argv[1]);
+       args->target = g_strdup(target);
+
+       if (g_dbus_proxy_method_call(client, "CreateSession", connect_setup,
+                       connect_reply, args, connect_args_free) == FALSE) {
+               rl_printf("Failed to connect\n");
+               return;
+       }
+
+       rl_printf("Attempting to connect to %s\n", argv[1]);
+}
+
+static void disconnect_reply(DBusMessage *message, void *user_data)
+{
+       DBusError error;
+
+       dbus_error_init(&error);
+
+       if (dbus_set_error_from_message(&error, message) == TRUE) {
+               rl_printf("Failed to disconnect: %s\n", error.name);
+               dbus_error_free(&error);
+               return;
+       }
+
+       rl_printf("Disconnection successful\n");
+}
+
+static void disconnect_setup(DBusMessageIter *iter, void *user_data)
+{
+       GDBusProxy *proxy = user_data;
+       const char *path;
+
+       path = g_dbus_proxy_get_path(proxy);
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
+}
+
+static GDBusProxy *find_session(const char *path)
+{
+       GSList *l;
+
+       for (l = sessions; l; l = g_slist_next(l)) {
+               GDBusProxy *proxy = l->data;
+
+               if (strcmp(path, g_dbus_proxy_get_path(proxy)) == 0)
+                       return proxy;
+       }
+
+       return NULL;
+}
+
+static void cmd_disconnect(int argc, char *argv[])
+{
+       GDBusProxy *proxy;
+
+       if (argc > 1)
+               proxy = find_session(argv[1]);
+       else
+               proxy = default_session;
+
+       if (proxy == NULL) {
+               rl_printf("Session not available\n");
+               return;
+       }
+
+       if (g_dbus_proxy_method_call(client, "RemoveSession", disconnect_setup,
+                               disconnect_reply, proxy, NULL) == FALSE) {
+               rl_printf("Failed to disconnect\n");
+               return;
+       }
+
+       rl_printf("Attempting to disconnect to %s\n",
+                                               g_dbus_proxy_get_path(proxy));
+}
+
+static char *proxy_description(GDBusProxy *proxy, const char *title,
+                                               const char *description)
+{
+       const char *path;
+
+       path = g_dbus_proxy_get_path(proxy);
+
+       return g_strdup_printf("%s%s%s%s %s ",
+                                       description ? "[" : "",
+                                       description ? : "",
+                                       description ? "] " : "",
+                                       title, path);
+}
+
+static void print_proxy(GDBusProxy *proxy, const char *title,
+                                                       const char *description)
+{
+       char *str;
+
+       str = proxy_description(proxy, title, description);
+
+       rl_printf("%s%s\n", str, default_session == proxy ? "[default]" : "");
+
+       g_free(str);
+}
+
+static void cmd_list(int argc, char *arg[])
+{
+       GSList *l;
+
+       for (l = sessions; l; l = g_slist_next(l)) {
+               GDBusProxy *proxy = l->data;
+               print_proxy(proxy, "Session", NULL);
+       }
+}
+
+static bool check_default_session(void)
+{
+       if (!default_session) {
+               rl_printf("No default session available\n");
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+static void print_iter(const char *label, const char *name,
+                                               DBusMessageIter *iter)
+{
+       dbus_bool_t valbool;
+       dbus_uint64_t valu64;
+       dbus_uint32_t valu32;
+       dbus_uint16_t valu16;
+       dbus_int16_t vals16;
+       const char *valstr;
+       DBusMessageIter subiter;
+
+       if (iter == NULL) {
+               rl_printf("%s%s is nil\n", label, name);
+               return;
+       }
+
+       switch (dbus_message_iter_get_arg_type(iter)) {
+       case DBUS_TYPE_INVALID:
+               rl_printf("%s%s is invalid\n", label, name);
+               break;
+       case DBUS_TYPE_STRING:
+       case DBUS_TYPE_OBJECT_PATH:
+               dbus_message_iter_get_basic(iter, &valstr);
+               rl_printf("%s%s: %s\n", label, name, valstr);
+               break;
+       case DBUS_TYPE_BOOLEAN:
+               dbus_message_iter_get_basic(iter, &valbool);
+               rl_printf("%s%s: %s\n", label, name,
+                                       valbool == TRUE ? "yes" : "no");
+               break;
+       case DBUS_TYPE_UINT64:
+               dbus_message_iter_get_basic(iter, &valu64);
+               rl_printf("%s%s: %" PRIu64 "\n", label, name, valu64);
+               break;
+       case DBUS_TYPE_UINT32:
+               dbus_message_iter_get_basic(iter, &valu32);
+               rl_printf("%s%s: 0x%08x\n", label, name, valu32);
+               break;
+       case DBUS_TYPE_UINT16:
+               dbus_message_iter_get_basic(iter, &valu16);
+               rl_printf("%s%s: 0x%04x\n", label, name, valu16);
+               break;
+       case DBUS_TYPE_INT16:
+               dbus_message_iter_get_basic(iter, &vals16);
+               rl_printf("%s%s: %d\n", label, name, vals16);
+               break;
+       case DBUS_TYPE_VARIANT:
+               dbus_message_iter_recurse(iter, &subiter);
+               print_iter(label, name, &subiter);
+               break;
+       case DBUS_TYPE_ARRAY:
+               dbus_message_iter_recurse(iter, &subiter);
+               while (dbus_message_iter_get_arg_type(&subiter) !=
+                                                       DBUS_TYPE_INVALID) {
+                       print_iter(label, name, &subiter);
+                       dbus_message_iter_next(&subiter);
+               }
+               break;
+       case DBUS_TYPE_DICT_ENTRY:
+               dbus_message_iter_recurse(iter, &subiter);
+               dbus_message_iter_get_basic(&subiter, &valstr);
+               dbus_message_iter_next(&subiter);
+               print_iter(label, valstr, &subiter);
+               break;
+       default:
+               rl_printf("%s%s has unsupported type\n", label, name);
+               break;
+       }
+}
+
+static void print_property(GDBusProxy *proxy, const char *name)
+{
+       DBusMessageIter iter;
+
+       if (g_dbus_proxy_get_property(proxy, name, &iter) == FALSE)
+               return;
+
+       print_iter("\t", name, &iter);
+}
+
+static void cmd_show(int argc, char *argv[])
+{
+       GDBusProxy *proxy;
+
+       if (argc < 2) {
+               if (check_default_session() == FALSE)
+                       return;
+
+               proxy = default_session;
+       } else {
+               proxy = find_session(argv[1]);
+               if (!proxy) {
+                       rl_printf("Session %s not available\n", argv[1]);
+                       return;
+               }
+       }
+
+       rl_printf("Session %s\n", g_dbus_proxy_get_path(proxy));
+
+       print_property(proxy, "Destination");
+       print_property(proxy, "Target");
+}
+
+static void set_default_session(GDBusProxy *proxy)
+{
+       char *desc;
+       DBusMessageIter iter;
+
+       default_session = proxy;
+
+       if (proxy == NULL) {
+               desc = g_strdup(PROMPT_ON);
+               goto done;
+       }
+
+       if (g_dbus_proxy_get_property(proxy, "Destination", &iter))
+               dbus_message_iter_get_basic(&iter, &desc);
+
+       desc = g_strdup_printf(COLOR_BLUE "[%s]" COLOR_OFF "# ", desc);
+
+done:
+       rl_set_prompt(desc);
+       rl_redisplay();
+       g_free(desc);
+}
+
+static void cmd_select(int argc, char *argv[])
+{
+       GDBusProxy *proxy;
+
+       if (argc < 2) {
+               rl_printf("Missing session address argument\n");
+               return;
+       }
+
+       proxy = find_session(argv[1]);
+       if (proxy == NULL) {
+               rl_printf("Session %s not available\n", argv[1]);
+               return;
+       }
+
+       if (default_session == proxy)
+               return;
+
+       set_default_session(proxy);
+
+       print_proxy(proxy, "Session", NULL);
+}
+
+static GDBusProxy *find_transfer(const char *path)
+{
+       GSList *l;
+
+       for (l = transfers; l; l = g_slist_next(l)) {
+               GDBusProxy *proxy = l->data;
+
+               if (strcmp(path, g_dbus_proxy_get_path(proxy)) == 0)
+                       return proxy;
+       }
+
+       return NULL;
+}
+
+static GDBusProxy *find_message(const char *path)
+{
+       GSList *l;
+
+       for (l = msgs; l; l = g_slist_next(l)) {
+               GDBusProxy *proxy = l->data;
+
+               if (strcmp(path, g_dbus_proxy_get_path(proxy)) == 0)
+                       return proxy;
+       }
+
+       return NULL;
+}
+
+static void transfer_info(GDBusProxy *proxy, int argc, char *argv[])
+{
+       rl_printf("Transfer %s\n", g_dbus_proxy_get_path(proxy));
+
+       print_property(proxy, "Session");
+       print_property(proxy, "Name");
+       print_property(proxy, "Type");
+       print_property(proxy, "Status");
+       print_property(proxy, "Time");
+       print_property(proxy, "Size");
+       print_property(proxy, "Transferred");
+       print_property(proxy, "Filename");
+}
+
+static void message_info(GDBusProxy *proxy, int argc, char *argv[])
+{
+       rl_printf("Message %s\n", g_dbus_proxy_get_path(proxy));
+
+       print_property(proxy, "Folder");
+       print_property(proxy, "Subject");
+       print_property(proxy, "Timestamp");
+       print_property(proxy, "Sender");
+       print_property(proxy, "SenderAddress");
+       print_property(proxy, "ReplyTo");
+       print_property(proxy, "Recipient");
+       print_property(proxy, "RecipientAddress");
+       print_property(proxy, "Type");
+       print_property(proxy, "Size");
+       print_property(proxy, "Status");
+       print_property(proxy, "Priority");
+       print_property(proxy, "Read");
+       print_property(proxy, "Deleted");
+       print_property(proxy, "Sent");
+       print_property(proxy, "Protected");
+}
+
+static void cmd_info(int argc, char *argv[])
+{
+       GDBusProxy *proxy;
+
+       if (argc < 2) {
+               rl_printf("Missing object path argument\n");
+               return;
+       }
+
+       proxy = find_transfer(argv[1]);
+       if (proxy) {
+               transfer_info(proxy, argc, argv);
+               return;
+       }
+
+       proxy = find_message(argv[1]);
+       if (proxy) {
+               message_info(proxy, argc, argv);
+               return;
+       }
+
+       rl_printf("Object %s not available\n", argv[1]);
+}
+
+static void cancel_reply(DBusMessage *message, void *user_data)
+{
+       DBusError error;
+
+       dbus_error_init(&error);
+
+       if (dbus_set_error_from_message(&error, message) == TRUE) {
+               rl_printf("Failed to cancel: %s\n", error.name);
+               dbus_error_free(&error);
+               return;
+       }
+
+       rl_printf("Cancel successful\n");
+}
+
+static void cmd_cancel(int argc, char *argv[])
+{
+       GDBusProxy *proxy;
+
+       if (argc < 2) {
+               rl_printf("Missing transfer address argument\n");
+               return;
+       }
+
+       proxy = find_transfer(argv[1]);
+       if (!proxy) {
+               rl_printf("Transfer %s not available\n", argv[1]);
+               return;
+       }
+
+       if (g_dbus_proxy_method_call(proxy, "Cancel", NULL, cancel_reply, NULL,
+                                                       NULL) == FALSE) {
+               rl_printf("Failed to cancel transfer\n");
+               return;
+       }
+
+       rl_printf("Attempting to cancel transfer %s\n",
+                                               g_dbus_proxy_get_path(proxy));
+}
+
+static GDBusProxy *find_opp(const char *path)
+{
+       GSList *l;
+
+       for (l = opps; l; l = g_slist_next(l)) {
+               GDBusProxy *proxy = l->data;
+
+               if (strcmp(path, g_dbus_proxy_get_path(proxy)) == 0)
+                       return proxy;
+       }
+
+       return NULL;
+}
+
+static GDBusProxy *find_map(const char *path)
+{
+       GSList *l;
+
+       for (l = maps; l; l = g_slist_next(l)) {
+               GDBusProxy *proxy = l->data;
+
+               if (strcmp(path, g_dbus_proxy_get_path(proxy)) == 0)
+                       return proxy;
+       }
+
+       return NULL;
+}
+
+static void print_dict_iter(DBusMessageIter *iter)
+{
+       DBusMessageIter dict;
+       int ctype;
+
+       ctype = dbus_message_iter_get_arg_type(iter);
+       if (ctype != DBUS_TYPE_ARRAY)
+               return;
+
+       dbus_message_iter_recurse(iter, &dict);
+
+       while ((ctype = dbus_message_iter_get_arg_type(&dict)) !=
+                                                       DBUS_TYPE_INVALID) {
+               DBusMessageIter entry;
+               const char *key;
+
+               if (ctype != DBUS_TYPE_DICT_ENTRY)
+                       return;
+
+               dbus_message_iter_recurse(&dict, &entry);
+               if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
+                       return;
+
+               dbus_message_iter_get_basic(&entry, &key);
+               dbus_message_iter_next(&entry);
+
+               print_iter("\t", key, &entry);
+
+               dbus_message_iter_next(&dict);
+       }
+}
+
+static void print_transfer_iter(DBusMessageIter *iter)
+{
+       const char *path;
+
+       dbus_message_iter_get_basic(iter, &path);
+
+       rl_printf("Transfer %s\n", path);
+
+       dbus_message_iter_next(iter);
+
+       print_dict_iter(iter);
+}
+
+static void send_reply(DBusMessage *message, void *user_data)
+{
+       DBusMessageIter iter;
+       DBusError error;
+
+       dbus_error_init(&error);
+
+       if (dbus_set_error_from_message(&error, message) == TRUE) {
+               rl_printf("Failed to send: %s\n", error.name);
+               dbus_error_free(&error);
+               return;
+       }
+
+       dbus_message_iter_init(message, &iter);
+
+       print_transfer_iter(&iter);
+}
+
+static void send_setup(DBusMessageIter *iter, void *user_data)
+{
+       const char *file = user_data;
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &file);
+}
+
+static void opp_send(GDBusProxy *proxy, int argc, char *argv[])
+{
+       if (argc < 2) {
+               rl_printf("Missing file argument\n");
+               return;
+       }
+
+       if (g_dbus_proxy_method_call(proxy, "SendFile", send_setup, send_reply,
+                                       g_strdup(argv[1]), g_free) == FALSE) {
+               rl_printf("Failed to send\n");
+               return;
+       }
+
+       rl_printf("Attempting to send %s to %s\n", argv[1],
+                                               g_dbus_proxy_get_path(proxy));
+}
+
+static void push_reply(DBusMessage *message, void *user_data)
+{
+       DBusMessageIter iter;
+       DBusError error;
+
+       dbus_error_init(&error);
+
+       if (dbus_set_error_from_message(&error, message) == TRUE) {
+               rl_printf("Failed to PushMessage: %s\n", error.name);
+               dbus_error_free(&error);
+               return;
+       }
+
+       dbus_message_iter_init(message, &iter);
+
+       print_transfer_iter(&iter);
+}
+
+static void push_setup(DBusMessageIter *iter, void *user_data)
+{
+       const char *file = user_data;
+       const char *folder = "";
+       DBusMessageIter dict;
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &file);
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &folder);
+
+       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_close_container(iter, &dict);
+}
+
+static void map_send(GDBusProxy *proxy, int argc, char *argv[])
+{
+       if (argc < 2) {
+               rl_printf("Missing file argument\n");
+               return;
+       }
+
+       if (g_dbus_proxy_method_call(proxy, "PushMessage", push_setup,
+                                       push_reply, g_strdup(argv[1]),
+                                       g_free) == FALSE) {
+               rl_printf("Failed to send\n");
+               return;
+       }
+
+       rl_printf("Attempting to send %s to %s\n", argv[1],
+                                               g_dbus_proxy_get_path(proxy));
+}
+
+static void cmd_send(int argc, char *argv[])
+{
+       GDBusProxy *proxy;
+
+       if (!check_default_session())
+               return;
+
+       proxy = find_opp(g_dbus_proxy_get_path(default_session));
+       if (proxy) {
+               opp_send(proxy, argc, argv);
+               return;
+       }
+
+       proxy = find_map(g_dbus_proxy_get_path(default_session));
+       if (proxy) {
+               map_send(proxy, argc, argv);
+               return;
+       }
+
+       rl_printf("Command not supported\n");
+}
+
+static void change_folder_reply(DBusMessage *message, void *user_data)
+{
+       DBusError error;
+
+       dbus_error_init(&error);
+
+       if (dbus_set_error_from_message(&error, message) == TRUE) {
+               rl_printf("Failed to ChangeFolder: %s\n", error.name);
+               dbus_error_free(&error);
+               return;
+       }
+
+       rl_printf("ChangeFolder successful\n");
+}
+
+static void change_folder_setup(DBusMessageIter *iter, void *user_data)
+{
+       const char *folder = user_data;
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &folder);
+}
+
+static void select_reply(DBusMessage *message, void *user_data)
+{
+       DBusMessageIter iter;
+       DBusError error;
+
+       dbus_error_init(&error);
+
+       if (dbus_set_error_from_message(&error, message) == TRUE) {
+               rl_printf("Failed to Select: %s\n", error.name);
+               dbus_error_free(&error);
+               return;
+       }
+
+       dbus_message_iter_init(message, &iter);
+
+       rl_printf("Select successful\n");
+}
+
+static void select_setup(DBusMessageIter *iter, void *user_data)
+{
+       const char *folder = user_data;
+       const char *location = "int";
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &location);
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &folder);
+}
+
+static void setfolder_reply(DBusMessage *message, void *user_data)
+{
+       DBusError error;
+
+       dbus_error_init(&error);
+
+       if (dbus_set_error_from_message(&error, message) == TRUE) {
+               rl_printf("Failed to SetFolder: %s\n", error.name);
+               dbus_error_free(&error);
+               return;
+       }
+
+       rl_printf("SetFolder successful\n");
+}
+
+static void setfolder_setup(DBusMessageIter *iter, void *user_data)
+{
+       const char *folder = user_data;
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &folder);
+}
+
+static GDBusProxy *find_ftp(const char *path)
+{
+       GSList *l;
+
+       for (l = ftps; l; l = g_slist_next(l)) {
+               GDBusProxy *proxy = l->data;
+
+               if (strcmp(path, g_dbus_proxy_get_path(proxy)) == 0)
+                       return proxy;
+       }
+
+       return NULL;
+}
+
+static GDBusProxy *find_pbap(const char *path)
+{
+       GSList *l;
+
+       for (l = pbaps; l; l = g_slist_next(l)) {
+               GDBusProxy *proxy = l->data;
+
+               if (strcmp(path, g_dbus_proxy_get_path(proxy)) == 0)
+                       return proxy;
+       }
+
+       return NULL;
+}
+
+static void ftp_cd(GDBusProxy *proxy, int argc, char *argv[])
+{
+       if (argc < 2) {
+               rl_printf("Missing path argument\n");
+               return;
+       }
+
+       if (g_dbus_proxy_method_call(proxy, "ChangeFolder", change_folder_setup,
+                                       change_folder_reply, g_strdup(argv[1]),
+                                       g_free) == FALSE) {
+               rl_printf("Failed to ChangeFolder\n");
+               return;
+       }
+
+       rl_printf("Attempting to ChangeFolder to %s\n", argv[1]);
+}
+
+static void pbap_cd(GDBusProxy *proxy, int argc, char *argv[])
+{
+       if (argc < 2) {
+               rl_printf("Missing path argument\n");
+               return;
+       }
+
+       if (g_dbus_proxy_method_call(proxy, "Select", select_setup,
+                                       select_reply, g_strdup(argv[1]),
+                                       g_free) == FALSE) {
+               rl_printf("Failed to Select\n");
+               return;
+       }
+
+       rl_printf("Attempting to Select to %s\n", argv[1]);
+}
+
+static void map_cd(GDBusProxy *proxy, int argc, char *argv[])
+{
+       if (argc < 2) {
+               rl_printf("Missing path argument\n");
+               return;
+       }
+
+       if (g_dbus_proxy_method_call(proxy, "SetFolder", setfolder_setup,
+                                       setfolder_reply, g_strdup(argv[1]),
+                                       g_free) == FALSE) {
+               rl_printf("Failed to SetFolder\n");
+               return;
+       }
+
+       rl_printf("Attempting to SetFolder to %s\n", argv[1]);
+}
+
+static void cmd_cd(int argc, char *argv[])
+{
+       GDBusProxy *proxy;
+
+       if (!check_default_session())
+               return;
+
+       proxy = find_ftp(g_dbus_proxy_get_path(default_session));
+       if (proxy) {
+               ftp_cd(proxy, argc, argv);
+               return;
+       }
+
+       proxy = find_pbap(g_dbus_proxy_get_path(default_session));
+       if (proxy) {
+               pbap_cd(proxy, argc, argv);
+               return;
+       }
+
+       proxy = find_map(g_dbus_proxy_get_path(default_session));
+       if (proxy) {
+               map_cd(proxy, argc, argv);
+               return;
+       }
+
+       rl_printf("Command not supported\n");
+}
+
+static void list_folder_reply(DBusMessage *message, void *user_data)
+{
+       DBusMessageIter iter, array;
+       DBusError error;
+
+       dbus_error_init(&error);
+
+       if (dbus_set_error_from_message(&error, message) == TRUE) {
+               rl_printf("Failed to ListFolder: %s\n", error.name);
+               dbus_error_free(&error);
+               return;
+       }
+
+       dbus_message_iter_init(message, &iter);
+
+       if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
+               return;
+
+       dbus_message_iter_recurse(&iter, &array);
+
+       while (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_INVALID) {
+               print_dict_iter(&array);
+               dbus_message_iter_next(&array);
+       }
+}
+
+static void ftp_ls(GDBusProxy *proxy, int argc, char *argv[])
+{
+       if (g_dbus_proxy_method_call(proxy, "ListFolder", NULL,
+                                               list_folder_reply, NULL,
+                                               NULL) == FALSE) {
+               rl_printf("Failed to ls\n");
+               return;
+       }
+
+       rl_printf("Attempting to ListFolder\n");
+}
+
+static void parse_list_reply(DBusMessage *message)
+{
+       DBusMessageIter iter, array;
+
+       dbus_message_iter_init(message, &iter);
+
+       if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
+               return;
+
+       dbus_message_iter_recurse(&iter, &array);
+
+       while (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_INVALID) {
+               DBusMessageIter entry;
+               const char *vcard;
+
+               if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRUCT)
+                       return;
+
+               dbus_message_iter_recurse(&array, &entry);
+
+               dbus_message_iter_get_basic(&entry, &vcard);
+               dbus_message_iter_next(&entry);
+               print_iter("\t", vcard, &entry);
+               dbus_message_iter_next(&array);
+       }
+}
+
+static void list_reply(DBusMessage *message, void *user_data)
+{
+       DBusError error;
+
+       dbus_error_init(&error);
+
+       if (dbus_set_error_from_message(&error, message) == TRUE) {
+               rl_printf("Failed to List: %s\n", error.name);
+               dbus_error_free(&error);
+               return;
+       }
+
+       parse_list_reply(message);
+}
+
+static void list_setup(DBusMessageIter *iter, void *user_data)
+{
+       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);
+
+       dbus_message_iter_close_container(iter, &dict);
+}
+
+static void search_reply(DBusMessage *message, void *user_data)
+{
+       DBusError error;
+
+       dbus_error_init(&error);
+
+       if (dbus_set_error_from_message(&error, message) == TRUE) {
+               rl_printf("Failed to Search: %s\n", error.name);
+               dbus_error_free(&error);
+               return;
+       }
+
+       parse_list_reply(message);
+}
+
+static void search_setup(DBusMessageIter *iter, void *user_data)
+{
+       const char *value = user_data;
+       const char *field;
+       DBusMessageIter dict;
+
+       field = isalpha(value[0]) ? "name" : "number";
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &field);
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &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_close_container(iter, &dict);
+}
+
+static void pbap_search(GDBusProxy *proxy, int argc, char *argv[])
+{
+       if (g_dbus_proxy_method_call(proxy, "Search", search_setup,
+                                       search_reply, g_strdup(argv[1]),
+                                       g_free) == FALSE) {
+               rl_printf("Failed to Search\n");
+               return;
+       }
+
+       rl_printf("Attempting to Search\n");
+}
+
+static void list_folders_reply(DBusMessage *message, void *user_data)
+{
+       DBusError error;
+       DBusMessageIter iter, array;
+
+       dbus_error_init(&error);
+
+       if (dbus_set_error_from_message(&error, message) == TRUE) {
+               rl_printf("Failed to ListFolders: %s\n", error.name);
+               dbus_error_free(&error);
+               return;
+       }
+
+       dbus_message_iter_init(message, &iter);
+
+       if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
+               return;
+
+       dbus_message_iter_recurse(&iter, &array);
+
+       while (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_INVALID) {
+               print_dict_iter(&array);
+               dbus_message_iter_next(&array);
+       }
+}
+
+static void list_folders_setup(DBusMessageIter *iter, void *user_data)
+{
+       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);
+
+       dbus_message_iter_close_container(iter, &dict);
+}
+
+static void list_messages_reply(DBusMessage *message, void *user_data)
+{
+       DBusError error;
+       DBusMessageIter iter, array;
+       int ctype;
+
+       dbus_error_init(&error);
+
+       if (dbus_set_error_from_message(&error, message) == TRUE) {
+               rl_printf("Failed to ListFolders: %s\n", error.name);
+               dbus_error_free(&error);
+               return;
+       }
+
+       dbus_message_iter_init(message, &iter);
+
+       if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
+               return;
+
+       dbus_message_iter_recurse(&iter, &array);
+
+       while ((ctype = dbus_message_iter_get_arg_type(&array)) ==
+                                                       DBUS_TYPE_DICT_ENTRY) {
+               DBusMessageIter entry;
+               const char *obj;
+
+               dbus_message_iter_recurse(&array, &entry);
+               dbus_message_iter_get_basic(&entry, &obj);
+               rl_printf("\t%s\n", obj);
+               dbus_message_iter_next(&array);
+       }
+}
+
+static void list_messages_setup(DBusMessageIter *iter, void *user_data)
+{
+       const char *folder = user_data;
+       DBusMessageIter dict;
+
+       if (strcmp(folder, "*") == 0)
+               folder = "";
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &folder);
+
+       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_close_container(iter, &dict);
+}
+
+static void pbap_ls(GDBusProxy *proxy, int argc, char *argv[])
+{
+       if (argc > 1) {
+               pbap_search(proxy, argc, argv);
+               return;
+       }
+
+       if (g_dbus_proxy_method_call(proxy, "List", list_setup, list_reply,
+                                               NULL, NULL) == FALSE) {
+               rl_printf("Failed to List\n");
+               return;
+       }
+
+       rl_printf("Attempting to List\n");
+}
+
+static void map_ls_messages(GDBusProxy *proxy, int argc, char *argv[])
+{
+       if (g_dbus_proxy_method_call(proxy, "ListMessages", list_messages_setup,
+                                       list_messages_reply, g_strdup(argv[1]),
+                                       g_free) == FALSE) {
+               rl_printf("Failed to ListMessages\n");
+               return;
+       }
+
+       rl_printf("Attempting to ListMessages\n");
+}
+
+static void map_ls(GDBusProxy *proxy, int argc, char *argv[])
+{
+       if (argc > 1) {
+               map_ls_messages(proxy, argc, argv);
+               return;
+       }
+
+       if (g_dbus_proxy_method_call(proxy, "ListFolders", list_folders_setup,
+                                               list_folders_reply, NULL,
+                                               NULL) == FALSE) {
+               rl_printf("Failed to ListFolders\n");
+               return;
+       }
+
+       rl_printf("Attempting to ListFolders\n");
+}
+
+static void cmd_ls(int argc, char *argv[])
+{
+       GDBusProxy *proxy;
+
+       if (!check_default_session())
+               return;
+
+       proxy = find_ftp(g_dbus_proxy_get_path(default_session));
+       if (proxy) {
+               ftp_ls(proxy, argc, argv);
+               return;
+       }
+
+       proxy = find_pbap(g_dbus_proxy_get_path(default_session));
+       if (proxy) {
+               pbap_ls(proxy, argc, argv);
+               return;
+       }
+
+       proxy = find_map(g_dbus_proxy_get_path(default_session));
+       if (proxy) {
+               map_ls(proxy, argc, argv);
+               return;
+       }
+
+       rl_printf("Command not supported\n");
+}
+
+struct cp_args {
+       char *source;
+       char *target;
+};
+
+static void cp_free(void *data)
+{
+       struct cp_args *args = data;
+
+       g_free(args->source);
+       g_free(args->target);
+       g_free(args);
+}
+
+static struct cp_args *cp_new(char *argv[])
+{
+       struct cp_args *args;
+       const char *source;
+       const char *target;
+
+       source = rindex(argv[1], ':');
+       if (source == NULL)
+               source = argv[1];
+       else
+               source++;
+
+       target = rindex(argv[2], ':');
+       if (target == NULL)
+               target = argv[2];
+       else
+               target++;
+
+       args = g_new0(struct cp_args, 1);
+       args->source = g_strdup(source);
+       args->target = g_strdup(target);
+
+       return args;
+}
+
+static void cp_setup(DBusMessageIter *iter, void *user_data)
+{
+       struct cp_args *args = user_data;
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &args->source);
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &args->target);
+}
+
+static void copy_file_reply(DBusMessage *message, void *user_data)
+{
+       DBusError error;
+
+       dbus_error_init(&error);
+
+       if (dbus_set_error_from_message(&error, message) == TRUE) {
+               rl_printf("Failed to CopyFile: %s\n", error.name);
+               dbus_error_free(&error);
+               return;
+       }
+
+       rl_printf("CopyFile successful\n");
+}
+
+static void ftp_copy(GDBusProxy *proxy, int argc, char *argv[])
+{
+       struct cp_args *args;
+
+       args = cp_new(argv);
+
+       if (g_dbus_proxy_method_call(proxy, "CopyFile", cp_setup,
+                               copy_file_reply, args, cp_free) == FALSE) {
+               rl_printf("Failed to CopyFile\n");
+               return;
+       }
+
+       rl_printf("Attempting to CopyFile\n");
+}
+
+static void get_file_reply(DBusMessage *message, void *user_data)
+{
+       DBusError error;
+       DBusMessageIter iter;
+
+       dbus_error_init(&error);
+
+       if (dbus_set_error_from_message(&error, message) == TRUE) {
+               rl_printf("Failed to GetFile: %s\n", error.name);
+               dbus_error_free(&error);
+               return;
+       }
+
+       dbus_message_iter_init(message, &iter);
+
+       print_transfer_iter(&iter);
+}
+
+static void get_file_setup(DBusMessageIter *iter, void *user_data)
+{
+       struct cp_args *args = user_data;
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &args->target);
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &args->source);
+}
+
+static void ftp_get(GDBusProxy *proxy, int argc, char *argv[])
+{
+       struct cp_args *args;
+
+       if (rindex(argv[2], ':') == NULL)
+               return ftp_copy(proxy, argc, argv);
+
+       args = cp_new(argv);
+
+       if (g_dbus_proxy_method_call(proxy, "GetFile", get_file_setup,
+                               get_file_reply, args, cp_free) == FALSE) {
+               rl_printf("Failed to GetFile\n");
+               return;
+       }
+
+       rl_printf("Attempting to GetFile\n");
+}
+
+static void put_file_reply(DBusMessage *message, void *user_data)
+{
+       DBusError error;
+       DBusMessageIter iter;
+
+       dbus_error_init(&error);
+
+       if (dbus_set_error_from_message(&error, message) == TRUE) {
+               rl_printf("Failed to PutFile: %s\n", error.name);
+               dbus_error_free(&error);
+               return;
+       }
+
+       dbus_message_iter_init(message, &iter);
+
+       print_transfer_iter(&iter);
+}
+
+static void ftp_put(GDBusProxy *proxy, int argc, char *argv[])
+{
+       struct cp_args *args;
+
+       if (rindex(argv[2], ':') != NULL) {
+               rl_printf("Invalid target file argument\n");
+               return;
+       }
+
+       args = cp_new(argv);
+
+       if (g_dbus_proxy_method_call(proxy, "PutFile", cp_setup, put_file_reply,
+                                               args, cp_free) == FALSE) {
+               rl_printf("Failed to PutFile\n");
+               return;
+       }
+
+       rl_printf("Attempting to PutFile\n");
+}
+
+static void ftp_cp(GDBusProxy *proxy, int argc, char *argv[])
+{
+       if (argc < 2) {
+               rl_printf("Missing source file argument\n");
+               return;
+       }
+
+       if (argc < 3) {
+               rl_printf("Missing target file argument\n");
+               return;
+       }
+
+       if (rindex(argv[1], ':') == NULL)
+               return ftp_get(proxy, argc, argv);
+
+       return ftp_put(proxy, argc, argv);
+}
+
+static void pull_all_reply(DBusMessage *message, void *user_data)
+{
+       DBusError error;
+
+       dbus_error_init(&error);
+
+       if (dbus_set_error_from_message(&error, message) == TRUE) {
+               rl_printf("Failed to PullAll: %s\n", error.name);
+               dbus_error_free(&error);
+               return;
+       }
+
+
+       rl_printf("PullAll successful\n");
+}
+
+static void pull_all_setup(DBusMessageIter *iter, void *user_data)
+{
+       const char *file = user_data;
+       DBusMessageIter dict;
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &file);
+
+       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_close_container(iter, &dict);
+}
+
+static void pbap_pull_all(GDBusProxy *proxy, int argc, char *argv[])
+{
+       if (g_dbus_proxy_method_call(proxy, "PullAll", pull_all_setup,
+                                       pull_all_reply, g_strdup(argv[2]),
+                                       g_free) == FALSE) {
+               rl_printf("Failed to PullAll\n");
+               return;
+       }
+
+       rl_printf("Attempting to PullAll\n");
+}
+
+static void pull_reply(DBusMessage *message, void *user_data)
+{
+       DBusError error;
+
+       dbus_error_init(&error);
+
+       if (dbus_set_error_from_message(&error, message) == TRUE) {
+               rl_printf("Failed to Pull: %s\n", error.name);
+               dbus_error_free(&error);
+               return;
+       }
+
+
+       rl_printf("Pull successful\n");
+}
+
+static void pull_setup(DBusMessageIter *iter, void *user_data)
+{
+       struct cp_args *args = user_data;
+       DBusMessageIter dict;
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &args->source);
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &args->target);
+
+       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_close_container(iter, &dict);
+}
+
+static void pbap_pull(GDBusProxy *proxy, int argc, char *argv[])
+{
+       struct cp_args *args;
+
+       args = cp_new(argv);
+
+       if (g_dbus_proxy_method_call(proxy, "Pull", pull_setup, pull_reply,
+                                               args, cp_free) == FALSE) {
+               rl_printf("Failed to Pull\n");
+               return;
+       }
+
+       rl_printf("Attempting to Pull\n");
+}
+
+static void pbap_cp(GDBusProxy *proxy, int argc, char *argv[])
+{
+       if (argc < 2) {
+               rl_printf("Missing source file argument\n");
+               return;
+       }
+
+       if (argc < 3) {
+               rl_printf("Missing target file argument\n");
+               return;
+       }
+
+       if (strcmp(argv[1], "*") == 0)
+               return pbap_pull_all(proxy, argc, argv);
+
+       return pbap_pull(proxy, argc, argv);
+}
+
+static void get_reply(DBusMessage *message, void *user_data)
+{
+       DBusMessageIter iter;
+       DBusError error;
+
+       dbus_error_init(&error);
+
+       if (dbus_set_error_from_message(&error, message) == TRUE) {
+               rl_printf("Failed to Get: %s\n", error.name);
+               dbus_error_free(&error);
+               return;
+       }
+
+       dbus_message_iter_init(message, &iter);
+
+       print_transfer_iter(&iter);
+}
+
+static void get_setup(DBusMessageIter *iter, void *user_data)
+{
+       const char *file = user_data;
+       dbus_bool_t attachment = TRUE;
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &file);
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &attachment);
+}
+
+static void map_cp(GDBusProxy *proxy, int argc, char *argv[])
+{
+       GDBusProxy *obj;
+
+       if (argc < 2) {
+               rl_printf("Missing message argument\n");
+               return;
+       }
+
+       obj = find_message(argv[1]);
+       if (obj == NULL) {
+               rl_printf("Invalid message argument\n");
+               return;
+       }
+
+       if (argc < 3) {
+               rl_printf("Missing target file argument\n");
+               return;
+       }
+
+       if (g_dbus_proxy_method_call(obj, "Get", get_setup, get_reply,
+                                       g_strdup(argv[2]), g_free) == FALSE) {
+               rl_printf("Failed to Get\n");
+               return;
+       }
+
+       rl_printf("Attempting to Get\n");
+}
+
+static void cmd_cp(int argc, char *argv[])
+{
+
+       GDBusProxy *proxy;
+
+       if (!check_default_session())
+               return;
+
+       proxy = find_ftp(g_dbus_proxy_get_path(default_session));
+       if (proxy) {
+               ftp_cp(proxy, argc, argv);
+               return;
+       }
+
+       proxy = find_pbap(g_dbus_proxy_get_path(default_session));
+       if (proxy) {
+               pbap_cp(proxy, argc, argv);
+               return;
+       }
+
+       proxy = find_map(g_dbus_proxy_get_path(default_session));
+       if (proxy) {
+               map_cp(proxy, argc, argv);
+               return;
+       }
+
+       rl_printf("Command not supported\n");
+}
+
+static void move_file_reply(DBusMessage *message, void *user_data)
+{
+       DBusError error;
+
+       dbus_error_init(&error);
+
+       if (dbus_set_error_from_message(&error, message) == TRUE) {
+               rl_printf("Failed to MoveFile: %s\n", error.name);
+               dbus_error_free(&error);
+               return;
+       }
+
+       rl_printf("MoveFile successful\n");
+}
+
+static void cmd_mv(int argc, char *argv[])
+{
+       GDBusProxy *proxy;
+       struct cp_args *args;
+
+       if (!check_default_session())
+               return;
+
+       if (argc < 2) {
+               rl_printf("Missing source file argument\n");
+               return;
+       }
+
+       if (argc < 3) {
+               rl_printf("Missing target file argument\n");
+               return;
+       }
+
+       proxy = find_ftp(g_dbus_proxy_get_path(default_session));
+       if (proxy == NULL) {
+               rl_printf("Command not supported\n");
+               return;
+       }
+
+       args = cp_new(argv);
+
+       if (g_dbus_proxy_method_call(proxy, "MoveFile", cp_setup,
+                               move_file_reply, args, cp_free) == FALSE) {
+               rl_printf("Failed to MoveFile\n");
+               return;
+       }
+
+       rl_printf("Attempting to MoveFile\n");
+}
+
+static void delete_reply(DBusMessage *message, void *user_data)
+{
+       DBusError error;
+
+       dbus_error_init(&error);
+
+       if (dbus_set_error_from_message(&error, message) == TRUE) {
+               rl_printf("Failed to Delete: %s\n", error.name);
+               dbus_error_free(&error);
+               return;
+       }
+
+       rl_printf("Delete successful\n");
+}
+
+static void delete_setup(DBusMessageIter *iter, void *user_data)
+{
+       const char *file = user_data;
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &file);
+}
+
+static void ftp_rm(GDBusProxy *proxy, int argc, char *argv[])
+{
+       if (argc < 2) {
+               rl_printf("Missing file argument\n");
+               return;
+       }
+
+       if (g_dbus_proxy_method_call(proxy, "Delete", delete_setup,
+                                       delete_reply, g_strdup(argv[1]),
+                                       g_free) == FALSE) {
+               rl_printf("Failed to Delete\n");
+               return;
+       }
+
+       rl_printf("Attempting to Delete\n");
+}
+
+static void set_delete_reply(const DBusError *error, void *user_data)
+{
+       if (dbus_error_is_set(error))
+               rl_printf("Failed to set Deleted: %s\n", error->name);
+       else
+               rl_printf("Set Deleted successful\n");
+}
+
+static void map_rm(GDBusProxy *proxy, int argc, char *argv[])
+{
+       GDBusProxy *msg;
+       dbus_bool_t value = TRUE;
+
+       if (argc < 2) {
+               rl_printf("Missing message argument\n");
+               return;
+       }
+
+       msg = find_message(argv[1]);
+       if (msg == NULL) {
+               rl_printf("Invalid message argument\n");
+               return;
+       }
+
+       if (g_dbus_proxy_set_property_basic(msg, "Deleted", DBUS_TYPE_BOOLEAN,
+                                               &value, set_delete_reply,
+                                               NULL, NULL) == FALSE) {
+               rl_printf("Failed to set Deleted\n");
+               return;
+       }
+
+       rl_printf("Attempting to set Deleted\n");
+}
+
+static void cmd_rm(int argc, char *argv[])
+{
+       GDBusProxy *proxy;
+
+       if (!check_default_session())
+               return;
+
+       proxy = find_ftp(g_dbus_proxy_get_path(default_session));
+       if (proxy) {
+               ftp_rm(proxy, argc, argv);
+               return;
+       }
+
+       proxy = find_map(g_dbus_proxy_get_path(default_session));
+       if (proxy) {
+               map_rm(proxy, argc, argv);
+               return;
+       }
+
+       rl_printf("Command not supported\n");
+}
+
+static void create_folder_reply(DBusMessage *message, void *user_data)
+{
+       DBusError error;
+
+       dbus_error_init(&error);
+
+       if (dbus_set_error_from_message(&error, message) == TRUE) {
+               rl_printf("Failed to CreateFolder: %s\n", error.name);
+               dbus_error_free(&error);
+               return;
+       }
+
+       rl_printf("CreateFolder successful\n");
+}
+
+static void create_folder_setup(DBusMessageIter *iter, void *user_data)
+{
+       const char *folder = user_data;
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &folder);
+}
+
+static void cmd_mkdir(int argc, char *argv[])
+{
+       GDBusProxy *proxy;
+
+       if (!check_default_session())
+               return;
+
+       if (argc < 2) {
+               rl_printf("Missing folder argument\n");
+               return;
+       }
+
+       proxy = find_ftp(g_dbus_proxy_get_path(default_session));
+       if (proxy == NULL) {
+               rl_printf("Command not supported\n");
+               return;
+       }
+
+       if (g_dbus_proxy_method_call(proxy, "CreateFolder", create_folder_setup,
+                                       create_folder_reply, g_strdup(argv[1]),
+                                       g_free) == FALSE) {
+               rl_printf("Failed to CreateFolder\n");
+               return;
+       }
+
+       rl_printf("Attempting to CreateFolder\n");
+}
+
+static const struct {
+       const char *cmd;
+       const char *arg;
+       void (*func) (int argc, char *argv[]);
+       const char *desc;
+} cmd_table[] = {
+       { "connect",      "<dev> [uuid]", cmd_connect, "Connect session" },
+       { "disconnect",   "[session]", cmd_disconnect, "Disconnect session" },
+       { "list",         NULL,       cmd_list, "List available sessions" },
+       { "show",         "[session]", cmd_show, "Session information" },
+       { "select",       "<session>", cmd_select, "Select default session" },
+       { "info",         "<object>", cmd_info, "Object information" },
+       { "cancel",       "<transfer>", cmd_cancel, "Cancel transfer" },
+       { "send",         "<file>",   cmd_send, "Send file" },
+       { "cd",           "<path>",   cmd_cd, "Change current folder" },
+       { "ls",           NULL,       cmd_ls, "List current folder" },
+       { "cp",          "<source file> <destination file>",   cmd_cp,
+                               "Copy source file to destination file" },
+       { "mv",          "<source file> <destination file>",   cmd_mv,
+                               "Move source file to destination file" },
+       { "rm",          "<file>",    cmd_rm, "Delete file" },
+       { "mkdir",       "<folder>",    cmd_mkdir, "Create folder" },
+       { "quit",         NULL,       cmd_quit, "Quit program" },
+       { "exit",         NULL,       cmd_quit },
+       { "help" },
+       {}
+};
+
+static char *cmd_generator(const char *text, int state)
+{
+       static int index, len;
+       const char *cmd;
+
+       if (!state) {
+               index = 0;
+               len = strlen(text);
+       }
+
+       while ((cmd = cmd_table[index].cmd)) {
+               index++;
+
+               if (!strncmp(cmd, text, len))
+                       return strdup(cmd);
+       }
+
+       return NULL;
+}
+
+static char **cmd_completion(const char *text, int start, int end)
+{
+       char **matches = NULL;
+
+       if (start == 0) {
+               rl_completion_display_matches_hook = NULL;
+               matches = rl_completion_matches(text, cmd_generator);
+       }
+
+       if (!matches)
+               rl_attempted_completion_over = 1;
+
+       return matches;
+}
+
+static void rl_handler(char *input)
+{
+       int argc;
+       char **argv = NULL;
+       int i;
+
+       if (!input) {
+               rl_insert_text("quit");
+               rl_redisplay();
+               rl_crlf();
+               g_main_loop_quit(main_loop);
+               return;
+       }
+
+       if (!strlen(input))
+               goto done;
+
+       add_history(input);
+
+       argv = g_strsplit(input, " ", -1);
+       if (argv == NULL)
+               goto done;
+
+       for (argc = 0; argv[argc];)
+               argc++;
+
+       if (argc == 0)
+               goto done;
+
+       for (i = 0; cmd_table[i].cmd; i++) {
+               if (strcmp(argv[0], cmd_table[i].cmd))
+                       continue;
+
+               if (cmd_table[i].func) {
+                       cmd_table[i].func(argc, argv);
+                       goto done;
+               }
+       }
+
+       if (strcmp(argv[0], "help")) {
+               printf("Invalid command\n");
+               goto done;
+       }
+
+       printf("Available commands:\n");
+
+       for (i = 0; cmd_table[i].cmd; i++) {
+               if (cmd_table[i].desc)
+                       printf("  %s %-*s %s\n", cmd_table[i].cmd,
+                                       (int)(25 - strlen(cmd_table[i].cmd)),
+                                       cmd_table[i].arg ? : "",
+                                       cmd_table[i].desc ? : "");
+       }
+
+done:
+       g_strfreev(argv);
+       free(input);
+}
+
+static gboolean option_version = FALSE;
+
+static GOptionEntry options[] = {
+       { "version", 'v', 0, G_OPTION_ARG_NONE, &option_version,
+                               "Show version information and exit" },
+       { NULL },
+};
+
+static gboolean signal_handler(GIOChannel *channel, GIOCondition condition,
+                                                       gpointer user_data)
+{
+       static unsigned int __terminated = 0;
+       struct signalfd_siginfo si;
+       ssize_t result;
+       int fd;
+
+       if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
+               g_main_loop_quit(main_loop);
+               return FALSE;
+       }
+
+       fd = g_io_channel_unix_get_fd(channel);
+
+       result = read(fd, &si, sizeof(si));
+       if (result != sizeof(si))
+               return FALSE;
+
+       switch (si.ssi_signo) {
+       case SIGINT:
+               rl_replace_line("", 0);
+               rl_crlf();
+               rl_on_new_line();
+               rl_redisplay();
+               break;
+       case SIGTERM:
+               if (__terminated == 0) {
+                       rl_replace_line("", 0);
+                       rl_crlf();
+                       g_main_loop_quit(main_loop);
+               }
+
+               __terminated = 1;
+               break;
+       }
+
+       return TRUE;
+}
+
+static guint setup_signalfd(void)
+{
+       GIOChannel *channel;
+       guint source;
+       sigset_t mask;
+       int fd;
+
+       sigemptyset(&mask);
+       sigaddset(&mask, SIGINT);
+       sigaddset(&mask, SIGTERM);
+
+       if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
+               perror("Failed to set signal mask");
+               return 0;
+       }
+
+       fd = signalfd(-1, &mask, 0);
+       if (fd < 0) {
+               perror("Failed to create signal descriptor");
+               return 0;
+       }
+
+       channel = g_io_channel_unix_new(fd);
+
+       g_io_channel_set_close_on_unref(channel, TRUE);
+       g_io_channel_set_encoding(channel, NULL, NULL);
+       g_io_channel_set_buffered(channel, FALSE);
+
+       source = g_io_add_watch(channel,
+                               G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+                               signal_handler, NULL);
+
+       g_io_channel_unref(channel);
+
+       return source;
+}
+
+static gboolean input_handler(GIOChannel *channel, GIOCondition condition,
+                                                       gpointer user_data)
+{
+       if (condition & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
+               g_main_loop_quit(main_loop);
+               return FALSE;
+       }
+
+       rl_callback_read_char();
+       return TRUE;
+}
+
+static guint setup_standard_input(void)
+{
+       GIOChannel *channel;
+       guint source;
+
+       channel = g_io_channel_unix_new(fileno(stdin));
+
+       source = g_io_add_watch(channel,
+                               G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+                               input_handler, NULL);
+
+       g_io_channel_unref(channel);
+
+       return source;
+}
+
+static void client_added(GDBusProxy *proxy)
+{
+       if (client == NULL)
+               client = proxy;
+
+       print_proxy(proxy, "Client", COLORED_NEW);
+}
+
+static void session_added(GDBusProxy *proxy)
+{
+       sessions = g_slist_append(sessions, proxy);
+
+       if (default_session == NULL)
+               set_default_session(proxy);
+
+       print_proxy(proxy, "Session", COLORED_NEW);
+}
+
+static void print_transferred(struct transfer_data *data, const char *str,
+                                                       DBusMessageIter *iter)
+{
+       dbus_uint64_t valu64;
+       uint64_t speed;
+       int seconds, minutes;
+
+       dbus_message_iter_get_basic(iter, &valu64);
+       speed = valu64 - data->transferred;
+       data->transferred = valu64;
+
+       if (data->size == 0) {
+               rl_printf("%sTransferred: %" PRIu64 " (@%" PRIu64 "KB/s)\n",
+                                               str, valu64, speed / 1000);
+               return;
+       }
+
+       seconds = (data->size - data->transferred) / speed;
+       minutes = seconds / 60;
+       seconds %= 60;
+       rl_printf("%sTransferred: %" PRIu64 " (@%" PRIu64 "KB/s %02u:%02u)\n",
+                               str, valu64, speed / 1000, minutes, seconds);
+}
+
+static void transfer_property_changed(GDBusProxy *proxy, const char *name,
+                                       DBusMessageIter *iter, void *user_data)
+{
+       struct transfer_data *data = user_data;
+       char *str;
+
+       str = proxy_description(proxy, "Transfer", COLORED_CHG);
+
+       if (strcmp(name, "Transferred") == 0) {
+               print_transferred(data, str, iter);
+               goto done;
+       }
+
+       if (strcmp(name, "Size") == 0)
+               dbus_message_iter_get_basic(iter, &data->size);
+
+       print_iter(str, name, iter);
+
+done:
+       g_free(str);
+}
+
+static void transfer_destroy(GDBusProxy *proxy, void *user_data)
+{
+       struct transfer_data *data = user_data;
+
+       g_free(data);
+}
+
+static void transfer_added(GDBusProxy *proxy)
+{
+       struct transfer_data *data;
+       DBusMessageIter iter;
+
+       transfers = g_slist_append(transfers, proxy);
+
+       print_proxy(proxy, "Transfer", COLORED_NEW);
+
+       data = g_new0(struct transfer_data, 1);
+
+       if (g_dbus_proxy_get_property(proxy, "Transfered", &iter))
+               dbus_message_iter_get_basic(&iter, &data->transferred);
+
+       if (g_dbus_proxy_get_property(proxy, "Size", &iter))
+               dbus_message_iter_get_basic(&iter, &data->size);
+
+       g_dbus_proxy_set_property_watch(proxy, transfer_property_changed, data);
+       g_dbus_proxy_set_removed_watch(proxy, transfer_destroy, data);
+}
+
+static void opp_added(GDBusProxy *proxy)
+{
+       opps = g_slist_append(opps, proxy);
+
+       print_proxy(proxy, "ObjectPush", COLORED_NEW);
+}
+
+static void ftp_added(GDBusProxy *proxy)
+{
+       ftps = g_slist_append(ftps, proxy);
+
+       print_proxy(proxy, "FileTransfer", COLORED_NEW);
+}
+
+static void pbap_added(GDBusProxy *proxy)
+{
+       pbaps = g_slist_append(pbaps, proxy);
+
+       print_proxy(proxy, "PhonebookAccess", COLORED_NEW);
+}
+
+static void map_added(GDBusProxy *proxy)
+{
+       maps = g_slist_append(maps, proxy);
+
+       print_proxy(proxy, "MessageAccess", COLORED_NEW);
+}
+
+static void msg_added(GDBusProxy *proxy)
+{
+       msgs = g_slist_append(msgs, proxy);
+
+       print_proxy(proxy, "Message", COLORED_NEW);
+}
+
+static void proxy_added(GDBusProxy *proxy, void *user_data)
+{
+       const char *interface;
+
+       interface = g_dbus_proxy_get_interface(proxy);
+
+       if (!strcmp(interface, OBEX_CLIENT_INTERFACE))
+               client_added(proxy);
+       else if (!strcmp(interface, OBEX_SESSION_INTERFACE))
+               session_added(proxy);
+       else if (!strcmp(interface, OBEX_TRANSFER_INTERFACE))
+               transfer_added(proxy);
+       else if (!strcmp(interface, OBEX_OPP_INTERFACE))
+               opp_added(proxy);
+       else if (!strcmp(interface, OBEX_FTP_INTERFACE))
+               ftp_added(proxy);
+       else if (!strcmp(interface, OBEX_PBAP_INTERFACE))
+               pbap_added(proxy);
+       else if (!strcmp(interface, OBEX_MAP_INTERFACE))
+               map_added(proxy);
+       else if (!strcmp(interface, OBEX_MSG_INTERFACE))
+               msg_added(proxy);
+}
+
+static void client_removed(GDBusProxy *proxy)
+{
+       print_proxy(proxy, "Client", COLORED_DEL);
+
+       if (client == proxy)
+               client = NULL;
+}
+
+static void session_removed(GDBusProxy *proxy)
+{
+       print_proxy(proxy, "Session", COLORED_DEL);
+
+       if (default_session == proxy)
+               set_default_session(NULL);
+
+       sessions = g_slist_remove(sessions, proxy);
+}
+
+static void transfer_removed(GDBusProxy *proxy)
+{
+       print_proxy(proxy, "Transfer", COLORED_DEL);
+
+       transfers = g_slist_remove(transfers, proxy);
+}
+
+static void opp_removed(GDBusProxy *proxy)
+{
+       print_proxy(proxy, "ObjectPush", COLORED_DEL);
+
+       opps = g_slist_remove(opps, proxy);
+}
+
+static void ftp_removed(GDBusProxy *proxy)
+{
+       print_proxy(proxy, "FileTransfer", COLORED_DEL);
+
+       ftps = g_slist_remove(ftps, proxy);
+}
+
+static void pbap_removed(GDBusProxy *proxy)
+{
+       print_proxy(proxy, "PhonebookAccess", COLORED_DEL);
+
+       pbaps = g_slist_remove(pbaps, proxy);
+}
+
+static void map_removed(GDBusProxy *proxy)
+{
+       print_proxy(proxy, "MessageAccess", COLORED_DEL);
+
+       maps = g_slist_remove(maps, proxy);
+}
+
+static void msg_removed(GDBusProxy *proxy)
+{
+       print_proxy(proxy, "Message", COLORED_DEL);
+
+       msgs = g_slist_remove(msgs, proxy);
+}
+
+static void proxy_removed(GDBusProxy *proxy, void *user_data)
+{
+       const char *interface;
+
+       interface = g_dbus_proxy_get_interface(proxy);
+
+       if (!strcmp(interface, OBEX_CLIENT_INTERFACE))
+               client_removed(proxy);
+       else if (!strcmp(interface, OBEX_SESSION_INTERFACE))
+               session_removed(proxy);
+       else if (!strcmp(interface, OBEX_TRANSFER_INTERFACE))
+               transfer_removed(proxy);
+       else if (!strcmp(interface, OBEX_OPP_INTERFACE))
+               opp_removed(proxy);
+       else if (!strcmp(interface, OBEX_FTP_INTERFACE))
+               ftp_removed(proxy);
+       else if (!strcmp(interface, OBEX_PBAP_INTERFACE))
+               pbap_removed(proxy);
+       else if (!strcmp(interface, OBEX_MAP_INTERFACE))
+               map_removed(proxy);
+       else if (!strcmp(interface, OBEX_MSG_INTERFACE))
+               msg_removed(proxy);
+}
+
+static void session_property_changed(GDBusProxy *proxy, const char *name,
+                                               DBusMessageIter *iter)
+{
+       char *str;
+
+       str = proxy_description(proxy, "Session", COLORED_CHG);
+       print_iter(str, name, iter);
+       g_free(str);
+}
+
+static void property_changed(GDBusProxy *proxy, const char *name,
+                                       DBusMessageIter *iter, void *user_data)
+{
+       const char *interface;
+
+       interface = g_dbus_proxy_get_interface(proxy);
+
+       if (!strcmp(interface, OBEX_SESSION_INTERFACE))
+               session_property_changed(proxy, name, iter);
+}
+
+int main(int argc, char *argv[])
+{
+       GOptionContext *context;
+       GError *error = NULL;
+       GDBusClient *client;
+       guint signal, input;
+
+       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);
+       }
+
+       main_loop = g_main_loop_new(NULL, FALSE);
+       dbus_conn = g_dbus_setup_bus(DBUS_BUS_SESSION, NULL, NULL);
+
+       rl_attempted_completion_function = cmd_completion;
+
+       rl_erase_empty_line = 1;
+       rl_callback_handler_install(NULL, rl_handler);
+
+       rl_set_prompt(PROMPT_OFF);
+       rl_redisplay();
+
+       input = setup_standard_input();
+       signal = setup_signalfd();
+       client = g_dbus_client_new(dbus_conn, "org.bluez.obex",
+                                                       "/org/bluez/obex");
+
+       g_dbus_client_set_connect_watch(client, connect_handler, NULL);
+       g_dbus_client_set_disconnect_watch(client, disconnect_handler, NULL);
+
+       g_dbus_client_set_proxy_handlers(client, proxy_added, proxy_removed,
+                                                       property_changed, NULL);
+
+       g_main_loop_run(main_loop);
+
+       g_dbus_client_unref(client);
+       g_source_remove(signal);
+       g_source_remove(input);
+
+       rl_message("");
+       rl_callback_handler_remove();
+
+       dbus_connection_unref(dbus_conn);
+       g_main_loop_unref(main_loop);
+
+       return 0;
+}
index 88ad818d662cefa9e90e84fa6c0b892395b4a588..ea959333d97749baef5f5ca5b5cdd1754b49a79f 100644 (file)
@@ -91,9 +91,15 @@ the \fB--handle\fP option.
 .IP "" 10
 You can specify a channel to add the service on
 using the \fB--channel\fP option.
+.IP "" 10
+NOTE: Local adapters configuration will not be updated and this command should
+be used only for SDP testing.
 .IP "\fBdel record_handle\fP" 10
 Remove a service from the local
 SDP database.
+.IP "" 10
+NOTE: Local adapters configuration will not be updated and this command should
+be used only for SDP testing.
 .IP "\fBget [--tree] [--raw] [--xml] [--bdaddr bdaddr] record_handle\fP" 10
 Retrieve a service from the local
 SDP database.
diff --git a/tools/update_compids.sh b/tools/update_compids.sh
deleted file mode 100755 (executable)
index 38d1fff..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/bin/bash
-# Download the list of company IDs from bluetooth.org and generate a diff which
-# can be applied to source tree to update bt_compidtostr(). Usage:
-#
-# 1) ./tools/update_compids.sh | git apply -p0
-# 2) Inspect changes to make sure they are sane
-# 3) git commit -m "lib: Update list of company identifiers" lib/bluetooth.c
-#
-# Requires html2text: http://www.mbayer.de/html2text/
-#
-set -e -u
-
-tmpdir=$(mktemp -d)
-trap "rm -rf $tmpdir" EXIT
-
-mkdir $tmpdir/lib
-cp lib/bluetooth.c $tmpdir/lib/bluetooth.c.orig
-cp lib/bluetooth.c $tmpdir/lib/bluetooth.c
-
-cd $tmpdir
-
-path=en-us/specification/assigned-numbers/company-identifiers
-# Use "iconv -c" to strip unwanted unicode characters
-# Fixups:
-# - strip <input> tags of type "checkbox" because html2text generates UTF-8 for
-#   them in some distros even when using -ascii (e.g. Fedora)
-# - replace "&#160;" (non-breaking space) with whitespace manually, because
-#   some versions incorrectly convert it into "\xC2\xA0"
-curl https://www.bluetooth.org/$path | iconv -c -f utf8 -t ascii | \
-    sed '/<input.*type="checkbox"/d; s/&#160;/ /g' | \
-    html2text -ascii -o identifiers.txt >/dev/null
-
-# Some versions of html2text do not replace &amp; (e.g. Fedora)
-sed -i 's/&amp;/\&/g' identifiers.txt
-
-sed -n '/^const char \*bt_compidtostr(int compid)/,/^}/p' \
-    lib/bluetooth.c > old.c
-
-echo -e 'const char *bt_compidtostr(int compid)\n{\n\tswitch (compid) {' > new.c
-cat identifiers.txt |
-    perl -ne 'm/^(\d+)\s+0x[0-9a-f]+\s+(.*)/i &&
-        print "\tcase $1:\n\t\treturn \"$2\";\n"' >> new.c
-if ! grep -q "return \"" new.c; then
-    echo "ERROR: could not parse company IDs from bluetooth.org" >&2
-    exit 1
-fi
-if [ -n "$(tr -d '[:print:]\t\n' < new.c)" ]; then
-    echo -n "ERROR: invalid non-ASCII characters found while parsing" >&2
-    echo -n " company IDs. Please identify offending sequence and fix" >&2
-    echo " tools/update_compids.sh accordingly." >&2
-    exit 1
-fi
-echo -e '\tcase 65535:\n\t\treturn "internal use";' >> new.c
-echo -e '\tdefault:\n\t\treturn "not assigned";\n\t}\n}' >> new.c
-
-diff -Naur old.c new.c | patch -sp0 lib/bluetooth.c
-diff -Naur lib/bluetooth.c.orig lib/bluetooth.c
diff --git a/ylwrap b/ylwrap
deleted file mode 100755 (executable)
index 9253635..0000000
--- a/ylwrap
+++ /dev/null
@@ -1,226 +0,0 @@
-#! /bin/sh
-# ylwrap - wrapper for lex/yacc invocations.
-
-scriptversion=2011-08-25.18; # UTC
-
-# Copyright (C) 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004, 2005,
-# 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
-#
-# Written by Tom Tromey <tromey@cygnus.com>.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, 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, see <http://www.gnu.org/licenses/>.
-
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# This file is maintained in Automake, please report
-# bugs to <bug-automake@gnu.org> or send patches to
-# <automake-patches@gnu.org>.
-
-case "$1" in
-  '')
-    echo "$0: No files given.  Try \`$0 --help' for more information." 1>&2
-    exit 1
-    ;;
-  --basedir)
-    basedir=$2
-    shift 2
-    ;;
-  -h|--h*)
-    cat <<\EOF
-Usage: ylwrap [--help|--version] INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]...
-
-Wrapper for lex/yacc invocations, renaming files as desired.
-
-  INPUT is the input file
-  OUTPUT is one file PROG generates
-  DESIRED is the file we actually want instead of OUTPUT
-  PROGRAM is program to run
-  ARGS are passed to PROG
-
-Any number of OUTPUT,DESIRED pairs may be used.
-
-Report bugs to <bug-automake@gnu.org>.
-EOF
-    exit $?
-    ;;
-  -v|--v*)
-    echo "ylwrap $scriptversion"
-    exit $?
-    ;;
-esac
-
-
-# The input.
-input="$1"
-shift
-case "$input" in
-  [\\/]* | ?:[\\/]*)
-    # Absolute path; do nothing.
-    ;;
-  *)
-    # Relative path.  Make it absolute.
-    input="`pwd`/$input"
-    ;;
-esac
-
-pairlist=
-while test "$#" -ne 0; do
-  if test "$1" = "--"; then
-    shift
-    break
-  fi
-  pairlist="$pairlist $1"
-  shift
-done
-
-# The program to run.
-prog="$1"
-shift
-# Make any relative path in $prog absolute.
-case "$prog" in
-  [\\/]* | ?:[\\/]*) ;;
-  *[\\/]*) prog="`pwd`/$prog" ;;
-esac
-
-# FIXME: add hostname here for parallel makes that run commands on
-# other machines.  But that might take us over the 14-char limit.
-dirname=ylwrap$$
-do_exit="cd '`pwd`' && rm -rf $dirname > /dev/null 2>&1;"' (exit $ret); exit $ret'
-trap "ret=129; $do_exit" 1
-trap "ret=130; $do_exit" 2
-trap "ret=141; $do_exit" 13
-trap "ret=143; $do_exit" 15
-mkdir $dirname || exit 1
-
-cd $dirname
-
-case $# in
-  0) "$prog" "$input" ;;
-  *) "$prog" "$@" "$input" ;;
-esac
-ret=$?
-
-if test $ret -eq 0; then
-  set X $pairlist
-  shift
-  first=yes
-  # Since DOS filename conventions don't allow two dots,
-  # the DOS version of Bison writes out y_tab.c instead of y.tab.c
-  # and y_tab.h instead of y.tab.h. Test to see if this is the case.
-  y_tab_nodot="no"
-  if test -f y_tab.c || test -f y_tab.h; then
-    y_tab_nodot="yes"
-  fi
-
-  # The directory holding the input.
-  input_dir=`echo "$input" | sed -e 's,\([\\/]\)[^\\/]*$,\1,'`
-  # Quote $INPUT_DIR so we can use it in a regexp.
-  # FIXME: really we should care about more than `.' and `\'.
-  input_rx=`echo "$input_dir" | sed 's,\\\\,\\\\\\\\,g;s,\\.,\\\\.,g'`
-
-  while test "$#" -ne 0; do
-    from="$1"
-    # Handle y_tab.c and y_tab.h output by DOS
-    if test $y_tab_nodot = "yes"; then
-      if test $from = "y.tab.c"; then
-        from="y_tab.c"
-      else
-        if test $from = "y.tab.h"; then
-          from="y_tab.h"
-        fi
-      fi
-    fi
-    if test -f "$from"; then
-      # If $2 is an absolute path name, then just use that,
-      # otherwise prepend `../'.
-      case "$2" in
-        [\\/]* | ?:[\\/]*) target="$2";;
-        *) target="../$2";;
-      esac
-
-      # We do not want to overwrite a header file if it hasn't
-      # changed.  This avoid useless recompilations.  However the
-      # parser itself (the first file) should always be updated,
-      # because it is the destination of the .y.c rule in the
-      # Makefile.  Divert the output of all other files to a temporary
-      # file so we can compare them to existing versions.
-      if test $first = no; then
-        realtarget="$target"
-        target="tmp-`echo $target | sed s/.*[\\/]//g`"
-      fi
-      # Edit out `#line' or `#' directives.
-      #
-      # We don't want the resulting debug information to point at
-      # an absolute srcdir; it is better for it to just mention the
-      # .y file with no path.
-      #
-      # We want to use the real output file name, not yy.lex.c for
-      # instance.
-      #
-      # We want the include guards to be adjusted too.
-      FROM=`echo "$from" | sed \
-            -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\
-            -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'`
-      TARGET=`echo "$2" | sed \
-            -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\
-            -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'`
-
-      sed -e "/^#/!b" -e "s,$input_rx,," -e "s,$from,$2," \
-          -e "s,$FROM,$TARGET," "$from" >"$target" || ret=$?
-
-      # Check whether header files must be updated.
-      if test $first = no; then
-        if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then
-          echo "$2" is unchanged
-          rm -f "$target"
-        else
-          echo updating "$2"
-          mv -f "$target" "$realtarget"
-        fi
-      fi
-    else
-      # A missing file is only an error for the first file.  This
-      # is a blatant hack to let us support using "yacc -d".  If -d
-      # is not specified, we don't want an error when the header
-      # file is "missing".
-      if test $first = yes; then
-        ret=1
-      fi
-    fi
-    shift
-    shift
-    first=no
-  done
-else
-  ret=$?
-fi
-
-# Remove the directory.
-cd ..
-rm -rf $dirname
-
-exit $ret
-
-# Local Variables:
-# mode: shell-script
-# sh-indentation: 2
-# eval: (add-hook 'write-file-hooks 'time-stamp)
-# time-stamp-start: "scriptversion="
-# time-stamp-format: "%:y-%02m-%02d.%02H"
-# time-stamp-time-zone: "UTC"
-# time-stamp-end: "; # UTC"
-# End: