summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWu zheng <wu.zheng@intel.com>2013-10-21 15:46:54 +0800
committerWu zheng <wu.zheng@intel.com>2013-10-21 15:46:54 +0800
commit034a07d678ede7415b6942437a56d9804585e8c7 (patch)
tree19f2478d0a294d5abe604c6c24abf3451b0d30ad
parentfaf72771582dd07a97a670650c96f6f9664f6785 (diff)
downloadbluez-devel_test.tar.gz
bluez-devel_test.tar.bz2
bluez-devel_test.zip
Upgrade to bluez-5.10 for testingdevel_test
-rw-r--r--ChangeLog11
-rw-r--r--Makefile.am2
-rw-r--r--Makefile.android2
-rw-r--r--Makefile.in196
-rw-r--r--Makefile.tools7
-rw-r--r--android/Android.mk20
-rw-r--r--android/hal-ipc-api.txt1247
-rw-r--r--bluez.pc.in10
-rwxr-xr-xconfigure42
-rw-r--r--configure.ac2
-rw-r--r--doc/input-api.txt32
-rw-r--r--doc/mgmt-api.txt50
-rw-r--r--doc/settings-storage.txt225
-rw-r--r--emulator/btdev.c23
-rw-r--r--gdbus/client.c5
-rw-r--r--gdbus/object.c11
-rw-r--r--monitor/bt.h9
-rw-r--r--monitor/packet.c31
-rw-r--r--obexd/client/session.c12
-rw-r--r--obexd/plugins/messages-tracker.c345
-rw-r--r--obexd/plugins/phonebook-ebook.c707
-rw-r--r--obexd/plugins/phonebook-tracker.c1718
-rw-r--r--obexd/plugins/syncevolution.c482
-rwxr-xr-x[-rw-r--r--]packaging/bluetooth.sh0
-rw-r--r--packaging/bluez.spec2
-rwxr-xr-x[-rw-r--r--]packaging/create-symlinks0
-rwxr-xr-x[-rw-r--r--]packaging/obex-root-setup0
-rw-r--r--profiles/audio/1.patch108
-rw-r--r--profiles/audio/avctp.c21
-rw-r--r--profiles/audio/avdtp.c44
-rw-r--r--profiles/audio/media.c40
-rwxr-xr-xtest/exchange-business-cards19
-rwxr-xr-xtest/ftp-client176
-rwxr-xr-xtest/get-managed-objects29
-rwxr-xr-xtest/get-obex-capabilities19
-rwxr-xr-xtest/list-folders39
-rwxr-xr-xtest/map-client231
-rwxr-xr-xtest/opp-client116
-rwxr-xr-xtest/pbap-client173
-rwxr-xr-xtest/simple-obex-agent85
-rw-r--r--[-rwxr-xr-x]test/test-alert0
-rw-r--r--[-rwxr-xr-x]test/test-cyclingspeed0
-rw-r--r--[-rwxr-xr-x]test/test-heartrate0
-rw-r--r--[-rwxr-xr-x]test/test-hfp0
-rw-r--r--[-rwxr-xr-x]test/test-profile0
-rw-r--r--tools/bdaddr.168
-rw-r--r--tools/btmgmt.c4
-rw-r--r--tools/example.psr12
-rw-r--r--tools/mgmt-tester.c37
-rw-r--r--tools/mpris-player.c27
-rw-r--r--tools/obexctl.c2400
-rw-r--r--tools/sdptool.16
-rwxr-xr-xtools/update_compids.sh57
-rwxr-xr-xylwrap226
54 files changed, 4133 insertions, 4995 deletions
diff --git a/ChangeLog b/ChangeLog
index d8296402..fc9b3d7f 100644
--- 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.
diff --git a/Makefile.am b/Makefile.am
index 51204f47..8aed6f7e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -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
diff --git a/Makefile.android b/Makefile.android
index e161e6dc..3ceefd8f 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -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
diff --git a/Makefile.in b/Makefile.in
index 68410241..677ad3e9 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -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
diff --git a/Makefile.tools b/Makefile.tools
index 87bb62e8..840b95cb 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -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
diff --git a/android/Android.mk b/android/Android.mk
index ec820aca..0e025acd 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -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
index 00000000..9a8b770f
--- /dev/null
+++ b/android/hal-ipc-api.txt
@@ -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
index 3d6e5961..00000000
--- a/bluez.pc.in
+++ /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}
diff --git a/configure b/configure
index 26a2e354..2bb5b0f5 100755
--- 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\\"
diff --git a/configure.ac b/configure.ac
index 7b1f64aa..b4d3998d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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
index 67da08b1..00000000
--- a/doc/input-api.txt
+++ /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.
diff --git a/doc/mgmt-api.txt b/doc/mgmt-api.txt
index c1590494..371f2529 100644
--- a/doc/mgmt-api.txt
+++ b/doc/mgmt-api.txt
@@ -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
index a3b58e63..00000000
--- a/doc/settings-storage.txt
+++ /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
diff --git a/emulator/btdev.c b/emulator/btdev.c
index f98b5239..5f04bd17 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -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;
diff --git a/gdbus/client.c b/gdbus/client.c
index 7bffdad1..be8cc296 100644
--- a/gdbus/client.c
+++ b/gdbus/client.c
@@ -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);
diff --git a/gdbus/object.c b/gdbus/object.c
index 0822fe88..268fed55 100644
--- a/gdbus/object.c
+++ b/gdbus/object.c
@@ -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,
diff --git a/monitor/bt.h b/monitor/bt.h
index d82fddaf..2245ab31 100644
--- a/monitor/bt.h
+++ b/monitor/bt.h
@@ -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 {
diff --git a/monitor/packet.c b/monitor/packet.c
index b7f83145..55c9f0f0 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -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 },
diff --git a/obexd/client/session.c b/obexd/client/session.c
index 63692a12..7a56acdb 100644
--- a/obexd/client/session.c
+++ b/obexd/client/session.c
@@ -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
index 60f3a807..00000000
--- a/obexd/plugins/messages-tracker.c
+++ /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
index 2e495767..00000000
--- a/obexd/plugins/phonebook-ebook.c
+++ /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
index 433f95a7..00000000
--- a/obexd/plugins/phonebook-tracker.c
+++ /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
index edc00c84..00000000
--- a/obexd/plugins/syncevolution.c
+++ /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)
diff --git a/packaging/bluetooth.sh b/packaging/bluetooth.sh
index 8cec6360..8cec6360 100644..100755
--- a/packaging/bluetooth.sh
+++ b/packaging/bluetooth.sh
diff --git a/packaging/bluez.spec b/packaging/bluez.spec
index e5592f35..0395ca5f 100644
--- a/packaging/bluez.spec
+++ b/packaging/bluez.spec
@@ -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+
diff --git a/packaging/create-symlinks b/packaging/create-symlinks
index 31aa6ab3..31aa6ab3 100644..100755
--- a/packaging/create-symlinks
+++ b/packaging/create-symlinks
diff --git a/packaging/obex-root-setup b/packaging/obex-root-setup
index fc0864f7..fc0864f7 100644..100755
--- a/packaging/obex-root-setup
+++ b/packaging/obex-root-setup
diff --git a/profiles/audio/1.patch b/profiles/audio/1.patch
deleted file mode 100644
index fa44d323..00000000
--- a/profiles/audio/1.patch
+++ /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);
- }
diff --git a/profiles/audio/avctp.c b/profiles/audio/avctp.c
index 845027f9..dac7a66c 100644
--- a/profiles/audio/avctp.c
+++ b/profiles/audio/avctp.c
@@ -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;
diff --git a/profiles/audio/avdtp.c b/profiles/audio/avdtp.c
index 622dff81..dab8f1c8 100644
--- a/profiles/audio/avdtp.c
+++ b/profiles/audio/avdtp.c
@@ -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;
diff --git a/profiles/audio/media.c b/profiles/audio/media.c
index 9c72b8dc..5edd3dee 100644
--- a/profiles/audio/media.c
+++ b/profiles/audio/media.c
@@ -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
index 6805cf71..00000000
--- a/test/exchange-business-cards
+++ /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
index ae3cbcb9..00000000
--- a/test/ftp-client
+++ /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
index 3156f658..00000000
--- a/test/get-managed-objects
+++ /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
index e8afbad2..00000000
--- a/test/get-obex-capabilities
+++ /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
index 7321a152..00000000
--- a/test/list-folders
+++ /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
index f3c657f7..00000000
--- a/test/map-client
+++ /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
index 878c263c..00000000
--- a/test/opp-client
+++ /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
index c02833bd..00000000
--- a/test/pbap-client
+++ /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
index f15e9d1d..00000000
--- a/test/simple-obex-agent
+++ /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"
diff --git a/test/test-alert b/test/test-alert
index 066e5378..066e5378 100755..100644
--- a/test/test-alert
+++ b/test/test-alert
diff --git a/test/test-cyclingspeed b/test/test-cyclingspeed
index 75bd7d74..75bd7d74 100755..100644
--- a/test/test-cyclingspeed
+++ b/test/test-cyclingspeed
diff --git a/test/test-heartrate b/test/test-heartrate
index f26b3dba..f26b3dba 100755..100644
--- a/test/test-heartrate
+++ b/test/test-heartrate
diff --git a/test/test-hfp b/test/test-hfp
index 873de0a2..873de0a2 100755..100644
--- a/test/test-hfp
+++ b/test/test-hfp
diff --git a/test/test-profile b/test/test-profile
index b78d00c9..b78d00c9 100755..100644
--- a/test/test-profile
+++ b/test/test-profile
diff --git a/tools/bdaddr.1 b/tools/bdaddr.1
deleted file mode 100644
index efb77d2e..00000000
--- a/tools/bdaddr.1
+++ /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
diff --git a/tools/btmgmt.c b/tools/btmgmt.c
index 51332278..1d71d74f 100644
--- a/tools/btmgmt.c
+++ b/tools/btmgmt.c
@@ -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
index bbbec73a..00000000
--- a/tools/example.psr
+++ /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
diff --git a/tools/mgmt-tester.c b/tools/mgmt-tester.c
index 90eae67e..2ef72cfe 100644
--- a/tools/mgmt-tester.c
+++ b/tools/mgmt-tester.c
@@ -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();
}
diff --git a/tools/mpris-player.c b/tools/mpris-player.c
index 03b8875d..c94330cb 100644
--- a/tools/mpris-player.c
+++ b/tools/mpris-player.c
@@ -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
index 00000000..0491b514
--- /dev/null
+++ b/tools/obexctl.c
@@ -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;
+}
diff --git a/tools/sdptool.1 b/tools/sdptool.1
index 88ad818d..ea959333 100644
--- a/tools/sdptool.1
+++ b/tools/sdptool.1
@@ -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
index 38d1fff3..00000000
--- a/tools/update_compids.sh
+++ /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
index 92536350..00000000
--- 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: