All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH BlueZ 0/9] Distribution inspired fixes
@ 2024-01-24 23:43 ` Emil Velikov
  0 siblings, 0 replies; 28+ messages in thread
From: Emil Velikov via B4 Relay @ 2024-01-24 23:43 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: Vicki Pfau, Rachel Blackman, Sam Lantinga, Bastien Nocera,
	Emil Velikov, Nobuhiro Iwamatsu

Hello team,

This series picks (directly where possible) distro shipped fixes, for
upstream inclusion.

In particular we have:
 - first two patches have been in SteamOS 3 for about 1 year
 - adapter: Remove experimental flag for PowerState - has been shipping
   in Gentoo and Fedora since Dec 2022, at least
 - use /usr/bin/env python3 sheband - Debian inspired
 - remove unused suspend-dummy.c - Debian inspired
 - remove three unused obex plugins/backends - inspired by ^^ removal
 - ship all conf files with --enable-datafiles - Arch, Gentoo, Fedora

Everything apart from the first two, should be dead trivial. I have
little knowledge about the SteamOS inspired fixes, so hopefully
maintainers won't have too many questions there ;-)

As the comment in the last commit says - there's one final batch
(planned) of patches. Allowing for more flexible conf management, akin
to `man sysctl.d`.

Although I will send those out, once most of the existing patches have
landed.

---
Bastien Nocera (1):
      adapter: Remove experimental flag for PowerState

Emil Velikov (6):
      test: consistently use /usr/bin/env python3 shebang
      profiles: remove unused suspend-dummy.c
      obex: remove unused syncevolution plugin
      obex: remove unused mas/messages-tracker impl
      obex: remove phonebook tracker backend
      build: ship all config files with --enable-datafiles

Sam Lantinga (1):
      Return at least the title attribute from player_list_metadata()

Vicki Pfau (1):
      Enable alternate Bluetooth connection modes

 Makefile.am                       |    8 +-
 Makefile.mesh                     |    1 +
 Makefile.obexd                    |    3 +-
 Makefile.plugins                  |    2 -
 configure.ac                      |    6 +-
 obexd/plugins/messages-tracker.c  |  332 --------
 obexd/plugins/phonebook-tracker.c | 1704 -------------------------------------
 obexd/plugins/syncevolution.c     |  470 ----------
 profiles/audio/avrcp.c            |    4 +
 profiles/input/suspend-dummy.c    |  149 ----
 src/adapter.c                     |   49 +-
 src/btd.h                         |    2 +
 src/main.c                        |   66 ++
 src/main.conf                     |    5 +
 test/agent.py                     |    2 +-
 test/example-adv-monitor          |    2 +-
 test/example-advertisement        |    2 +-
 test/example-endpoint             |    2 +-
 test/example-player               |    2 +-
 test/exchange-business-cards      |    2 +-
 test/ftp-client                   |    2 +-
 test/get-managed-objects          |    2 +-
 test/get-obex-capabilities        |    2 +-
 test/list-devices                 |    2 +-
 test/list-folders                 |    2 +-
 test/map-client                   |    2 +-
 test/monitor-bluetooth            |    2 +-
 test/opp-client                   |    2 +-
 test/pbap-client                  |    2 +-
 test/simple-agent                 |    2 +-
 test/simple-endpoint              |    2 +-
 test/simple-obex-agent            |    2 +-
 test/simple-player                |    2 +-
 test/test-adapter                 |    2 +-
 test/test-device                  |    2 +-
 test/test-discovery               |    2 +-
 test/test-gatt-profile            |    2 +-
 test/test-health                  |    2 +-
 test/test-health-sink             |    2 +-
 test/test-hfp                     |    2 +-
 test/test-manager                 |    2 +-
 test/test-nap                     |    2 +-
 test/test-network                 |    2 +-
 test/test-profile                 |    2 +-
 test/test-sap-server              |    2 +-
 45 files changed, 167 insertions(+), 2696 deletions(-)
---
base-commit: a9d1f6f6a625607de6c3f5b7a40a3aac5f36c02b
change-id: 20240124-disto-patches-efd6b726602f

Best regards,
-- 
Emil Velikov <emil.l.velikov@gmail.com>


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH BlueZ 0/9] Distribution inspired fixes
@ 2024-01-24 23:43 ` Emil Velikov
  0 siblings, 0 replies; 28+ messages in thread
From: Emil Velikov @ 2024-01-24 23:43 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: Vicki Pfau, Rachel Blackman, Sam Lantinga, Bastien Nocera,
	Emil Velikov, Nobuhiro Iwamatsu

Hello team,

This series picks (directly where possible) distro shipped fixes, for
upstream inclusion.

In particular we have:
 - first two patches have been in SteamOS 3 for about 1 year
 - adapter: Remove experimental flag for PowerState - has been shipping
   in Gentoo and Fedora since Dec 2022, at least
 - use /usr/bin/env python3 sheband - Debian inspired
 - remove unused suspend-dummy.c - Debian inspired
 - remove three unused obex plugins/backends - inspired by ^^ removal
 - ship all conf files with --enable-datafiles - Arch, Gentoo, Fedora

Everything apart from the first two, should be dead trivial. I have
little knowledge about the SteamOS inspired fixes, so hopefully
maintainers won't have too many questions there ;-)

As the comment in the last commit says - there's one final batch
(planned) of patches. Allowing for more flexible conf management, akin
to `man sysctl.d`.

Although I will send those out, once most of the existing patches have
landed.

---
Bastien Nocera (1):
      adapter: Remove experimental flag for PowerState

Emil Velikov (6):
      test: consistently use /usr/bin/env python3 shebang
      profiles: remove unused suspend-dummy.c
      obex: remove unused syncevolution plugin
      obex: remove unused mas/messages-tracker impl
      obex: remove phonebook tracker backend
      build: ship all config files with --enable-datafiles

Sam Lantinga (1):
      Return at least the title attribute from player_list_metadata()

Vicki Pfau (1):
      Enable alternate Bluetooth connection modes

 Makefile.am                       |    8 +-
 Makefile.mesh                     |    1 +
 Makefile.obexd                    |    3 +-
 Makefile.plugins                  |    2 -
 configure.ac                      |    6 +-
 obexd/plugins/messages-tracker.c  |  332 --------
 obexd/plugins/phonebook-tracker.c | 1704 -------------------------------------
 obexd/plugins/syncevolution.c     |  470 ----------
 profiles/audio/avrcp.c            |    4 +
 profiles/input/suspend-dummy.c    |  149 ----
 src/adapter.c                     |   49 +-
 src/btd.h                         |    2 +
 src/main.c                        |   66 ++
 src/main.conf                     |    5 +
 test/agent.py                     |    2 +-
 test/example-adv-monitor          |    2 +-
 test/example-advertisement        |    2 +-
 test/example-endpoint             |    2 +-
 test/example-player               |    2 +-
 test/exchange-business-cards      |    2 +-
 test/ftp-client                   |    2 +-
 test/get-managed-objects          |    2 +-
 test/get-obex-capabilities        |    2 +-
 test/list-devices                 |    2 +-
 test/list-folders                 |    2 +-
 test/map-client                   |    2 +-
 test/monitor-bluetooth            |    2 +-
 test/opp-client                   |    2 +-
 test/pbap-client                  |    2 +-
 test/simple-agent                 |    2 +-
 test/simple-endpoint              |    2 +-
 test/simple-obex-agent            |    2 +-
 test/simple-player                |    2 +-
 test/test-adapter                 |    2 +-
 test/test-device                  |    2 +-
 test/test-discovery               |    2 +-
 test/test-gatt-profile            |    2 +-
 test/test-health                  |    2 +-
 test/test-health-sink             |    2 +-
 test/test-hfp                     |    2 +-
 test/test-manager                 |    2 +-
 test/test-nap                     |    2 +-
 test/test-network                 |    2 +-
 test/test-profile                 |    2 +-
 test/test-sap-server              |    2 +-
 45 files changed, 167 insertions(+), 2696 deletions(-)
---
base-commit: a9d1f6f6a625607de6c3f5b7a40a3aac5f36c02b
change-id: 20240124-disto-patches-efd6b726602f

Best regards,
-- 
Emil Velikov <emil.l.velikov@gmail.com>


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH BlueZ 1/9] Enable alternate Bluetooth connection modes
  2024-01-24 23:43 ` Emil Velikov
@ 2024-01-24 23:43   ` Emil Velikov
  -1 siblings, 0 replies; 28+ messages in thread
From: Emil Velikov via B4 Relay @ 2024-01-24 23:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Vicki Pfau, Rachel Blackman

From: Vicki Pfau <vi@endrift.com>

This patch improves Bluetooth connectivity, especially with multiple
controllers and while docked.

Testing:
$ btmgmt
[mgmt]# phy

Verify the SupportedPHYs in main.conf are listed.
Verify that multiple controllers can connect and work well.

Co-Authored-By: Rachel Blackman <rachel.blackman@synapse.com>

[Emil Velikov]
Remove unused function, add default entries into parser, keep only
default entries in main.conf - commented out, like the other options.
---
 src/adapter.c | 46 +++++++++++++++++++++++++++++++++++++++++
 src/btd.h     |  2 ++
 src/main.c    | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/main.conf |  5 +++++
 4 files changed, 119 insertions(+)

diff --git a/src/adapter.c b/src/adapter.c
index 022390f0d..4c6b8f40f 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -86,6 +86,18 @@
 #define DISTANCE_VAL_INVALID	0x7FFF
 #define PATHLOSS_MAX		137
 
+#define LE_PHY_1M 0x01
+#define LE_PHY_2M 0x02
+#define LE_PHY_CODED 0x04
+
+#define PHYVAL_REQUIRED 0x07ff
+#define PHYVAL_1M_TX (1<<9)
+#define PHYVAL_1M_RX (1<<10)
+#define PHYVAL_2M_TX (1<<11)
+#define PHYVAL_2M_RX (1<<12)
+#define PHYVAL_CODED_TX (1<<13)
+#define PHYVAL_CODED_RX (1<<14)
+
 /*
  * These are known security keys that have been compromised.
  * If this grows or there are needs to be platform specific, it is
@@ -847,6 +859,36 @@ static bool set_discoverable(struct btd_adapter *adapter, uint8_t mode,
 	return false;
 }
 
+static void set_phy_support_complete(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	if (status != 0) {
+		struct btd_adapter *adapter = (struct btd_adapter *)user_data;
+
+		btd_error(adapter->dev_id, "PHY setting rejected for %u: %s",
+								adapter->dev_id, mgmt_errstr(status));
+	}
+}
+
+static bool set_phy_support(struct btd_adapter *adapter, uint32_t phy_mask)
+{
+	struct mgmt_cp_set_phy_confguration cp;
+
+	memset(&cp, 0, sizeof(cp));
+	cp.selected_phys = cpu_to_le32(phy_mask | PHYVAL_REQUIRED);
+
+	if (mgmt_send(adapter->mgmt, MGMT_OP_SET_PHY_CONFIGURATION,
+				adapter->dev_id, sizeof(cp), &cp,
+				set_phy_support_complete, (void*)adapter, NULL) > 0)
+		return true;
+
+	btd_error(adapter->dev_id, "Failed to set PHY for index %u",
+							adapter->dev_id);
+
+	return false;
+
+}
+
 static bool pairable_timeout_handler(gpointer user_data)
 {
 	struct btd_adapter *adapter = user_data;
@@ -10458,6 +10500,10 @@ static void read_info_complete(uint8_t status, uint16_t length,
 	if (btd_adapter_get_powered(adapter))
 		adapter_start(adapter);
 
+	// Some adapters do not want to accept this before being started/powered.
+	if (btd_opts.phys > 0)
+		set_phy_support(adapter, btd_opts.phys);
+
 	return;
 
 failed:
diff --git a/src/btd.h b/src/btd.h
index b7e7ebd61..2b84f7a51 100644
--- a/src/btd.h
+++ b/src/btd.h
@@ -151,6 +151,8 @@ struct btd_opts {
 	struct btd_advmon_opts	advmon;
 
 	struct btd_csis csis;
+
+	uint32_t	phys;
 };
 
 extern struct btd_opts btd_opts;
diff --git a/src/main.c b/src/main.c
index b1339c230..faedb853c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -128,6 +128,7 @@ static const char *le_options[] = {
 	"AdvMonAllowlistScanDuration",
 	"AdvMonNoFilterScanDuration",
 	"EnableAdvMonInterleaveScan",
+	"SupportedPHYs",
 	NULL
 };
 
@@ -182,10 +183,32 @@ static const struct group_table {
 	{ }
 };
 
+static const char *conf_phys_str[] = {
+	"BR1M1SLOT",
+	"BR1M3SLOT",
+	"BR1M5SLOT",
+	"EDR2M1SLOT",
+	"EDR2M3SLOT",
+	"EDR2M5SLOT",
+	"EDR3M1SLOT",
+	"EDR3M3SLOT",
+	"EDR3M5SLOT",
+	"LE1MTX",
+	"LE1MRX",
+	"LE2MTX",
+	"LE2MRX",
+	"LECODEDTX",
+	"LECODEDRX",
+};
+
 #ifndef MIN
 #define MIN(x, y) ((x) < (y) ? (x) : (y))
 #endif
 
+#ifndef NELEM
+#define NELEM(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
 static int8_t check_sirk_alpha_numeric(char *str)
 {
 	int8_t val = 0;
@@ -226,6 +249,36 @@ static size_t hex2bin(const char *hexstr, uint8_t *buf, size_t buflen)
 	return len;
 }
 
+static bool str2phy(const char *phy_str, uint32_t *phy_val)
+{
+	unsigned int i;
+
+	for (i = 0; i < NELEM(conf_phys_str); i++) {
+		if (strcasecmp(conf_phys_str[i], phy_str) == 0) {
+			*phy_val = (1 << i);
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static void btd_parse_phy_list(char **list)
+{
+	uint32_t phys = 0;
+
+	for (int i = 0; list[i]; i++) {
+		uint32_t phy_val;
+
+		info("Enabling PHY option: %s", list[i]);
+
+		if (str2phy(list[i], &phy_val))
+			phys |= phy_val;
+	}
+
+	btd_opts.phys = phys;
+}
+
 GKeyFile *btd_get_main_conf(void)
 {
 	return main_conf;
@@ -673,11 +726,24 @@ static void parse_le_config(GKeyFile *config)
 		  0,
 		  1},
 	};
+	char **strlist;
+	GError *err = NULL;
 
 	if (btd_opts.mode == BT_MODE_BREDR)
 		return;
 
 	parse_mode_config(config, "LE", params, ARRAY_SIZE(params));
+
+	strlist = g_key_file_get_string_list(config, "LE", "SupportedPHYs",
+						NULL, &err);
+	if (err) {
+		g_clear_error(&err);
+		strlist = g_new0(char *, 3);
+		strlist[0] = g_strdup("LE1MTX");
+		strlist[1] = g_strdup("LE1MRX");
+	}
+	btd_parse_phy_list(strlist);
+	g_strfreev(strlist);
 }
 
 static bool match_experimental(const void *data, const void *match_data)
diff --git a/src/main.conf b/src/main.conf
index 085c81a46..59d31e494 100644
--- a/src/main.conf
+++ b/src/main.conf
@@ -231,6 +231,11 @@
 # Defaults to 1
 #EnableAdvMonInterleaveScan=
 
+# Which Bluetooth LE PHYs should be enabled/supported?
+# Options are LE1MTX LE1MRX LE2MTX LE2MRX LECODEDTX LECODEDRX
+# Defaults to LE1MTX,LE1MRX
+#SupportedPHYs=LE1MTX,LE1MRX
+
 [GATT]
 # GATT attribute cache.
 # Possible values:

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH BlueZ 1/9] Enable alternate Bluetooth connection modes
@ 2024-01-24 23:43   ` Emil Velikov
  0 siblings, 0 replies; 28+ messages in thread
From: Emil Velikov @ 2024-01-24 23:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Vicki Pfau, Rachel Blackman

From: Vicki Pfau <vi@endrift.com>

This patch improves Bluetooth connectivity, especially with multiple
controllers and while docked.

Testing:
$ btmgmt
[mgmt]# phy

Verify the SupportedPHYs in main.conf are listed.
Verify that multiple controllers can connect and work well.

Co-Authored-By: Rachel Blackman <rachel.blackman@synapse.com>

[Emil Velikov]
Remove unused function, add default entries into parser, keep only
default entries in main.conf - commented out, like the other options.
---
 src/adapter.c | 46 +++++++++++++++++++++++++++++++++++++++++
 src/btd.h     |  2 ++
 src/main.c    | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/main.conf |  5 +++++
 4 files changed, 119 insertions(+)

diff --git a/src/adapter.c b/src/adapter.c
index 022390f0d..4c6b8f40f 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -86,6 +86,18 @@
 #define DISTANCE_VAL_INVALID	0x7FFF
 #define PATHLOSS_MAX		137
 
+#define LE_PHY_1M 0x01
+#define LE_PHY_2M 0x02
+#define LE_PHY_CODED 0x04
+
+#define PHYVAL_REQUIRED 0x07ff
+#define PHYVAL_1M_TX (1<<9)
+#define PHYVAL_1M_RX (1<<10)
+#define PHYVAL_2M_TX (1<<11)
+#define PHYVAL_2M_RX (1<<12)
+#define PHYVAL_CODED_TX (1<<13)
+#define PHYVAL_CODED_RX (1<<14)
+
 /*
  * These are known security keys that have been compromised.
  * If this grows or there are needs to be platform specific, it is
@@ -847,6 +859,36 @@ static bool set_discoverable(struct btd_adapter *adapter, uint8_t mode,
 	return false;
 }
 
+static void set_phy_support_complete(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	if (status != 0) {
+		struct btd_adapter *adapter = (struct btd_adapter *)user_data;
+
+		btd_error(adapter->dev_id, "PHY setting rejected for %u: %s",
+								adapter->dev_id, mgmt_errstr(status));
+	}
+}
+
+static bool set_phy_support(struct btd_adapter *adapter, uint32_t phy_mask)
+{
+	struct mgmt_cp_set_phy_confguration cp;
+
+	memset(&cp, 0, sizeof(cp));
+	cp.selected_phys = cpu_to_le32(phy_mask | PHYVAL_REQUIRED);
+
+	if (mgmt_send(adapter->mgmt, MGMT_OP_SET_PHY_CONFIGURATION,
+				adapter->dev_id, sizeof(cp), &cp,
+				set_phy_support_complete, (void*)adapter, NULL) > 0)
+		return true;
+
+	btd_error(adapter->dev_id, "Failed to set PHY for index %u",
+							adapter->dev_id);
+
+	return false;
+
+}
+
 static bool pairable_timeout_handler(gpointer user_data)
 {
 	struct btd_adapter *adapter = user_data;
@@ -10458,6 +10500,10 @@ static void read_info_complete(uint8_t status, uint16_t length,
 	if (btd_adapter_get_powered(adapter))
 		adapter_start(adapter);
 
+	// Some adapters do not want to accept this before being started/powered.
+	if (btd_opts.phys > 0)
+		set_phy_support(adapter, btd_opts.phys);
+
 	return;
 
 failed:
diff --git a/src/btd.h b/src/btd.h
index b7e7ebd61..2b84f7a51 100644
--- a/src/btd.h
+++ b/src/btd.h
@@ -151,6 +151,8 @@ struct btd_opts {
 	struct btd_advmon_opts	advmon;
 
 	struct btd_csis csis;
+
+	uint32_t	phys;
 };
 
 extern struct btd_opts btd_opts;
diff --git a/src/main.c b/src/main.c
index b1339c230..faedb853c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -128,6 +128,7 @@ static const char *le_options[] = {
 	"AdvMonAllowlistScanDuration",
 	"AdvMonNoFilterScanDuration",
 	"EnableAdvMonInterleaveScan",
+	"SupportedPHYs",
 	NULL
 };
 
@@ -182,10 +183,32 @@ static const struct group_table {
 	{ }
 };
 
+static const char *conf_phys_str[] = {
+	"BR1M1SLOT",
+	"BR1M3SLOT",
+	"BR1M5SLOT",
+	"EDR2M1SLOT",
+	"EDR2M3SLOT",
+	"EDR2M5SLOT",
+	"EDR3M1SLOT",
+	"EDR3M3SLOT",
+	"EDR3M5SLOT",
+	"LE1MTX",
+	"LE1MRX",
+	"LE2MTX",
+	"LE2MRX",
+	"LECODEDTX",
+	"LECODEDRX",
+};
+
 #ifndef MIN
 #define MIN(x, y) ((x) < (y) ? (x) : (y))
 #endif
 
+#ifndef NELEM
+#define NELEM(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
 static int8_t check_sirk_alpha_numeric(char *str)
 {
 	int8_t val = 0;
@@ -226,6 +249,36 @@ static size_t hex2bin(const char *hexstr, uint8_t *buf, size_t buflen)
 	return len;
 }
 
+static bool str2phy(const char *phy_str, uint32_t *phy_val)
+{
+	unsigned int i;
+
+	for (i = 0; i < NELEM(conf_phys_str); i++) {
+		if (strcasecmp(conf_phys_str[i], phy_str) == 0) {
+			*phy_val = (1 << i);
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static void btd_parse_phy_list(char **list)
+{
+	uint32_t phys = 0;
+
+	for (int i = 0; list[i]; i++) {
+		uint32_t phy_val;
+
+		info("Enabling PHY option: %s", list[i]);
+
+		if (str2phy(list[i], &phy_val))
+			phys |= phy_val;
+	}
+
+	btd_opts.phys = phys;
+}
+
 GKeyFile *btd_get_main_conf(void)
 {
 	return main_conf;
@@ -673,11 +726,24 @@ static void parse_le_config(GKeyFile *config)
 		  0,
 		  1},
 	};
+	char **strlist;
+	GError *err = NULL;
 
 	if (btd_opts.mode == BT_MODE_BREDR)
 		return;
 
 	parse_mode_config(config, "LE", params, ARRAY_SIZE(params));
+
+	strlist = g_key_file_get_string_list(config, "LE", "SupportedPHYs",
+						NULL, &err);
+	if (err) {
+		g_clear_error(&err);
+		strlist = g_new0(char *, 3);
+		strlist[0] = g_strdup("LE1MTX");
+		strlist[1] = g_strdup("LE1MRX");
+	}
+	btd_parse_phy_list(strlist);
+	g_strfreev(strlist);
 }
 
 static bool match_experimental(const void *data, const void *match_data)
diff --git a/src/main.conf b/src/main.conf
index 085c81a46..59d31e494 100644
--- a/src/main.conf
+++ b/src/main.conf
@@ -231,6 +231,11 @@
 # Defaults to 1
 #EnableAdvMonInterleaveScan=
 
+# Which Bluetooth LE PHYs should be enabled/supported?
+# Options are LE1MTX LE1MRX LE2MTX LE2MRX LECODEDTX LECODEDRX
+# Defaults to LE1MTX,LE1MRX
+#SupportedPHYs=LE1MTX,LE1MRX
+
 [GATT]
 # GATT attribute cache.
 # Possible values:

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH BlueZ 2/9] Return at least the title attribute from player_list_metadata()
  2024-01-24 23:43 ` Emil Velikov
@ 2024-01-24 23:43   ` Emil Velikov
  -1 siblings, 0 replies; 28+ messages in thread
From: Emil Velikov via B4 Relay @ 2024-01-24 23:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Sam Lantinga

From: Sam Lantinga <slouken@libsdl.org>

This fixes Bluetooth AVRCP certification test AVRCP/TG/MDI/BV-04-C,
which requires a valid response from the get_element_attributes command.
---
 profiles/audio/avrcp.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index 439fa27a9..36ce01a14 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -1210,6 +1210,10 @@ static GList *player_list_metadata(struct avrcp_player *player)
 					GUINT_TO_POINTER(str_to_metadata(key)));
 	}
 
+	if (attrs == NULL)
+		return g_list_prepend(NULL,
+				GUINT_TO_POINTER(AVRCP_MEDIA_ATTRIBUTE_TITLE));
+
 	return attrs;
 }
 

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH BlueZ 2/9] Return at least the title attribute from player_list_metadata()
@ 2024-01-24 23:43   ` Emil Velikov
  0 siblings, 0 replies; 28+ messages in thread
From: Emil Velikov @ 2024-01-24 23:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Sam Lantinga

From: Sam Lantinga <slouken@libsdl.org>

This fixes Bluetooth AVRCP certification test AVRCP/TG/MDI/BV-04-C,
which requires a valid response from the get_element_attributes command.
---
 profiles/audio/avrcp.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index 439fa27a9..36ce01a14 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -1210,6 +1210,10 @@ static GList *player_list_metadata(struct avrcp_player *player)
 					GUINT_TO_POINTER(str_to_metadata(key)));
 	}
 
+	if (attrs == NULL)
+		return g_list_prepend(NULL,
+				GUINT_TO_POINTER(AVRCP_MEDIA_ATTRIBUTE_TITLE));
+
 	return attrs;
 }
 

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH BlueZ 3/9] adapter: Remove experimental flag for PowerState
  2024-01-24 23:43 ` Emil Velikov
@ 2024-01-24 23:43   ` Emil Velikov
  -1 siblings, 0 replies; 28+ messages in thread
From: Emil Velikov via B4 Relay @ 2024-01-24 23:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Bastien Nocera

From: Bastien Nocera <hadess@hadess.net>

Now that the feature has been tested, that the API is deemed adequate
and the reliability sufficient.

[Emil Velikov]
The feature has landed in Sept 2022, with inclinations that "we might
switch it to stable in the next release", back in Nov 2022.

Today - a bit over 1 year later -  various distributions (Fedora, Gentoo
and by extension their derivatives) are carrying this patch. I think we
can say we're reasonably stable and can merge it upstream.
---
 src/adapter.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 4c6b8f40f..31ccaf54b 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3956,8 +3956,7 @@ static const GDBusPropertyTable adapter_properties[] = {
 	{ "Alias", "s", property_get_alias, property_set_alias },
 	{ "Class", "u", property_get_class },
 	{ "Powered", "b", property_get_powered, property_set_powered },
-	{ "PowerState", "s", property_get_power_state, NULL, NULL,
-			     G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{ "PowerState", "s", property_get_power_state },
 	{ "Discoverable", "b", property_get_discoverable,
 					property_set_discoverable },
 	{ "DiscoverableTimeout", "u", property_get_discoverable_timeout,

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH BlueZ 3/9] adapter: Remove experimental flag for PowerState
@ 2024-01-24 23:43   ` Emil Velikov
  0 siblings, 0 replies; 28+ messages in thread
From: Emil Velikov @ 2024-01-24 23:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Bastien Nocera

From: Bastien Nocera <hadess@hadess.net>

Now that the feature has been tested, that the API is deemed adequate
and the reliability sufficient.

[Emil Velikov]
The feature has landed in Sept 2022, with inclinations that "we might
switch it to stable in the next release", back in Nov 2022.

Today - a bit over 1 year later -  various distributions (Fedora, Gentoo
and by extension their derivatives) are carrying this patch. I think we
can say we're reasonably stable and can merge it upstream.
---
 src/adapter.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 4c6b8f40f..31ccaf54b 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3956,8 +3956,7 @@ static const GDBusPropertyTable adapter_properties[] = {
 	{ "Alias", "s", property_get_alias, property_set_alias },
 	{ "Class", "u", property_get_class },
 	{ "Powered", "b", property_get_powered, property_set_powered },
-	{ "PowerState", "s", property_get_power_state, NULL, NULL,
-			     G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{ "PowerState", "s", property_get_power_state },
 	{ "Discoverable", "b", property_get_discoverable,
 					property_set_discoverable },
 	{ "DiscoverableTimeout", "u", property_get_discoverable_timeout,

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH BlueZ 4/9] test: consistently use /usr/bin/env python3 shebang
  2024-01-24 23:43 ` Emil Velikov
@ 2024-01-24 23:43   ` Emil Velikov
  -1 siblings, 0 replies; 28+ messages in thread
From: Emil Velikov via B4 Relay @ 2024-01-24 23:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Emil Velikov, Nobuhiro Iwamatsu

From: Emil Velikov <emil.velikov@collabora.com>

Currently we have a mix of /usr/bin/python, /usr/bin/python3 and
/usr/bin/env python3. Use the latter since is the more common way of
handling this, plus it allows people to override the system python (for
what ever reason).

Inspired by a Debian patch, doing a mass /usr/bin/python{,3} conversion.

Cc: Nobuhiro Iwamatsu <iwamatsu@debian.org>
---
 test/agent.py                | 2 +-
 test/example-adv-monitor     | 2 +-
 test/example-advertisement   | 2 +-
 test/example-endpoint        | 2 +-
 test/example-player          | 2 +-
 test/exchange-business-cards | 2 +-
 test/ftp-client              | 2 +-
 test/get-managed-objects     | 2 +-
 test/get-obex-capabilities   | 2 +-
 test/list-devices            | 2 +-
 test/list-folders            | 2 +-
 test/map-client              | 2 +-
 test/monitor-bluetooth       | 2 +-
 test/opp-client              | 2 +-
 test/pbap-client             | 2 +-
 test/simple-agent            | 2 +-
 test/simple-endpoint         | 2 +-
 test/simple-obex-agent       | 2 +-
 test/simple-player           | 2 +-
 test/test-adapter            | 2 +-
 test/test-device             | 2 +-
 test/test-discovery          | 2 +-
 test/test-gatt-profile       | 2 +-
 test/test-health             | 2 +-
 test/test-health-sink        | 2 +-
 test/test-hfp                | 2 +-
 test/test-manager            | 2 +-
 test/test-nap                | 2 +-
 test/test-network            | 2 +-
 test/test-profile            | 2 +-
 test/test-sap-server         | 2 +-
 31 files changed, 31 insertions(+), 31 deletions(-)

diff --git a/test/agent.py b/test/agent.py
index 57a74183d..450fb20a3 100755
--- a/test/agent.py
+++ b/test/agent.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 import sys
diff --git a/test/example-adv-monitor b/test/example-adv-monitor
index a405fc7b0..09888a973 100644
--- a/test/example-adv-monitor
+++ b/test/example-adv-monitor
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 import argparse
diff --git a/test/example-advertisement b/test/example-advertisement
index 5f022ee67..910701220 100755
--- a/test/example-advertisement
+++ b/test/example-advertisement
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import print_function
diff --git a/test/example-endpoint b/test/example-endpoint
index 16651c683..cb5ac2ae9 100644
--- a/test/example-endpoint
+++ b/test/example-endpoint
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/example-player b/test/example-player
index 167460bad..9d56b4a13 100644
--- a/test/example-player
+++ b/test/example-player
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import print_function
diff --git a/test/exchange-business-cards b/test/exchange-business-cards
index 9a3aa29fb..12d513362 100755
--- a/test/exchange-business-cards
+++ b/test/exchange-business-cards
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 import sys
diff --git a/test/ftp-client b/test/ftp-client
index ef756ab2b..e37c027f4 100755
--- a/test/ftp-client
+++ b/test/ftp-client
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/get-managed-objects b/test/get-managed-objects
index 5125ee524..7ad359db4 100755
--- a/test/get-managed-objects
+++ b/test/get-managed-objects
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/get-obex-capabilities b/test/get-obex-capabilities
index a7980a442..25a996e18 100755
--- a/test/get-obex-capabilities
+++ b/test/get-obex-capabilities
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 import sys
diff --git a/test/list-devices b/test/list-devices
index 618d2867b..a24c31c7d 100755
--- a/test/list-devices
+++ b/test/list-devices
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/list-folders b/test/list-folders
index b4e3f100b..414bb367b 100755
--- a/test/list-folders
+++ b/test/list-folders
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 import sys
diff --git a/test/map-client b/test/map-client
index f44f512bd..b7369b068 100755
--- a/test/map-client
+++ b/test/map-client
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/monitor-bluetooth b/test/monitor-bluetooth
index 99f3c857c..347c91ac3 100755
--- a/test/monitor-bluetooth
+++ b/test/monitor-bluetooth
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/opp-client b/test/opp-client
index 4f00a41c0..deb02c77c 100755
--- a/test/opp-client
+++ b/test/opp-client
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/pbap-client b/test/pbap-client
index e6cafdd30..6dada4a11 100755
--- a/test/pbap-client
+++ b/test/pbap-client
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/simple-agent b/test/simple-agent
index 4fdaff1eb..09437eb22 100755
--- a/test/simple-agent
+++ b/test/simple-agent
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/simple-endpoint b/test/simple-endpoint
index 463f124d1..eace4286d 100755
--- a/test/simple-endpoint
+++ b/test/simple-endpoint
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/simple-obex-agent b/test/simple-obex-agent
index 064f6d30b..65807bff3 100755
--- a/test/simple-obex-agent
+++ b/test/simple-obex-agent
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/simple-player b/test/simple-player
index 7bad3d14f..190e047e2 100755
--- a/test/simple-player
+++ b/test/simple-player
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import print_function
diff --git a/test/test-adapter b/test/test-adapter
index c56ba9577..27aff27b5 100755
--- a/test/test-adapter
+++ b/test/test-adapter
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-device b/test/test-device
index c840f0565..8b1eb86d1 100755
--- a/test/test-device
+++ b/test/test-device
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-discovery b/test/test-discovery
index 54fc51403..6959e7be9 100755
--- a/test/test-discovery
+++ b/test/test-discovery
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-gatt-profile b/test/test-gatt-profile
index a973ae14e..64ff3e5f9 100755
--- a/test/test-gatt-profile
+++ b/test/test-gatt-profile
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-health b/test/test-health
index 3e16c415d..f26def906 100755
--- a/test/test-health
+++ b/test/test-health
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-health-sink b/test/test-health-sink
index 13b9a6b04..fcdc58e3d 100755
--- a/test/test-health-sink
+++ b/test/test-health-sink
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-hfp b/test/test-hfp
index 11e328e54..e1edac0aa 100755
--- a/test/test-hfp
+++ b/test/test-hfp
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-manager b/test/test-manager
index 3fa7205a0..a93819e27 100755
--- a/test/test-manager
+++ b/test/test-manager
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-nap b/test/test-nap
index d5c757b79..76cde74d4 100755
--- a/test/test-nap
+++ b/test/test-nap
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-network b/test/test-network
index acc7dff65..67be86106 100755
--- a/test/test-network
+++ b/test/test-network
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-profile b/test/test-profile
index af1e23f76..7d92f390e 100755
--- a/test/test-profile
+++ b/test/test-profile
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-sap-server b/test/test-sap-server
index ddb1efe9b..161a4bfec 100755
--- a/test/test-sap-server
+++ b/test/test-sap-server
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH BlueZ 4/9] test: consistently use /usr/bin/env python3 shebang
@ 2024-01-24 23:43   ` Emil Velikov
  0 siblings, 0 replies; 28+ messages in thread
From: Emil Velikov @ 2024-01-24 23:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Emil Velikov, Nobuhiro Iwamatsu

From: Emil Velikov <emil.velikov@collabora.com>

Currently we have a mix of /usr/bin/python, /usr/bin/python3 and
/usr/bin/env python3. Use the latter since is the more common way of
handling this, plus it allows people to override the system python (for
what ever reason).

Inspired by a Debian patch, doing a mass /usr/bin/python{,3} conversion.

Cc: Nobuhiro Iwamatsu <iwamatsu@debian.org>
---
 test/agent.py                | 2 +-
 test/example-adv-monitor     | 2 +-
 test/example-advertisement   | 2 +-
 test/example-endpoint        | 2 +-
 test/example-player          | 2 +-
 test/exchange-business-cards | 2 +-
 test/ftp-client              | 2 +-
 test/get-managed-objects     | 2 +-
 test/get-obex-capabilities   | 2 +-
 test/list-devices            | 2 +-
 test/list-folders            | 2 +-
 test/map-client              | 2 +-
 test/monitor-bluetooth       | 2 +-
 test/opp-client              | 2 +-
 test/pbap-client             | 2 +-
 test/simple-agent            | 2 +-
 test/simple-endpoint         | 2 +-
 test/simple-obex-agent       | 2 +-
 test/simple-player           | 2 +-
 test/test-adapter            | 2 +-
 test/test-device             | 2 +-
 test/test-discovery          | 2 +-
 test/test-gatt-profile       | 2 +-
 test/test-health             | 2 +-
 test/test-health-sink        | 2 +-
 test/test-hfp                | 2 +-
 test/test-manager            | 2 +-
 test/test-nap                | 2 +-
 test/test-network            | 2 +-
 test/test-profile            | 2 +-
 test/test-sap-server         | 2 +-
 31 files changed, 31 insertions(+), 31 deletions(-)

diff --git a/test/agent.py b/test/agent.py
index 57a74183d..450fb20a3 100755
--- a/test/agent.py
+++ b/test/agent.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 import sys
diff --git a/test/example-adv-monitor b/test/example-adv-monitor
index a405fc7b0..09888a973 100644
--- a/test/example-adv-monitor
+++ b/test/example-adv-monitor
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 import argparse
diff --git a/test/example-advertisement b/test/example-advertisement
index 5f022ee67..910701220 100755
--- a/test/example-advertisement
+++ b/test/example-advertisement
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import print_function
diff --git a/test/example-endpoint b/test/example-endpoint
index 16651c683..cb5ac2ae9 100644
--- a/test/example-endpoint
+++ b/test/example-endpoint
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/example-player b/test/example-player
index 167460bad..9d56b4a13 100644
--- a/test/example-player
+++ b/test/example-player
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import print_function
diff --git a/test/exchange-business-cards b/test/exchange-business-cards
index 9a3aa29fb..12d513362 100755
--- a/test/exchange-business-cards
+++ b/test/exchange-business-cards
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 import sys
diff --git a/test/ftp-client b/test/ftp-client
index ef756ab2b..e37c027f4 100755
--- a/test/ftp-client
+++ b/test/ftp-client
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/get-managed-objects b/test/get-managed-objects
index 5125ee524..7ad359db4 100755
--- a/test/get-managed-objects
+++ b/test/get-managed-objects
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/get-obex-capabilities b/test/get-obex-capabilities
index a7980a442..25a996e18 100755
--- a/test/get-obex-capabilities
+++ b/test/get-obex-capabilities
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 import sys
diff --git a/test/list-devices b/test/list-devices
index 618d2867b..a24c31c7d 100755
--- a/test/list-devices
+++ b/test/list-devices
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/list-folders b/test/list-folders
index b4e3f100b..414bb367b 100755
--- a/test/list-folders
+++ b/test/list-folders
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 import sys
diff --git a/test/map-client b/test/map-client
index f44f512bd..b7369b068 100755
--- a/test/map-client
+++ b/test/map-client
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/monitor-bluetooth b/test/monitor-bluetooth
index 99f3c857c..347c91ac3 100755
--- a/test/monitor-bluetooth
+++ b/test/monitor-bluetooth
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/opp-client b/test/opp-client
index 4f00a41c0..deb02c77c 100755
--- a/test/opp-client
+++ b/test/opp-client
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/pbap-client b/test/pbap-client
index e6cafdd30..6dada4a11 100755
--- a/test/pbap-client
+++ b/test/pbap-client
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/simple-agent b/test/simple-agent
index 4fdaff1eb..09437eb22 100755
--- a/test/simple-agent
+++ b/test/simple-agent
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/simple-endpoint b/test/simple-endpoint
index 463f124d1..eace4286d 100755
--- a/test/simple-endpoint
+++ b/test/simple-endpoint
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/simple-obex-agent b/test/simple-obex-agent
index 064f6d30b..65807bff3 100755
--- a/test/simple-obex-agent
+++ b/test/simple-obex-agent
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/simple-player b/test/simple-player
index 7bad3d14f..190e047e2 100755
--- a/test/simple-player
+++ b/test/simple-player
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import print_function
diff --git a/test/test-adapter b/test/test-adapter
index c56ba9577..27aff27b5 100755
--- a/test/test-adapter
+++ b/test/test-adapter
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-device b/test/test-device
index c840f0565..8b1eb86d1 100755
--- a/test/test-device
+++ b/test/test-device
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-discovery b/test/test-discovery
index 54fc51403..6959e7be9 100755
--- a/test/test-discovery
+++ b/test/test-discovery
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-gatt-profile b/test/test-gatt-profile
index a973ae14e..64ff3e5f9 100755
--- a/test/test-gatt-profile
+++ b/test/test-gatt-profile
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-health b/test/test-health
index 3e16c415d..f26def906 100755
--- a/test/test-health
+++ b/test/test-health
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-health-sink b/test/test-health-sink
index 13b9a6b04..fcdc58e3d 100755
--- a/test/test-health-sink
+++ b/test/test-health-sink
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-hfp b/test/test-hfp
index 11e328e54..e1edac0aa 100755
--- a/test/test-hfp
+++ b/test/test-hfp
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-manager b/test/test-manager
index 3fa7205a0..a93819e27 100755
--- a/test/test-manager
+++ b/test/test-manager
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-nap b/test/test-nap
index d5c757b79..76cde74d4 100755
--- a/test/test-nap
+++ b/test/test-nap
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-network b/test/test-network
index acc7dff65..67be86106 100755
--- a/test/test-network
+++ b/test/test-network
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-profile b/test/test-profile
index af1e23f76..7d92f390e 100755
--- a/test/test-profile
+++ b/test/test-profile
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-sap-server b/test/test-sap-server
index ddb1efe9b..161a4bfec 100755
--- a/test/test-sap-server
+++ b/test/test-sap-server
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 from __future__ import absolute_import, print_function, unicode_literals

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH BlueZ 5/9] profiles: remove unused suspend-dummy.c
  2024-01-24 23:43 ` Emil Velikov
@ 2024-01-24 23:43   ` Emil Velikov
  -1 siblings, 0 replies; 28+ messages in thread
From: Emil Velikov via B4 Relay @ 2024-01-24 23:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Emil Velikov, Nobuhiro Iwamatsu

From: Emil Velikov <emil.velikov@collabora.com>

The file has been used for about 8 years now - see commit fb55b7a6a
("profiles/hog: Use no suspend support instead of the dummy FIFO").

Inspired by a Debian patch by Nobuhiro Iwamatsu, which was changing the
/tmp/hogsuspend socket patch to /run. Looking through the codebase we
have a few more sockets that could use a to /run fix, but that will
follow-up at another day.

Cc: Nobuhiro Iwamatsu <iwamatsu@debian.org>
---
 Makefile.plugins               |   2 -
 profiles/input/suspend-dummy.c | 149 -----------------------------------------
 2 files changed, 151 deletions(-)

diff --git a/Makefile.plugins b/Makefile.plugins
index 5880ed0df..61a5cf687 100644
--- a/Makefile.plugins
+++ b/Makefile.plugins
@@ -74,8 +74,6 @@ builtin_sources += profiles/input/hog.c \
 			profiles/battery/bas.c profiles/battery/bas.h \
 			profiles/scanparam/scpp.c profiles/scanparam/scpp.h \
 			profiles/input/suspend.h profiles/input/suspend-none.c
-
-EXTRA_DIST += profiles/input/suspend-dummy.c
 endif
 
 if HEALTH
diff --git a/profiles/input/suspend-dummy.c b/profiles/input/suspend-dummy.c
deleted file mode 100644
index ea1835e0f..000000000
--- a/profiles/input/suspend-dummy.c
+++ /dev/null
@@ -1,149 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2012  Nordic Semiconductor Inc.
- *  Copyright (C) 2012  Instituto Nokia de Tecnologia - INdT
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include <glib.h>
-
-#include "src/log.h"
-#include "suspend.h"
-
-#define HOG_SUSPEND_FIFO	"/tmp/hogsuspend"
-
-static suspend_event suspend_cb = NULL;
-static resume_event resume_cb = NULL;
-static guint watch = 0;
-
-static int fifo_open(void);
-
-static gboolean read_fifo(GIOChannel *io, GIOCondition cond, gpointer user_data)
-{
-	char buffer[12];
-	gsize offset, left, bread;
-	GIOStatus iostatus;
-
-	if (cond & (G_IO_ERR | G_IO_HUP)) {
-		/*
-		 * Both ends needs to be open simultaneously before proceeding
-		 * any input or output operation. When the remote closes the
-		 * channel, hup signal is received on this end.
-		 */
-		fifo_open();
-		return FALSE;
-	}
-
-	offset = 0;
-	left = sizeof(buffer) - 1;
-	memset(buffer, 0, sizeof(buffer));
-
-	do {
-		iostatus = g_io_channel_read_chars(io, &buffer[offset], left,
-								&bread, NULL);
-
-		offset += bread;
-		left -= bread;
-		if (left == 0)
-			break;
-	} while (iostatus == G_IO_STATUS_NORMAL);
-
-	if (g_ascii_strncasecmp("suspend", buffer, 7) == 0)
-		suspend_cb();
-	else if (g_ascii_strncasecmp("resume", buffer, 6) == 0)
-		resume_cb();
-
-	return TRUE;
-}
-
-static int fifo_open(void)
-{
-	GIOCondition condition = G_IO_IN | G_IO_ERR | G_IO_HUP;
-	GIOChannel *fifoio;
-	int fd;
-
-	fd = open(HOG_SUSPEND_FIFO, O_RDONLY | O_NONBLOCK);
-	if (fd < 0) {
-		int err = -errno;
-		error("Can't open FIFO (%s): %s(%d)", HOG_SUSPEND_FIFO,
-							strerror(-err), -err);
-		return err;
-	}
-
-	fifoio = g_io_channel_unix_new(fd);
-	g_io_channel_set_close_on_unref(fifoio, TRUE);
-
-	watch = g_io_add_watch(fifoio, condition, read_fifo, NULL);
-
-	g_io_channel_unref(fifoio);
-
-	return 0;
-}
-
-int suspend_init(suspend_event suspend, resume_event resume)
-{
-	struct stat st;
-	int ret;
-
-	DBG("");
-
-	suspend_cb = suspend;
-	resume_cb = resume;
-
-	if (stat(HOG_SUSPEND_FIFO, &st) == 0) {
-		if (!S_ISFIFO(st.st_mode)) {
-			error("Unexpected non-FIFO %s file", HOG_SUSPEND_FIFO);
-			return -EIO;
-		}
-
-		if (unlink(HOG_SUSPEND_FIFO) < 0) {
-			int err = -errno;
-			error("Failed to remove FIFO (%s): %s (%d)",
-				HOG_SUSPEND_FIFO, strerror(-err), -err);
-			return err;
-		}
-	}
-
-	if (mkfifo(HOG_SUSPEND_FIFO, 0600) < 0) {
-		int err = -errno;
-
-		error("Can't create FIFO (%s): %s (%d)", HOG_SUSPEND_FIFO,
-							strerror(-err), -err);
-		return err;
-	}
-
-	DBG("Created suspend-dummy FIFO on %s", HOG_SUSPEND_FIFO);
-
-	ret = fifo_open();
-	if (ret < 0)
-		unlink(HOG_SUSPEND_FIFO);
-
-	return ret;
-}
-
-void suspend_exit(void)
-{
-	if (watch > 0) {
-		g_source_remove(watch);
-		watch = 0;
-	}
-
-	unlink(HOG_SUSPEND_FIFO);
-}

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH BlueZ 5/9] profiles: remove unused suspend-dummy.c
@ 2024-01-24 23:43   ` Emil Velikov
  0 siblings, 0 replies; 28+ messages in thread
From: Emil Velikov @ 2024-01-24 23:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Emil Velikov, Nobuhiro Iwamatsu

From: Emil Velikov <emil.velikov@collabora.com>

The file has been used for about 8 years now - see commit fb55b7a6a
("profiles/hog: Use no suspend support instead of the dummy FIFO").

Inspired by a Debian patch by Nobuhiro Iwamatsu, which was changing the
/tmp/hogsuspend socket patch to /run. Looking through the codebase we
have a few more sockets that could use a to /run fix, but that will
follow-up at another day.

Cc: Nobuhiro Iwamatsu <iwamatsu@debian.org>
---
 Makefile.plugins               |   2 -
 profiles/input/suspend-dummy.c | 149 -----------------------------------------
 2 files changed, 151 deletions(-)

diff --git a/Makefile.plugins b/Makefile.plugins
index 5880ed0df..61a5cf687 100644
--- a/Makefile.plugins
+++ b/Makefile.plugins
@@ -74,8 +74,6 @@ builtin_sources += profiles/input/hog.c \
 			profiles/battery/bas.c profiles/battery/bas.h \
 			profiles/scanparam/scpp.c profiles/scanparam/scpp.h \
 			profiles/input/suspend.h profiles/input/suspend-none.c
-
-EXTRA_DIST += profiles/input/suspend-dummy.c
 endif
 
 if HEALTH
diff --git a/profiles/input/suspend-dummy.c b/profiles/input/suspend-dummy.c
deleted file mode 100644
index ea1835e0f..000000000
--- a/profiles/input/suspend-dummy.c
+++ /dev/null
@@ -1,149 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2012  Nordic Semiconductor Inc.
- *  Copyright (C) 2012  Instituto Nokia de Tecnologia - INdT
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include <glib.h>
-
-#include "src/log.h"
-#include "suspend.h"
-
-#define HOG_SUSPEND_FIFO	"/tmp/hogsuspend"
-
-static suspend_event suspend_cb = NULL;
-static resume_event resume_cb = NULL;
-static guint watch = 0;
-
-static int fifo_open(void);
-
-static gboolean read_fifo(GIOChannel *io, GIOCondition cond, gpointer user_data)
-{
-	char buffer[12];
-	gsize offset, left, bread;
-	GIOStatus iostatus;
-
-	if (cond & (G_IO_ERR | G_IO_HUP)) {
-		/*
-		 * Both ends needs to be open simultaneously before proceeding
-		 * any input or output operation. When the remote closes the
-		 * channel, hup signal is received on this end.
-		 */
-		fifo_open();
-		return FALSE;
-	}
-
-	offset = 0;
-	left = sizeof(buffer) - 1;
-	memset(buffer, 0, sizeof(buffer));
-
-	do {
-		iostatus = g_io_channel_read_chars(io, &buffer[offset], left,
-								&bread, NULL);
-
-		offset += bread;
-		left -= bread;
-		if (left == 0)
-			break;
-	} while (iostatus == G_IO_STATUS_NORMAL);
-
-	if (g_ascii_strncasecmp("suspend", buffer, 7) == 0)
-		suspend_cb();
-	else if (g_ascii_strncasecmp("resume", buffer, 6) == 0)
-		resume_cb();
-
-	return TRUE;
-}
-
-static int fifo_open(void)
-{
-	GIOCondition condition = G_IO_IN | G_IO_ERR | G_IO_HUP;
-	GIOChannel *fifoio;
-	int fd;
-
-	fd = open(HOG_SUSPEND_FIFO, O_RDONLY | O_NONBLOCK);
-	if (fd < 0) {
-		int err = -errno;
-		error("Can't open FIFO (%s): %s(%d)", HOG_SUSPEND_FIFO,
-							strerror(-err), -err);
-		return err;
-	}
-
-	fifoio = g_io_channel_unix_new(fd);
-	g_io_channel_set_close_on_unref(fifoio, TRUE);
-
-	watch = g_io_add_watch(fifoio, condition, read_fifo, NULL);
-
-	g_io_channel_unref(fifoio);
-
-	return 0;
-}
-
-int suspend_init(suspend_event suspend, resume_event resume)
-{
-	struct stat st;
-	int ret;
-
-	DBG("");
-
-	suspend_cb = suspend;
-	resume_cb = resume;
-
-	if (stat(HOG_SUSPEND_FIFO, &st) == 0) {
-		if (!S_ISFIFO(st.st_mode)) {
-			error("Unexpected non-FIFO %s file", HOG_SUSPEND_FIFO);
-			return -EIO;
-		}
-
-		if (unlink(HOG_SUSPEND_FIFO) < 0) {
-			int err = -errno;
-			error("Failed to remove FIFO (%s): %s (%d)",
-				HOG_SUSPEND_FIFO, strerror(-err), -err);
-			return err;
-		}
-	}
-
-	if (mkfifo(HOG_SUSPEND_FIFO, 0600) < 0) {
-		int err = -errno;
-
-		error("Can't create FIFO (%s): %s (%d)", HOG_SUSPEND_FIFO,
-							strerror(-err), -err);
-		return err;
-	}
-
-	DBG("Created suspend-dummy FIFO on %s", HOG_SUSPEND_FIFO);
-
-	ret = fifo_open();
-	if (ret < 0)
-		unlink(HOG_SUSPEND_FIFO);
-
-	return ret;
-}
-
-void suspend_exit(void)
-{
-	if (watch > 0) {
-		g_source_remove(watch);
-		watch = 0;
-	}
-
-	unlink(HOG_SUSPEND_FIFO);
-}

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH BlueZ 6/9] obex: remove unused syncevolution plugin
  2024-01-24 23:43 ` Emil Velikov
@ 2024-01-24 23:44   ` Emil Velikov
  -1 siblings, 0 replies; 28+ messages in thread
From: Emil Velikov via B4 Relay @ 2024-01-24 23:44 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Emil Velikov

From: Emil Velikov <emil.velikov@collabora.com>

Based on my git log archaeology, the plugin was never built despite
receiving multiple updates across the years. It's possible that the git
history is lost when (if?) obexd code was imported.

The file isn't in the official tarball, so end users cannot enable if
even if they wanted to. So let's remove the dead/unused plugin.

There is some existing infra around OBEX_SYNCEVOLUTION which can be
checked/removed as follow-up.
---
 obexd/plugins/syncevolution.c | 470 ------------------------------------------
 1 file changed, 470 deletions(-)

diff --git a/obexd/plugins/syncevolution.c b/obexd/plugins/syncevolution.c
deleted file mode 100644
index ae3dc48c4..000000000
--- a/obexd/plugins/syncevolution.c
+++ /dev/null
@@ -1,470 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *
- *  OBEX Server
- *
- *  Copyright (C) 2007-2010  Intel Corporation
- *  Copyright (C) 2007-2010  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- */
-
-#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 "lib/bluetooth.h"
-
-#include "gdbus/gdbus.h"
-
-#include "btio/btio.h"
-#include "obexd/src/plugin.h"
-#include "obexd/src/obex.h"
-#include "obexd/src/service.h"
-#include "obexd/src/mimetype.h"
-#include "obexd/src/log.h"
-#include "obexd/src/manager.h"
-#include "obexd/src/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 const 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 const 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)

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH BlueZ 6/9] obex: remove unused syncevolution plugin
@ 2024-01-24 23:44   ` Emil Velikov
  0 siblings, 0 replies; 28+ messages in thread
From: Emil Velikov @ 2024-01-24 23:44 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Emil Velikov

From: Emil Velikov <emil.velikov@collabora.com>

Based on my git log archaeology, the plugin was never built despite
receiving multiple updates across the years. It's possible that the git
history is lost when (if?) obexd code was imported.

The file isn't in the official tarball, so end users cannot enable if
even if they wanted to. So let's remove the dead/unused plugin.

There is some existing infra around OBEX_SYNCEVOLUTION which can be
checked/removed as follow-up.
---
 obexd/plugins/syncevolution.c | 470 ------------------------------------------
 1 file changed, 470 deletions(-)

diff --git a/obexd/plugins/syncevolution.c b/obexd/plugins/syncevolution.c
deleted file mode 100644
index ae3dc48c4..000000000
--- a/obexd/plugins/syncevolution.c
+++ /dev/null
@@ -1,470 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *
- *  OBEX Server
- *
- *  Copyright (C) 2007-2010  Intel Corporation
- *  Copyright (C) 2007-2010  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- */
-
-#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 "lib/bluetooth.h"
-
-#include "gdbus/gdbus.h"
-
-#include "btio/btio.h"
-#include "obexd/src/plugin.h"
-#include "obexd/src/obex.h"
-#include "obexd/src/service.h"
-#include "obexd/src/mimetype.h"
-#include "obexd/src/log.h"
-#include "obexd/src/manager.h"
-#include "obexd/src/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 const 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 const 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)

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH BlueZ 7/9] obex: remove unused mas/messages-tracker impl
  2024-01-24 23:43 ` Emil Velikov
@ 2024-01-24 23:44   ` Emil Velikov
  -1 siblings, 0 replies; 28+ messages in thread
From: Emil Velikov via B4 Relay @ 2024-01-24 23:44 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Emil Velikov

From: Emil Velikov <emil.velikov@collabora.com>

Currently we have a "dummy" and a "tracker" implementation. The latter
was seemingly never wired into the build... Unless the git history was
rewritten and details were lost.

Remove the file - it's not shipped in the tarball, so even if anyone
want to use it they cannot.
---
 obexd/plugins/messages-tracker.c | 332 ---------------------------------------
 1 file changed, 332 deletions(-)

diff --git a/obexd/plugins/messages-tracker.c b/obexd/plugins/messages-tracker.c
deleted file mode 100644
index 4ce9f221d..000000000
--- a/obexd/plugins/messages-tracker.c
+++ /dev/null
@@ -1,332 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *
- *  OBEX Server
- *
- *  Copyright (C) 2010-2011  Nokia Corporation
- *
- *
- */
-
-#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)
-{
-}

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH BlueZ 7/9] obex: remove unused mas/messages-tracker impl
@ 2024-01-24 23:44   ` Emil Velikov
  0 siblings, 0 replies; 28+ messages in thread
From: Emil Velikov @ 2024-01-24 23:44 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Emil Velikov

From: Emil Velikov <emil.velikov@collabora.com>

Currently we have a "dummy" and a "tracker" implementation. The latter
was seemingly never wired into the build... Unless the git history was
rewritten and details were lost.

Remove the file - it's not shipped in the tarball, so even if anyone
want to use it they cannot.
---
 obexd/plugins/messages-tracker.c | 332 ---------------------------------------
 1 file changed, 332 deletions(-)

diff --git a/obexd/plugins/messages-tracker.c b/obexd/plugins/messages-tracker.c
deleted file mode 100644
index 4ce9f221d..000000000
--- a/obexd/plugins/messages-tracker.c
+++ /dev/null
@@ -1,332 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *
- *  OBEX Server
- *
- *  Copyright (C) 2010-2011  Nokia Corporation
- *
- *
- */
-
-#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)
-{
-}

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH BlueZ 8/9] obex: remove phonebook tracker backend
  2024-01-24 23:43 ` Emil Velikov
@ 2024-01-24 23:44   ` Emil Velikov
  -1 siblings, 0 replies; 28+ messages in thread
From: Emil Velikov via B4 Relay @ 2024-01-24 23:44 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Emil Velikov

From: Emil Velikov <emil.velikov@collabora.com>

Similar to the previous commits - the file was seemingly never build,
according to git log. Unlike the other cases, here the user can provide
the backend name via configure.ac toggle.

Although the case of tracker was never properly handled - no pkg-config
or probe based checks for includes, link library, etc.

Remove the file and enforce the two backend options - dummy and ebook.
---
 Makefile.obexd                    |    3 +-
 configure.ac                      |    6 +-
 obexd/plugins/phonebook-tracker.c | 1704 -------------------------------------
 3 files changed, 4 insertions(+), 1709 deletions(-)

diff --git a/Makefile.obexd b/Makefile.obexd
index 5d1a4ff65..d2aa06de3 100644
--- a/Makefile.obexd
+++ b/Makefile.obexd
@@ -42,8 +42,7 @@ obexd_builtin_sources += obexd/plugins/pbap.c \
 				obexd/plugins/vcard.h obexd/plugins/vcard.c \
 				obexd/plugins/phonebook.h \
 				obexd/plugins/phonebook-@PLUGIN_PHONEBOOK@.c
-EXTRA_DIST += obexd/plugins/phonebook-dummy.c obexd/plugins/phonebook-ebook.c \
-				obexd/plugins/phonebook-tracker.c
+EXTRA_DIST += obexd/plugins/phonebook-dummy.c obexd/plugins/phonebook-ebook.c
 
 obexd_builtin_modules += mas
 obexd_builtin_sources += obexd/plugins/mas.c obexd/src/map_ap.h \
diff --git a/configure.ac b/configure.ac
index cab5da581..e6daf00ac 100644
--- a/configure.ac
+++ b/configure.ac
@@ -433,11 +433,11 @@ AC_ARG_WITH([phonebook], AS_HELP_STRING([--with-phonebook=PLUGIN],
 			[plugin_phonebook=${withval}])
 if (test -z "${plugin_phonebook}"); then
 	plugin_phonebook=dummy
-fi
-
-if (test "${plugin_phonebook}" = "ebook"); then
+else if (test "${plugin_phonebook}" = "ebook"); then
 	PKG_CHECK_MODULES(LIBEBOOK, libebook-1.2 >= 3.3)
 	PKG_CHECK_MODULES(LIBEDATESERVER, libedataserver-1.2 >= 3.3)
+else
+	AC_MSG_ERROR([Unsupported phonebook backend ${plugin_phonebook}])
 fi
 AC_SUBST(PLUGIN_PHONEBOOK, [${plugin_phonebook}])
 
diff --git a/obexd/plugins/phonebook-tracker.c b/obexd/plugins/phonebook-tracker.c
deleted file mode 100644
index 71a91c1ea..000000000
--- a/obexd/plugins/phonebook-tracker.c
+++ /dev/null
@@ -1,1704 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *  Phonebook access through D-Bus vCard and call history service
- *
- *  Copyright (C) 2010  Nokia Corporation
- *
- *
- */
-
-#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 "obexd/src/log.h"
-#include "obexd/src/obex.h"
-#include "obexd/src/service.h"
-#include "obexd/src/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_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;
-}

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH BlueZ 8/9] obex: remove phonebook tracker backend
@ 2024-01-24 23:44   ` Emil Velikov
  0 siblings, 0 replies; 28+ messages in thread
From: Emil Velikov @ 2024-01-24 23:44 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Emil Velikov

From: Emil Velikov <emil.velikov@collabora.com>

Similar to the previous commits - the file was seemingly never build,
according to git log. Unlike the other cases, here the user can provide
the backend name via configure.ac toggle.

Although the case of tracker was never properly handled - no pkg-config
or probe based checks for includes, link library, etc.

Remove the file and enforce the two backend options - dummy and ebook.
---
 Makefile.obexd                    |    3 +-
 configure.ac                      |    6 +-
 obexd/plugins/phonebook-tracker.c | 1704 -------------------------------------
 3 files changed, 4 insertions(+), 1709 deletions(-)

diff --git a/Makefile.obexd b/Makefile.obexd
index 5d1a4ff65..d2aa06de3 100644
--- a/Makefile.obexd
+++ b/Makefile.obexd
@@ -42,8 +42,7 @@ obexd_builtin_sources += obexd/plugins/pbap.c \
 				obexd/plugins/vcard.h obexd/plugins/vcard.c \
 				obexd/plugins/phonebook.h \
 				obexd/plugins/phonebook-@PLUGIN_PHONEBOOK@.c
-EXTRA_DIST += obexd/plugins/phonebook-dummy.c obexd/plugins/phonebook-ebook.c \
-				obexd/plugins/phonebook-tracker.c
+EXTRA_DIST += obexd/plugins/phonebook-dummy.c obexd/plugins/phonebook-ebook.c
 
 obexd_builtin_modules += mas
 obexd_builtin_sources += obexd/plugins/mas.c obexd/src/map_ap.h \
diff --git a/configure.ac b/configure.ac
index cab5da581..e6daf00ac 100644
--- a/configure.ac
+++ b/configure.ac
@@ -433,11 +433,11 @@ AC_ARG_WITH([phonebook], AS_HELP_STRING([--with-phonebook=PLUGIN],
 			[plugin_phonebook=${withval}])
 if (test -z "${plugin_phonebook}"); then
 	plugin_phonebook=dummy
-fi
-
-if (test "${plugin_phonebook}" = "ebook"); then
+else if (test "${plugin_phonebook}" = "ebook"); then
 	PKG_CHECK_MODULES(LIBEBOOK, libebook-1.2 >= 3.3)
 	PKG_CHECK_MODULES(LIBEDATESERVER, libedataserver-1.2 >= 3.3)
+else
+	AC_MSG_ERROR([Unsupported phonebook backend ${plugin_phonebook}])
 fi
 AC_SUBST(PLUGIN_PHONEBOOK, [${plugin_phonebook}])
 
diff --git a/obexd/plugins/phonebook-tracker.c b/obexd/plugins/phonebook-tracker.c
deleted file mode 100644
index 71a91c1ea..000000000
--- a/obexd/plugins/phonebook-tracker.c
+++ /dev/null
@@ -1,1704 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *  Phonebook access through D-Bus vCard and call history service
- *
- *  Copyright (C) 2010  Nokia Corporation
- *
- *
- */
-
-#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 "obexd/src/log.h"
-#include "obexd/src/obex.h"
-#include "obexd/src/service.h"
-#include "obexd/src/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_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;
-}

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH BlueZ 9/9] build: ship all config files with --enable-datafiles
  2024-01-24 23:43 ` Emil Velikov
@ 2024-01-24 23:44   ` Emil Velikov
  -1 siblings, 0 replies; 28+ messages in thread
From: Emil Velikov via B4 Relay @ 2024-01-24 23:44 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Emil Velikov

From: Emil Velikov <emil.velikov@collabora.com>

Currently we ship only the dbus/systemd policy files and omit the other
four - /etc/bluetooth/{main,mesh-main,input,network}.conf.

Outside of those files, there is no documentation what the defaults are
and the other possible options. A number of distributions (Arch, Gentoo,
Fedora) have opted to manually copy those into the package. Alas this
does not scale and leaves other distros at disadvantage, in a sense.

Note: we need a custom install target to ensure confdir and statedir
have the correct permissions.
---
Some distributions do toggle some of the default values, by patching the
source tree. Future patches will add support for more maintainable
configuration handling akin to `man sysctl.d`.
---
 Makefile.am   | 8 +++++++-
 Makefile.mesh | 1 +
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/Makefile.am b/Makefile.am
index e738eb3a5..9c19cec49 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -31,11 +31,17 @@ AM_LDFLAGS = $(MISC_LDFLAGS)
 confdir = $(sysconfdir)/bluetooth
 statedir = $(localstatedir)/lib/bluetooth
 
+install-data-hook:
+	install -dm555 $(DESTDIR)$(confdir)
+	install -dm700 $(DESTDIR)$(statedir)
+
 if DATAFILES
 dbusdir = $(DBUS_CONFDIR)/dbus-1/system.d
 dbus_DATA = src/bluetooth.conf
 
-conf_DATA =
+conf_DATA = src/main.conf
+conf_DATA += profiles/input/input.conf
+conf_DATA += profiles/network/network.conf
 state_DATA =
 endif
 
diff --git a/Makefile.mesh b/Makefile.mesh
index 63f085de1..930262d53 100644
--- a/Makefile.mesh
+++ b/Makefile.mesh
@@ -3,6 +3,7 @@ if MESH
 
 if DATAFILES
 dbus_DATA += mesh/bluetooth-mesh.conf
+conf_DATA += mesh/mesh-main.conf
 endif
 
 if SYSTEMD

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH BlueZ 9/9] build: ship all config files with --enable-datafiles
@ 2024-01-24 23:44   ` Emil Velikov
  0 siblings, 0 replies; 28+ messages in thread
From: Emil Velikov @ 2024-01-24 23:44 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Emil Velikov

From: Emil Velikov <emil.velikov@collabora.com>

Currently we ship only the dbus/systemd policy files and omit the other
four - /etc/bluetooth/{main,mesh-main,input,network}.conf.

Outside of those files, there is no documentation what the defaults are
and the other possible options. A number of distributions (Arch, Gentoo,
Fedora) have opted to manually copy those into the package. Alas this
does not scale and leaves other distros at disadvantage, in a sense.

Note: we need a custom install target to ensure confdir and statedir
have the correct permissions.
---
Some distributions do toggle some of the default values, by patching the
source tree. Future patches will add support for more maintainable
configuration handling akin to `man sysctl.d`.
---
 Makefile.am   | 8 +++++++-
 Makefile.mesh | 1 +
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/Makefile.am b/Makefile.am
index e738eb3a5..9c19cec49 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -31,11 +31,17 @@ AM_LDFLAGS = $(MISC_LDFLAGS)
 confdir = $(sysconfdir)/bluetooth
 statedir = $(localstatedir)/lib/bluetooth
 
+install-data-hook:
+	install -dm555 $(DESTDIR)$(confdir)
+	install -dm700 $(DESTDIR)$(statedir)
+
 if DATAFILES
 dbusdir = $(DBUS_CONFDIR)/dbus-1/system.d
 dbus_DATA = src/bluetooth.conf
 
-conf_DATA =
+conf_DATA = src/main.conf
+conf_DATA += profiles/input/input.conf
+conf_DATA += profiles/network/network.conf
 state_DATA =
 endif
 
diff --git a/Makefile.mesh b/Makefile.mesh
index 63f085de1..930262d53 100644
--- a/Makefile.mesh
+++ b/Makefile.mesh
@@ -3,6 +3,7 @@ if MESH
 
 if DATAFILES
 dbus_DATA += mesh/bluetooth-mesh.conf
+conf_DATA += mesh/mesh-main.conf
 endif
 
 if SYSTEMD

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* RE: Distribution inspired fixes
  2024-01-24 23:43   ` Emil Velikov
  (?)
@ 2024-01-25  2:29   ` bluez.test.bot
  -1 siblings, 0 replies; 28+ messages in thread
From: bluez.test.bot @ 2024-01-25  2:29 UTC (permalink / raw)
  To: linux-bluetooth, devnull+emil.l.velikov.gmail.com

[-- Attachment #1: Type: text/plain, Size: 6145 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=819667

---Test result---

Test Summary:
CheckPatch                    FAIL      4.59 seconds
GitLint                       PASS      2.64 seconds
BuildEll                      PASS      24.25 seconds
BluezMake                     FAIL      4.89 seconds
MakeCheck                     FAIL      0.12 seconds
MakeDistcheck                 FAIL      4.40 seconds
CheckValgrind                 FAIL      4.38 seconds
CheckSmatch                   FAIL      4.52 seconds
bluezmakeextell               FAIL      4.42 seconds
IncrementalBuild              FAIL      4731.57 seconds
ScanBuild                     FAIL      480.27 seconds

Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[BlueZ,1/9] Enable alternate Bluetooth connection modes
WARNING:BAD_SIGN_OFF: Non-standard signature: Co-Authored-By:
#87: 
Co-Authored-By: Rachel Blackman <rachel.blackman@synapse.com>

WARNING:BAD_SIGN_OFF: 'Co-authored-by:' is the preferred signature form
#87: 
Co-Authored-By: Rachel Blackman <rachel.blackman@synapse.com>

WARNING:LONG_LINE: line length of 102 exceeds 80 columns
#133: FILE: src/adapter.c:869:
+								adapter->dev_id, mgmt_errstr(status));

WARNING:LONG_LINE: line length of 84 exceeds 80 columns
#146: FILE: src/adapter.c:882:
+				set_phy_support_complete, (void*)adapter, NULL) > 0)

ERROR:POINTER_LOCATION: "(foo*)" should be "(foo *)"
#146: FILE: src/adapter.c:882:
+				set_phy_support_complete, (void*)adapter, NULL) > 0)

WARNING:LONG_LINE_COMMENT: line length of 81 exceeds 80 columns
#163: FILE: src/adapter.c:10503:
+	// Some adapters do not want to accept this before being started/powered.

WARNING:STATIC_CONST_CHAR_ARRAY: static const char * array should probably be static const char * const
#199: FILE: src/main.c:186:
+static const char *conf_phys_str[] = {

/github/workspace/src/src/13529758.patch total: 1 errors, 6 warnings, 182 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/src/13529758.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


[BlueZ,5/9] profiles: remove unused suspend-dummy.c
WARNING:UNKNOWN_COMMIT_ID: Unknown commit id 'fb55b7a6a', maybe rebased or not pulled?
#77: 
The file has been used for about 8 years now - see commit fb55b7a6a

/github/workspace/src/src/13529762.patch total: 0 errors, 1 warnings, 8 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/src/13529762.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


##############################
Test: BluezMake - FAIL
Desc: Build BlueZ
Output:

configure.ac:21: installing './compile'
configure.ac:36: installing './config.guess'
configure.ac:36: installing './config.sub'
configure.ac:5: installing './install-sh'
configure.ac:5: installing './missing'
Makefile.am: installing './depcomp'
parallel-tests: installing './test-driver'
./configure: line 15145: syntax error: unexpected end of file
##############################
Test: MakeCheck - FAIL
Desc: Run Bluez Make Check
Output:

make: *** No rule to make target 'check'.  Stop.
##############################
Test: MakeDistcheck - FAIL
Desc: Run Bluez Make Distcheck
Output:

configure.ac:21: installing './compile'
configure.ac:5: installing './missing'
Makefile.am: installing './depcomp'
./configure: line 15145: syntax error: unexpected end of file
##############################
Test: CheckValgrind - FAIL
Desc: Run Bluez Make Check with Valgrind
Output:

configure.ac:21: installing './compile'
configure.ac:5: installing './missing'
Makefile.am: installing './depcomp'
./configure: line 15145: syntax error: unexpected end of file
##############################
Test: CheckSmatch - FAIL
Desc: Run smatch tool with source
Output:

configure.ac:21: installing './compile'
configure.ac:5: installing './missing'
Makefile.am: installing './depcomp'
./configure: line 15145: syntax error: unexpected end of file
##############################
Test: bluezmakeextell - FAIL
Desc: Build Bluez with External ELL
Output:

configure.ac:21: installing './compile'
configure.ac:5: installing './missing'
Makefile.am: installing './depcomp'
./configure: line 15145: syntax error: unexpected end of file
##############################
Test: IncrementalBuild - FAIL
Desc: Incremental build with the patches in the series
Output:
[BlueZ,8/9] obex: remove phonebook tracker backend

./configure: line 15145: syntax error: unexpected end of file
make: *** [Makefile:4713: config.status] Error 2
configure.ac:21: installing './compile'
configure.ac:5: installing './missing'
Makefile.am: installing './depcomp'
./configure: line 15145: syntax error: unexpected end of file
##############################
Test: ScanBuild - FAIL
Desc: Run Scan Build
Output:

configure.ac:21: installing './compile'
configure.ac:36: installing './config.guess'
configure.ac:36: installing './config.sub'
configure.ac:5: installing './install-sh'
configure.ac:5: installing './missing'
Makefile.am: installing './depcomp'
parallel-tests: installing './test-driver'
./configure: line 15145: syntax error: unexpected end of file


---
Regards,
Linux Bluetooth


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH BlueZ 1/9] Enable alternate Bluetooth connection modes
  2024-01-24 23:43   ` Emil Velikov
  (?)
  (?)
@ 2024-01-25  3:05   ` Vicki Pfau
  2024-01-25 13:41     ` Emil Velikov
  -1 siblings, 1 reply; 28+ messages in thread
From: Vicki Pfau @ 2024-01-25  3:05 UTC (permalink / raw)
  To: emil.l.velikov, linux-bluetooth; +Cc: Rachel Blackman

Hi Emil,

I didn't write this patch. It was written by Rachel Blackman, and I believe I just rebased it onto our local tree with the expectation that it was just our local tree. It would be better attributed to her, potentially with a Co-Authored-By for me.

Vicki

On 1/24/24 15:43, Emil Velikov via B4 Relay wrote:
> From: Vicki Pfau <vi@endrift.com>
> 
> This patch improves Bluetooth connectivity, especially with multiple
> controllers and while docked.
> 
> Testing:
> $ btmgmt
> [mgmt]# phy
> 
> Verify the SupportedPHYs in main.conf are listed.
> Verify that multiple controllers can connect and work well.
> 
> Co-Authored-By: Rachel Blackman <rachel.blackman@synapse.com>
> 
> [Emil Velikov]
> Remove unused function, add default entries into parser, keep only
> default entries in main.conf - commented out, like the other options.
> ---
>  src/adapter.c | 46 +++++++++++++++++++++++++++++++++++++++++
>  src/btd.h     |  2 ++
>  src/main.c    | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  src/main.conf |  5 +++++
>  4 files changed, 119 insertions(+)
> 
> diff --git a/src/adapter.c b/src/adapter.c
> index 022390f0d..4c6b8f40f 100644
> --- a/src/adapter.c
> +++ b/src/adapter.c
> @@ -86,6 +86,18 @@
>  #define DISTANCE_VAL_INVALID	0x7FFF
>  #define PATHLOSS_MAX		137
>  
> +#define LE_PHY_1M 0x01
> +#define LE_PHY_2M 0x02
> +#define LE_PHY_CODED 0x04
> +
> +#define PHYVAL_REQUIRED 0x07ff
> +#define PHYVAL_1M_TX (1<<9)
> +#define PHYVAL_1M_RX (1<<10)
> +#define PHYVAL_2M_TX (1<<11)
> +#define PHYVAL_2M_RX (1<<12)
> +#define PHYVAL_CODED_TX (1<<13)
> +#define PHYVAL_CODED_RX (1<<14)
> +
>  /*
>   * These are known security keys that have been compromised.
>   * If this grows or there are needs to be platform specific, it is
> @@ -847,6 +859,36 @@ static bool set_discoverable(struct btd_adapter *adapter, uint8_t mode,
>  	return false;
>  }
>  
> +static void set_phy_support_complete(uint8_t status, uint16_t length,
> +					const void *param, void *user_data)
> +{
> +	if (status != 0) {
> +		struct btd_adapter *adapter = (struct btd_adapter *)user_data;
> +
> +		btd_error(adapter->dev_id, "PHY setting rejected for %u: %s",
> +								adapter->dev_id, mgmt_errstr(status));
> +	}
> +}
> +
> +static bool set_phy_support(struct btd_adapter *adapter, uint32_t phy_mask)
> +{
> +	struct mgmt_cp_set_phy_confguration cp;
> +
> +	memset(&cp, 0, sizeof(cp));
> +	cp.selected_phys = cpu_to_le32(phy_mask | PHYVAL_REQUIRED);
> +
> +	if (mgmt_send(adapter->mgmt, MGMT_OP_SET_PHY_CONFIGURATION,
> +				adapter->dev_id, sizeof(cp), &cp,
> +				set_phy_support_complete, (void*)adapter, NULL) > 0)
> +		return true;
> +
> +	btd_error(adapter->dev_id, "Failed to set PHY for index %u",
> +							adapter->dev_id);
> +
> +	return false;
> +
> +}
> +
>  static bool pairable_timeout_handler(gpointer user_data)
>  {
>  	struct btd_adapter *adapter = user_data;
> @@ -10458,6 +10500,10 @@ static void read_info_complete(uint8_t status, uint16_t length,
>  	if (btd_adapter_get_powered(adapter))
>  		adapter_start(adapter);
>  
> +	// Some adapters do not want to accept this before being started/powered.
> +	if (btd_opts.phys > 0)
> +		set_phy_support(adapter, btd_opts.phys);
> +
>  	return;
>  
>  failed:
> diff --git a/src/btd.h b/src/btd.h
> index b7e7ebd61..2b84f7a51 100644
> --- a/src/btd.h
> +++ b/src/btd.h
> @@ -151,6 +151,8 @@ struct btd_opts {
>  	struct btd_advmon_opts	advmon;
>  
>  	struct btd_csis csis;
> +
> +	uint32_t	phys;
>  };
>  
>  extern struct btd_opts btd_opts;
> diff --git a/src/main.c b/src/main.c
> index b1339c230..faedb853c 100644
> --- a/src/main.c
> +++ b/src/main.c
> @@ -128,6 +128,7 @@ static const char *le_options[] = {
>  	"AdvMonAllowlistScanDuration",
>  	"AdvMonNoFilterScanDuration",
>  	"EnableAdvMonInterleaveScan",
> +	"SupportedPHYs",
>  	NULL
>  };
>  
> @@ -182,10 +183,32 @@ static const struct group_table {
>  	{ }
>  };
>  
> +static const char *conf_phys_str[] = {
> +	"BR1M1SLOT",
> +	"BR1M3SLOT",
> +	"BR1M5SLOT",
> +	"EDR2M1SLOT",
> +	"EDR2M3SLOT",
> +	"EDR2M5SLOT",
> +	"EDR3M1SLOT",
> +	"EDR3M3SLOT",
> +	"EDR3M5SLOT",
> +	"LE1MTX",
> +	"LE1MRX",
> +	"LE2MTX",
> +	"LE2MRX",
> +	"LECODEDTX",
> +	"LECODEDRX",
> +};
> +
>  #ifndef MIN
>  #define MIN(x, y) ((x) < (y) ? (x) : (y))
>  #endif
>  
> +#ifndef NELEM
> +#define NELEM(x) (sizeof(x) / sizeof((x)[0]))
> +#endif
> +
>  static int8_t check_sirk_alpha_numeric(char *str)
>  {
>  	int8_t val = 0;
> @@ -226,6 +249,36 @@ static size_t hex2bin(const char *hexstr, uint8_t *buf, size_t buflen)
>  	return len;
>  }
>  
> +static bool str2phy(const char *phy_str, uint32_t *phy_val)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < NELEM(conf_phys_str); i++) {
> +		if (strcasecmp(conf_phys_str[i], phy_str) == 0) {
> +			*phy_val = (1 << i);
> +			return true;
> +		}
> +	}
> +
> +	return false;
> +}
> +
> +static void btd_parse_phy_list(char **list)
> +{
> +	uint32_t phys = 0;
> +
> +	for (int i = 0; list[i]; i++) {
> +		uint32_t phy_val;
> +
> +		info("Enabling PHY option: %s", list[i]);
> +
> +		if (str2phy(list[i], &phy_val))
> +			phys |= phy_val;
> +	}
> +
> +	btd_opts.phys = phys;
> +}
> +
>  GKeyFile *btd_get_main_conf(void)
>  {
>  	return main_conf;
> @@ -673,11 +726,24 @@ static void parse_le_config(GKeyFile *config)
>  		  0,
>  		  1},
>  	};
> +	char **strlist;
> +	GError *err = NULL;
>  
>  	if (btd_opts.mode == BT_MODE_BREDR)
>  		return;
>  
>  	parse_mode_config(config, "LE", params, ARRAY_SIZE(params));
> +
> +	strlist = g_key_file_get_string_list(config, "LE", "SupportedPHYs",
> +						NULL, &err);
> +	if (err) {
> +		g_clear_error(&err);
> +		strlist = g_new0(char *, 3);
> +		strlist[0] = g_strdup("LE1MTX");
> +		strlist[1] = g_strdup("LE1MRX");
> +	}
> +	btd_parse_phy_list(strlist);
> +	g_strfreev(strlist);
>  }
>  
>  static bool match_experimental(const void *data, const void *match_data)
> diff --git a/src/main.conf b/src/main.conf
> index 085c81a46..59d31e494 100644
> --- a/src/main.conf
> +++ b/src/main.conf
> @@ -231,6 +231,11 @@
>  # Defaults to 1
>  #EnableAdvMonInterleaveScan=
>  
> +# Which Bluetooth LE PHYs should be enabled/supported?
> +# Options are LE1MTX LE1MRX LE2MTX LE2MRX LECODEDTX LECODEDRX
> +# Defaults to LE1MTX,LE1MRX
> +#SupportedPHYs=LE1MTX,LE1MRX
> +
>  [GATT]
>  # GATT attribute cache.
>  # Possible values:
> 

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH BlueZ 1/9] Enable alternate Bluetooth connection modes
  2024-01-24 23:43   ` Emil Velikov
                     ` (2 preceding siblings ...)
  (?)
@ 2024-01-25  3:54   ` Luiz Augusto von Dentz
  2024-01-25 13:39     ` Emil Velikov
  -1 siblings, 1 reply; 28+ messages in thread
From: Luiz Augusto von Dentz @ 2024-01-25  3:54 UTC (permalink / raw)
  To: emil.l.velikov; +Cc: linux-bluetooth, Vicki Pfau, Rachel Blackman

Hi Emil,

On Wed, Jan 24, 2024 at 6:46 PM Emil Velikov via B4 Relay
<devnull+emil.l.velikov.gmail.com@kernel.org> wrote:
>
> From: Vicki Pfau <vi@endrift.com>
>
> This patch improves Bluetooth connectivity, especially with multiple
> controllers and while docked.
>
> Testing:
> $ btmgmt
> [mgmt]# phy
>
> Verify the SupportedPHYs in main.conf are listed.
> Verify that multiple controllers can connect and work well.
>
> Co-Authored-By: Rachel Blackman <rachel.blackman@synapse.com>
>
> [Emil Velikov]
> Remove unused function, add default entries into parser, keep only
> default entries in main.conf - commented out, like the other options.
> ---
>  src/adapter.c | 46 +++++++++++++++++++++++++++++++++++++++++
>  src/btd.h     |  2 ++
>  src/main.c    | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  src/main.conf |  5 +++++
>  4 files changed, 119 insertions(+)
>
> diff --git a/src/adapter.c b/src/adapter.c
> index 022390f0d..4c6b8f40f 100644
> --- a/src/adapter.c
> +++ b/src/adapter.c
> @@ -86,6 +86,18 @@
>  #define DISTANCE_VAL_INVALID   0x7FFF
>  #define PATHLOSS_MAX           137
>
> +#define LE_PHY_1M 0x01
> +#define LE_PHY_2M 0x02
> +#define LE_PHY_CODED 0x04
> +
> +#define PHYVAL_REQUIRED 0x07ff
> +#define PHYVAL_1M_TX (1<<9)
> +#define PHYVAL_1M_RX (1<<10)
> +#define PHYVAL_2M_TX (1<<11)
> +#define PHYVAL_2M_RX (1<<12)
> +#define PHYVAL_CODED_TX (1<<13)
> +#define PHYVAL_CODED_RX (1<<14)
> +
>  /*
>   * These are known security keys that have been compromised.
>   * If this grows or there are needs to be platform specific, it is
> @@ -847,6 +859,36 @@ static bool set_discoverable(struct btd_adapter *adapter, uint8_t mode,
>         return false;
>  }
>
> +static void set_phy_support_complete(uint8_t status, uint16_t length,
> +                                       const void *param, void *user_data)
> +{
> +       if (status != 0) {
> +               struct btd_adapter *adapter = (struct btd_adapter *)user_data;
> +
> +               btd_error(adapter->dev_id, "PHY setting rejected for %u: %s",
> +                                                               adapter->dev_id, mgmt_errstr(status));
> +       }
> +}
> +
> +static bool set_phy_support(struct btd_adapter *adapter, uint32_t phy_mask)
> +{
> +       struct mgmt_cp_set_phy_confguration cp;
> +
> +       memset(&cp, 0, sizeof(cp));
> +       cp.selected_phys = cpu_to_le32(phy_mask | PHYVAL_REQUIRED);
> +
> +       if (mgmt_send(adapter->mgmt, MGMT_OP_SET_PHY_CONFIGURATION,
> +                               adapter->dev_id, sizeof(cp), &cp,
> +                               set_phy_support_complete, (void*)adapter, NULL) > 0)
> +               return true;
> +
> +       btd_error(adapter->dev_id, "Failed to set PHY for index %u",
> +                                                       adapter->dev_id);
> +
> +       return false;
> +
> +}
> +
>  static bool pairable_timeout_handler(gpointer user_data)
>  {
>         struct btd_adapter *adapter = user_data;
> @@ -10458,6 +10500,10 @@ static void read_info_complete(uint8_t status, uint16_t length,
>         if (btd_adapter_get_powered(adapter))
>                 adapter_start(adapter);
>
> +       // Some adapters do not want to accept this before being started/powered.
> +       if (btd_opts.phys > 0)
> +               set_phy_support(adapter, btd_opts.phys);
> +
>         return;
>
>  failed:
> diff --git a/src/btd.h b/src/btd.h
> index b7e7ebd61..2b84f7a51 100644
> --- a/src/btd.h
> +++ b/src/btd.h
> @@ -151,6 +151,8 @@ struct btd_opts {
>         struct btd_advmon_opts  advmon;
>
>         struct btd_csis csis;
> +
> +       uint32_t        phys;
>  };
>
>  extern struct btd_opts btd_opts;
> diff --git a/src/main.c b/src/main.c
> index b1339c230..faedb853c 100644
> --- a/src/main.c
> +++ b/src/main.c
> @@ -128,6 +128,7 @@ static const char *le_options[] = {
>         "AdvMonAllowlistScanDuration",
>         "AdvMonNoFilterScanDuration",
>         "EnableAdvMonInterleaveScan",
> +       "SupportedPHYs",
>         NULL
>  };
>
> @@ -182,10 +183,32 @@ static const struct group_table {
>         { }
>  };
>
> +static const char *conf_phys_str[] = {
> +       "BR1M1SLOT",
> +       "BR1M3SLOT",
> +       "BR1M5SLOT",
> +       "EDR2M1SLOT",
> +       "EDR2M3SLOT",
> +       "EDR2M5SLOT",
> +       "EDR3M1SLOT",
> +       "EDR3M3SLOT",
> +       "EDR3M5SLOT",
> +       "LE1MTX",
> +       "LE1MRX",
> +       "LE2MTX",
> +       "LE2MRX",
> +       "LECODEDTX",
> +       "LECODEDRX",
> +};
> +
>  #ifndef MIN
>  #define MIN(x, y) ((x) < (y) ? (x) : (y))
>  #endif
>
> +#ifndef NELEM
> +#define NELEM(x) (sizeof(x) / sizeof((x)[0]))
> +#endif
> +
>  static int8_t check_sirk_alpha_numeric(char *str)
>  {
>         int8_t val = 0;
> @@ -226,6 +249,36 @@ static size_t hex2bin(const char *hexstr, uint8_t *buf, size_t buflen)
>         return len;
>  }
>
> +static bool str2phy(const char *phy_str, uint32_t *phy_val)
> +{
> +       unsigned int i;
> +
> +       for (i = 0; i < NELEM(conf_phys_str); i++) {
> +               if (strcasecmp(conf_phys_str[i], phy_str) == 0) {
> +                       *phy_val = (1 << i);
> +                       return true;
> +               }
> +       }
> +
> +       return false;
> +}
> +
> +static void btd_parse_phy_list(char **list)
> +{
> +       uint32_t phys = 0;
> +
> +       for (int i = 0; list[i]; i++) {
> +               uint32_t phy_val;
> +
> +               info("Enabling PHY option: %s", list[i]);
> +
> +               if (str2phy(list[i], &phy_val))
> +                       phys |= phy_val;
> +       }
> +
> +       btd_opts.phys = phys;
> +}
> +
>  GKeyFile *btd_get_main_conf(void)
>  {
>         return main_conf;
> @@ -673,11 +726,24 @@ static void parse_le_config(GKeyFile *config)
>                   0,
>                   1},
>         };
> +       char **strlist;
> +       GError *err = NULL;
>
>         if (btd_opts.mode == BT_MODE_BREDR)
>                 return;
>
>         parse_mode_config(config, "LE", params, ARRAY_SIZE(params));
> +
> +       strlist = g_key_file_get_string_list(config, "LE", "SupportedPHYs",
> +                                               NULL, &err);
> +       if (err) {
> +               g_clear_error(&err);
> +               strlist = g_new0(char *, 3);
> +               strlist[0] = g_strdup("LE1MTX");
> +               strlist[1] = g_strdup("LE1MRX");
> +       }
> +       btd_parse_phy_list(strlist);
> +       g_strfreev(strlist);
>  }
>
>  static bool match_experimental(const void *data, const void *match_data)
> diff --git a/src/main.conf b/src/main.conf
> index 085c81a46..59d31e494 100644
> --- a/src/main.conf
> +++ b/src/main.conf
> @@ -231,6 +231,11 @@
>  # Defaults to 1
>  #EnableAdvMonInterleaveScan=
>
> +# Which Bluetooth LE PHYs should be enabled/supported?
> +# Options are LE1MTX LE1MRX LE2MTX LE2MRX LECODEDTX LECODEDRX
> +# Defaults to LE1MTX,LE1MRX
> +#SupportedPHYs=LE1MTX,LE1MRX

I'm sort of surprised by this, we do only use the PHYs listed as
supported by the controller, so is there a bug or is this really a way
to disable PHYs that the controllers report as supported but in
reality don't really work properly? In case of the latter I think we
would be better off having a quirk added in the kernel so it can be
marked to the controllers we know misbehaves rather than limiting all
controllers to 1M PHY by default.

>  [GATT]
>  # GATT attribute cache.
>  # Possible values:
>
> --
> 2.43.0
>
>


-- 
Luiz Augusto von Dentz

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH BlueZ 1/9] Enable alternate Bluetooth connection modes
  2024-01-25  3:54   ` Luiz Augusto von Dentz
@ 2024-01-25 13:39     ` Emil Velikov
  2024-01-25 14:59       ` Luiz Augusto von Dentz
  0 siblings, 1 reply; 28+ messages in thread
From: Emil Velikov @ 2024-01-25 13:39 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth, Vicki Pfau, Rachel Blackman

Hi Luiz,

On Thu, 25 Jan 2024 at 03:54, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
>
> Hi Emil,
>

>
> I'm sort of surprised by this, we do only use the PHYs listed as
> supported by the controller, so is there a bug or is this really a way
> to disable PHYs that the controllers report as supported but in
> reality don't really work properly? In case of the latter I think we
> would be better off having a quirk added in the kernel so it can be
> marked to the controllers we know misbehaves rather than limiting all
> controllers to 1M PHY by default.
>

Using pristine bluez, bluetoothctl/mgmt/phy lists (omitting the slot phys):

Supported phys:     LE1MTX LE1MRX LE2MTX LE2MRX LECODEDTX LECODEDRX
Configurable phys:                LE2MTX LE2MRX LECODEDTX LECODEDRX
Selected phys:      LE1MTX LE1MRX

With this patch + the LE/SupportedPHY config set to "LE1MTX LE1MRX
LE2MTX LE2MRX LECODEDTX LECODEDRX", as per the original patch we get.
Note: I've intentionally dropped the override for submission, happy to
bring it back if you prefer.

Supported phys:     LE1MTX LE1MRX LE2MTX LE2MRX LECODEDTX LECODEDRX
Configurable phys:                LE2MTX LE2MRX LECODEDTX LECODEDRX
Selected phys:      LE1MTX LE1MRX LE2MTX LE2MRX LECODEDTX LECODEDRX

Note: I've intentionally dropped the override for upstreaming, happy
to bring it back if you prefer.

So from what I can tell, the controller reports that all (as far as
we're concerned) PHYs are supported. Yet the selected and configurable
PHYs are mutually exclusive, which doesn't quite compute here.
Mind you, my bluetooth knowledge is a bit limited - I'm just going by the code.

What would you say is the best way to move forward with this? It
doesn't seem like a kernel quirk is needed IMHO.
Generally, if you feel that a different name and/or semantics for the
toggle would help, I'm all ears.

Thanks in advance,
Emil

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH BlueZ 1/9] Enable alternate Bluetooth connection modes
  2024-01-25  3:05   ` [PATCH BlueZ 1/9] Enable alternate Bluetooth connection modes Vicki Pfau
@ 2024-01-25 13:41     ` Emil Velikov
  0 siblings, 0 replies; 28+ messages in thread
From: Emil Velikov @ 2024-01-25 13:41 UTC (permalink / raw)
  To: Vicki Pfau; +Cc: linux-bluetooth, Rachel Blackman

Hi Vicki,

On Thu, 25 Jan 2024 at 03:05, Vicki Pfau <vi@endrift.com> wrote:
>
> Hi Emil,
>
> I didn't write this patch. It was written by Rachel Blackman, and I believe I just rebased it onto our local tree with the expectation that it was just our local tree. It would be better attributed to her, potentially with a Co-Authored-By for me.
>

Sure can do that. I've intentionally tried to preserve authorship,
which seemed to have backfired in this case :-)

-Emil

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH BlueZ 1/9] Enable alternate Bluetooth connection modes
  2024-01-25 13:39     ` Emil Velikov
@ 2024-01-25 14:59       ` Luiz Augusto von Dentz
  2024-01-25 16:32         ` Emil Velikov
  0 siblings, 1 reply; 28+ messages in thread
From: Luiz Augusto von Dentz @ 2024-01-25 14:59 UTC (permalink / raw)
  To: Emil Velikov; +Cc: linux-bluetooth, Vicki Pfau, Rachel Blackman

Hi Emil,

On Thu, Jan 25, 2024 at 8:39 AM Emil Velikov <emil.l.velikov@gmail.com> wrote:
>
> Hi Luiz,
>
> On Thu, 25 Jan 2024 at 03:54, Luiz Augusto von Dentz
> <luiz.dentz@gmail.com> wrote:
> >
> > Hi Emil,
> >
>
> >
> > I'm sort of surprised by this, we do only use the PHYs listed as
> > supported by the controller, so is there a bug or is this really a way
> > to disable PHYs that the controllers report as supported but in
> > reality don't really work properly? In case of the latter I think we
> > would be better off having a quirk added in the kernel so it can be
> > marked to the controllers we know misbehaves rather than limiting all
> > controllers to 1M PHY by default.
> >
>
> Using pristine bluez, bluetoothctl/mgmt/phy lists (omitting the slot phys):
>
> Supported phys:     LE1MTX LE1MRX LE2MTX LE2MRX LECODEDTX LECODEDRX
> Configurable phys:                LE2MTX LE2MRX LECODEDTX LECODEDRX
> Selected phys:      LE1MTX LE1MRX
>
> With this patch + the LE/SupportedPHY config set to "LE1MTX LE1MRX
> LE2MTX LE2MRX LECODEDTX LECODEDRX", as per the original patch we get.
> Note: I've intentionally dropped the override for submission, happy to
> bring it back if you prefer.
>
> Supported phys:     LE1MTX LE1MRX LE2MTX LE2MRX LECODEDTX LECODEDRX
> Configurable phys:                LE2MTX LE2MRX LECODEDTX LECODEDRX
> Selected phys:      LE1MTX LE1MRX LE2MTX LE2MRX LECODEDTX LECODEDRX
>
> Note: I've intentionally dropped the override for upstreaming, happy
> to bring it back if you prefer.
>
> So from what I can tell, the controller reports that all (as far as
> we're concerned) PHYs are supported. Yet the selected and configurable
> PHYs are mutually exclusive, which doesn't quite compute here.
> Mind you, my bluetooth knowledge is a bit limited - I'm just going by the code.
>
> What would you say is the best way to move forward with this? It
> doesn't seem like a kernel quirk is needed IMHO.
> Generally, if you feel that a different name and/or semantics for the
> toggle would help, I'm all ears.

Hmm, are you sure you are not missing something like:

commit 288c90224eec55d13e786844b7954ef060752089
Author: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Date:   Mon Dec 19 13:37:02 2022 -0800

    Bluetooth: Enable all supported LE PHY by default

    This enables 2M and Coded PHY by default if they are marked as supported
    in the LE features bits.

    Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

Later one we had to introduce HCI_QUIRK_BROKEN_LE_CODED because of it,
but so far that was the only drawback.

> Thanks in advance,
> Emil



-- 
Luiz Augusto von Dentz

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH BlueZ 1/9] Enable alternate Bluetooth connection modes
  2024-01-25 14:59       ` Luiz Augusto von Dentz
@ 2024-01-25 16:32         ` Emil Velikov
  2024-01-25 18:18           ` Luiz Augusto von Dentz
  0 siblings, 1 reply; 28+ messages in thread
From: Emil Velikov @ 2024-01-25 16:32 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth, Vicki Pfau, Rachel Blackman

Hi Luiz,

On Thu, 25 Jan 2024 at 14:59, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:

[snip]

> Hmm, are you sure you are not missing something like:
>
> commit 288c90224eec55d13e786844b7954ef060752089
> Author: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> Date:   Mon Dec 19 13:37:02 2022 -0800
>
>     Bluetooth: Enable all supported LE PHY by default
>
>     This enables 2M and Coded PHY by default if they are marked as supported
>     in the LE features bits.
>
>     Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> Later one we had to introduce HCI_QUIRK_BROKEN_LE_CODED because of it,
> but so far that was the only drawback.
>

Hell yeah, that commit should fix our problem. Fwiw we were on the 6.1
stable tree where the above landed in 6.4. Glancing around it was not
picked for any(?) stable branches, which is why we're missing it.

Thanks a million,
Emil

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH BlueZ 1/9] Enable alternate Bluetooth connection modes
  2024-01-25 16:32         ` Emil Velikov
@ 2024-01-25 18:18           ` Luiz Augusto von Dentz
  0 siblings, 0 replies; 28+ messages in thread
From: Luiz Augusto von Dentz @ 2024-01-25 18:18 UTC (permalink / raw)
  To: Emil Velikov; +Cc: linux-bluetooth, Vicki Pfau, Rachel Blackman

Hi Emil,

On Thu, Jan 25, 2024 at 11:32 AM Emil Velikov <emil.l.velikov@gmail.com> wrote:
>
> Hi Luiz,
>
> On Thu, 25 Jan 2024 at 14:59, Luiz Augusto von Dentz
> <luiz.dentz@gmail.com> wrote:
>
> [snip]
>
> > Hmm, are you sure you are not missing something like:
> >
> > commit 288c90224eec55d13e786844b7954ef060752089
> > Author: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> > Date:   Mon Dec 19 13:37:02 2022 -0800
> >
> >     Bluetooth: Enable all supported LE PHY by default
> >
> >     This enables 2M and Coded PHY by default if they are marked as supported
> >     in the LE features bits.
> >
> >     Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> >
> > Later one we had to introduce HCI_QUIRK_BROKEN_LE_CODED because of it,
> > but so far that was the only drawback.
> >
>
> Hell yeah, that commit should fix our problem. Fwiw we were on the 6.1
> stable tree where the above landed in 6.4. Glancing around it was not
> picked for any(?) stable branches, which is why we're missing it.

I didn't tag it for stable since I was afraid something could blow up
like it did, well now at least we know that a quirk is required and
perhaps we can mark both to be backported.

> Thanks a million,
> Emil



-- 
Luiz Augusto von Dentz

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2024-01-25 18:18 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-24 23:43 [PATCH BlueZ 0/9] Distribution inspired fixes Emil Velikov via B4 Relay
2024-01-24 23:43 ` Emil Velikov
2024-01-24 23:43 ` [PATCH BlueZ 1/9] Enable alternate Bluetooth connection modes Emil Velikov via B4 Relay
2024-01-24 23:43   ` Emil Velikov
2024-01-25  2:29   ` Distribution inspired fixes bluez.test.bot
2024-01-25  3:05   ` [PATCH BlueZ 1/9] Enable alternate Bluetooth connection modes Vicki Pfau
2024-01-25 13:41     ` Emil Velikov
2024-01-25  3:54   ` Luiz Augusto von Dentz
2024-01-25 13:39     ` Emil Velikov
2024-01-25 14:59       ` Luiz Augusto von Dentz
2024-01-25 16:32         ` Emil Velikov
2024-01-25 18:18           ` Luiz Augusto von Dentz
2024-01-24 23:43 ` [PATCH BlueZ 2/9] Return at least the title attribute from player_list_metadata() Emil Velikov via B4 Relay
2024-01-24 23:43   ` Emil Velikov
2024-01-24 23:43 ` [PATCH BlueZ 3/9] adapter: Remove experimental flag for PowerState Emil Velikov via B4 Relay
2024-01-24 23:43   ` Emil Velikov
2024-01-24 23:43 ` [PATCH BlueZ 4/9] test: consistently use /usr/bin/env python3 shebang Emil Velikov via B4 Relay
2024-01-24 23:43   ` Emil Velikov
2024-01-24 23:43 ` [PATCH BlueZ 5/9] profiles: remove unused suspend-dummy.c Emil Velikov via B4 Relay
2024-01-24 23:43   ` Emil Velikov
2024-01-24 23:44 ` [PATCH BlueZ 6/9] obex: remove unused syncevolution plugin Emil Velikov via B4 Relay
2024-01-24 23:44   ` Emil Velikov
2024-01-24 23:44 ` [PATCH BlueZ 7/9] obex: remove unused mas/messages-tracker impl Emil Velikov via B4 Relay
2024-01-24 23:44   ` Emil Velikov
2024-01-24 23:44 ` [PATCH BlueZ 8/9] obex: remove phonebook tracker backend Emil Velikov via B4 Relay
2024-01-24 23:44   ` Emil Velikov
2024-01-24 23:44 ` [PATCH BlueZ 9/9] build: ship all config files with --enable-datafiles Emil Velikov via B4 Relay
2024-01-24 23:44   ` Emil Velikov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.