Skip to contentSkip to conversation

btp: Update connect event structure

PATCH Superseded Tedd Ho-Jeong An 4 participants 7 messages Jun 5, 2020 Bluetooth drivers

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/2 btp: Update connect event structure

From: Tedd Ho-Jeong An <[email protected]>

This patch updates the connect event struct to align withe the btp spec.

Opcode 0x82 - Device Connected event
Controller Index: <controller id>
Event parameters: Address_Type (1 octet)
Address (6 octets) Connection Interval (2 octets) Connection Latency (2 octets) Supervision Timeout (2 octets)

This event indicates that a device was connected.

---
 src/shared/btp.h | 3 +++
 1 file changed, 3 insertions(+)
src/shared/btp.h +3 -0
index f0ac3a1ee..cc71a71df 100644
@@ -259,6 +259,9 @@ struct btp_device_found_ev {
 struct btp_gap_device_connected_ev {
 	uint8_t address_type;
 	bdaddr_t address;
+	uint16_t connection_interval;
+	uint16_t connection_latency;
+	uint16_t supervision_timeout;
 } __packed;
 
 #define BTP_EV_GAP_DEVICE_DISCONNECTED		0x83
Signature · 1 line
2.25.4
#1 lore raw

PATCH v2 2/2 tools/btpclient: Use mgmt api for limited discovery

From: Tedd Ho-Jeong An <[email protected]>

There are a few test cases for limited discovery in GAP qualification test suite. But the d-bus API doesn't support it and the only way to start the limited discovery is using the management API.

This patch adds support for limited discovery by using management API.

---
 tools/btpclient.c | 194 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 187 insertions(+), 7 deletions(-)
tools/btpclient.c +187 -7
index f9c693056..46f866117 100644
@@ -36,6 +36,10 @@
 #include "lib/bluetooth.h"
 #include "src/shared/btp.h"
 
+/* For BT_MGMT API */
+#include "lib/mgmt.h"
+#include "src/shared/mgmt.h"
+
 #define AD_PATH "/org/bluez/advertising"
 #define AG_PATH "/org/bluez/agent"
 #define AD_IFACE "org.bluez.LEAdvertisement1"
@@ -77,6 +81,14 @@ static struct btp *btp;
 
 static bool gap_service_registered;
 
+/* For BT_MGMT API */
+static struct mgmt *mgmt;
+static uint16_t mgmt_index;
+
+static uint32_t mgmt_flags;
+
+#define MGMT_OPS_DISCOVERY	0x01
+
 struct ad_data {
 	uint8_t data[25];
 	uint8_t len;
@@ -1403,6 +1415,88 @@ static void set_discovery_filter_reply(struct l_dbus_proxy *proxy,
 					start_discovery_reply, NULL, NULL);
 }
 
+#define SCAN_TYPE_BREDR (1 << BDADDR_BREDR)
+#define SCAN_TYPE_LE ((1 << BDADDR_LE_PUBLIC) | (1 << BDADDR_LE_RANDOM))
+#define SCAN_TYPE_DUAL (SCAN_TYPE_BREDR | SCAN_TYPE_LE)
+
+struct discovery_flags {
+	uint8_t flags;
+};
+
+static int btp_mgmt_start_limited_discovery(uint8_t flags)
+{
+	struct mgmt_cp_start_discovery cp;
+	uint8_t type = SCAN_TYPE_DUAL;
+
+	memset(&cp, 0, sizeof(cp));
+
+	if (flags & (BTP_GAP_DISCOVERY_FLAG_LE |
+		     BTP_GAP_DISCOVERY_FLAG_BREDR)) {
+		type = SCAN_TYPE_DUAL;
+	} else if (flags & BTP_GAP_DISCOVERY_FLAG_LE) {
+		type &= ~SCAN_TYPE_BREDR;
+		type |= SCAN_TYPE_LE;
+	} else if (flags & BTP_GAP_DISCOVERY_FLAG_BREDR) {
+		type |= SCAN_TYPE_BREDR;
+		type &= ~SCAN_TYPE_LE;
+	}
+	cp.type = type;
+
+	return mgmt_send(mgmt, MGMT_OP_START_LIMITED_DISCOVERY, mgmt_index,
+			 sizeof(cp), &cp, NULL, NULL, NULL);
+}
+
+static void btp_mgmt_discovering_destroy(void *user_data)
+{
+	l_free(user_data);
+}
+
+static void btp_mgmt_discovering_cb(uint16_t index, uint16_t len,
+				    const void *param, void *user_data)
+{
+	const struct mgmt_ev_discovering *ev = param;
+	struct discovery_flags *df = user_data;
+
+	if (len < sizeof(*ev)) {
+		l_error("Too short (%u bytes) discovering event", len);
+		return;
+	}
+
+	l_info("MGMT: discovering %s", ev->discovering ? "on" : "off");
+
+	/* Start new discovery */
+	if (ev->discovering == 0 && (mgmt_flags & MGMT_OPS_DISCOVERY))
+		btp_mgmt_start_limited_discovery(df->flags);
+}
+
+static void btp_mgmt_setup_limited_discovery(uint8_t index, uint8_t flags)
+{
+	int ret;
+	struct discovery_flags *df;
+
+	/* Saves the flags so it can be used to start new discovery */
+	df = l_new(struct discovery_flags, 1);
+	df->flags = flags;
+
+	/* Register event for discovering */
+	mgmt_register(mgmt, MGMT_EV_DISCOVERING, mgmt_index,
+		      btp_mgmt_discovering_cb, df,
+		      btp_mgmt_discovering_destroy);
+
+	ret = btp_mgmt_start_limited_discovery(flags);
+	if (ret == 0) {
+		l_error("Unable to send start_discovery cmd");
+		btp_send_error(btp, BTP_GAP_SERVICE, index, BTP_ERROR_FAIL);
+		return;
+	}
+
+	/* Set flag that mgmt interface is used for scanning */
+	mgmt_flags |= MGMT_OPS_DISCOVERY;
+
+	btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_START_DISCOVERY,
+		 index, 0, NULL);
+}
+
 static void btp_gap_start_discovery(uint8_t index, const void *param,
 					uint16_t length, void *user_data)
 {
@@ -1423,10 +1517,17 @@ static void btp_gap_start_discovery(uint8_t index, const void *param,
 		return;
 	}
 
-	l_dbus_proxy_method_call(adapter->proxy, "SetDiscoveryFilter",
-						set_discovery_filter_setup,
-						set_discovery_filter_reply,
-						L_UINT_TO_PTR(cp->flags), NULL);
+	/* Use BT MGMT interface to start limited discovery procedure since
+	 * it is not supported by D-BUS API
+	 */
+	if (cp->flags & BTP_GAP_DISCOVERY_FLAG_LIMITED)
+		btp_mgmt_setup_limited_discovery(index, cp->flags);
+	else {
+		l_dbus_proxy_method_call(adapter->proxy, "SetDiscoveryFilter",
+					 set_discovery_filter_setup,
+					 set_discovery_filter_reply,
+					 L_UINT_TO_PTR(cp->flags), NULL);
+	}
 }
 
 static void clear_discovery_filter_setup(struct l_dbus_message *message,
@@ -1501,6 +1602,29 @@ static void stop_discovery_reply(struct l_dbus_proxy *proxy,
 						NULL, NULL);
 }
 
+static void btp_mgmt_stop_discovery(uint8_t index)
+{
+	struct mgmt_cp_stop_discovery cp;
+	int ret;
+
+	memset(&cp, 0, sizeof(cp));
+	cp.type = SCAN_TYPE_DUAL;
+
+	ret = mgmt_send(mgmt, MGMT_OP_STOP_DISCOVERY, mgmt_index, sizeof(cp),
+			&cp, NULL, NULL, NULL);
+	if (ret == 0) {
+		l_error("Unable to send stop_discovery cmd");
+		btp_send_error(btp, BTP_GAP_SERVICE, index, BTP_ERROR_FAIL);
+		return;
+	}
+
+	/* Clear flag that mgmt interface is used for scanning */
+	mgmt_flags &= ~MGMT_OPS_DISCOVERY;
+
+	btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_STOP_DISCOVERY,
+		 index, 0, NULL);
+}
+
 static void btp_gap_stop_discovery(uint8_t index, const void *param,
 					uint16_t length, void *user_data)
 {
@@ -1520,8 +1644,14 @@ static void btp_gap_stop_discovery(uint8_t index, const void *param,
 		return;
 	}
 
-	l_dbus_proxy_method_call(adapter->proxy, "StopDiscovery", NULL,
-					stop_discovery_reply, NULL, NULL);
+	/* If the discovery procedure is started by BT MGMT API for limited
+	 * discovering, it should be stopped by mgmt API.
+	 */
+	if (mgmt_flags & MGMT_OPS_DISCOVERY)
+		btp_mgmt_stop_discovery(index);
+	else
+		l_dbus_proxy_method_call(adapter->proxy, "StopDiscovery", NULL,
+					 stop_discovery_reply, NULL, NULL);
 }
 
 static void connect_reply(struct l_dbus_proxy *proxy,
@@ -3140,6 +3270,7 @@ static void usage(void)
 	l_info("\tbtpclient [options]");
 	l_info("options:\n"
 	"\t-s, --socket <socket>  Socket to use for BTP\n"
+	"\t-i, --index <id>       Specify the adapter index\n"
 	"\t-q, --quiet            Don't emit any logs\n"
 	"\t-v, --version          Show version\n"
 	"\t-h, --help             Show help options");
@@ -3147,12 +3278,52 @@ static void usage(void)
 
 static const struct option options[] = {
 	{ "socket",	1, 0, 's' },
+	{ "index",	1, 0, 'i' },
 	{ "quiet",	0, 0, 'q' },
 	{ "version",	0, 0, 'v' },
 	{ "help",	0, 0, 'h' },
 	{ 0, 0, 0, 0 }
 };
 
+static void set_index(const char *arg)
+{
+	/* Use default index 0 */
+	if (!arg || !strcmp(arg, "none") || !strcmp(arg, "any") ||
+						!strcmp(arg, "all"))
+		mgmt_index = MGMT_INDEX_NONE;
+	else if (strlen(arg) > 3 && !strncasecmp(arg, "hci", 3))
+		mgmt_index = atoi(&arg[3]);
+	else
+		mgmt_index = atoi(arg);
+}
+
+static int btp_mgmt_init(const char *index_opt)
+{
+	mgmt = mgmt_new_default();
+	if (!mgmt) {
+		l_info("Unable to open mgmt_socket\n");
+		return EXIT_FAILURE;
+	}
+
+	if (index_opt)
+		set_index(index_opt);
+
+	if (mgmt_index == MGMT_INDEX_NONE)
+		mgmt_index = 0;
+
+	return EXIT_SUCCESS;
+}
+
+static void btp_mgmt_release(void)
+{
+	l_error("MGMT: Release all management resources");
+	mgmt_cancel_all(mgmt);
+	mgmt_unregister_all(mgmt);
+	mgmt_unref(mgmt);
+}
+
+static const char *index_opt;
+
 int main(int argc, char *argv[])
 {
 	struct l_dbus_client *client;
@@ -3160,7 +3331,8 @@ int main(int argc, char *argv[])
 
 	l_log_set_stderr();
 
-	while ((opt = getopt_long(argc, argv, "+hs:vq", options, NULL)) != -1) {
+	while ((opt = getopt_long(argc, argv, "+hs:vqi:", options,
+								NULL)) != -1) {
 		switch (opt) {
 		case 's':
 			socket_path = l_strdup(optarg);
@@ -3173,6 +3345,9 @@ int main(int argc, char *argv[])
 		case 'v':
 			l_info("%s", VERSION);
 			return EXIT_SUCCESS;
+		case 'i':
+			index_opt = l_strdup(optarg);
+			break;
 		case 'h':
 		default:
 			usage();
@@ -3189,6 +3364,10 @@ int main(int argc, char *argv[])
 	if (!l_main_init())
 		return EXIT_FAILURE;
 
+	if (btp_mgmt_init(index_opt)) {
+		l_error("Unable to initialize the management interface");
+		return EXIT_FAILURE;
+	}
 
 	adapters = l_queue_new();
 
@@ -3210,6 +3389,7 @@ int main(int argc, char *argv[])
 	l_dbus_client_destroy(client);
 	l_dbus_destroy(dbus);
 	btp_cleanup(btp);
+	btp_mgmt_release();
 
 	l_queue_destroy(adapters, (l_queue_destroy_func_t)btp_adapter_free);
 
Signature · 1 line
2.25.4
#2 lore raw

Re: [PATCH V2 2/2] tools/btpclient: Use mgmt api for limited discovery

Hi Ted,

Quoted 7 lines · On Friday, 5 June 2020 08:10:03 CEST Tedd Ho-Jeong An wrote:

From: Tedd Ho-Jeong An <[email protected]>

There are a few test cases for limited discovery in GAP qualification test suite. But the d-bus API doesn't support it and the only way to start the limited discovery is using the management API.

This patch adds support for limited discovery by using management API.

Isn't it enough by spec to check if limited discoverable flag is set? We provide this info in AdvertisingFlags so we should be conforming.

Also, if we want to be able to explicitly do Limited Discovery this should be added to SetDiscoveryFilter so that btpclient can stay D-Bus only.

Quoted 66 lines
---
 tools/btpclient.c | 194 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 187 insertions(+), 7 deletions(-)
tools/btpclient.c +40 -0
index f9c693056..46f866117 100644
@@ -36,6 +36,10 @@
 #include "lib/bluetooth.h"
 #include "src/shared/btp.h"
 
+/* For BT_MGMT API */
+#include "lib/mgmt.h"
+#include "src/shared/mgmt.h"
+
 #define AD_PATH "/org/bluez/advertising"
 #define AG_PATH "/org/bluez/agent"
 #define AD_IFACE "org.bluez.LEAdvertisement1"
@@ -77,6 +81,14 @@ static struct btp *btp;
 
 static bool gap_service_registered;
 
+/* For BT_MGMT API */
+static struct mgmt *mgmt;
+static uint16_t mgmt_index;
+
+static uint32_t mgmt_flags;
+
+#define MGMT_OPS_DISCOVERY	0x01
+
 struct ad_data {
 	uint8_t data[25];
 	uint8_t len;
@@ -1403,6 +1415,88 @@ static void set_discovery_filter_reply(struct
 l_dbus_proxy *proxy, start_discovery_reply, NULL, NULL);
 }
 
+#define SCAN_TYPE_BREDR (1 << BDADDR_BREDR)
+#define SCAN_TYPE_LE ((1 << BDADDR_LE_PUBLIC) | (1 << BDADDR_LE_RANDOM))
+#define SCAN_TYPE_DUAL (SCAN_TYPE_BREDR | SCAN_TYPE_LE)
+
+struct discovery_flags {
+	uint8_t flags;
+};
+
+static int btp_mgmt_start_limited_discovery(uint8_t flags)
+{
+	struct mgmt_cp_start_discovery cp;
+	uint8_t type = SCAN_TYPE_DUAL;
+
+	memset(&cp, 0, sizeof(cp));
+
+	if (flags & (BTP_GAP_DISCOVERY_FLAG_LE |
+		     BTP_GAP_DISCOVERY_FLAG_BREDR)) {
+		type = SCAN_TYPE_DUAL;
+	} else if (flags & BTP_GAP_DISCOVERY_FLAG_LE) {
+		type &= ~SCAN_TYPE_BREDR;
+		type |= SCAN_TYPE_LE;
+	} else if (flags & BTP_GAP_DISCOVERY_FLAG_BREDR) {
+		type |= SCAN_TYPE_BREDR;
+		type &= ~SCAN_TYPE_LE;
+	}
+	cp.type = type;
+
+	return mgmt_send(mgmt, MGMT_OP_START_LIMITED_DISCOVERY, mgmt_index,

tools/btpclient.c static void set_discovery_filter_reply(struct · line 1455

Quoted 10 lines
tools/btpclient.c +10 -0
+			 sizeof(cp), &cp, NULL, NULL, NULL);
+}
+
+static void btp_mgmt_discovering_destroy(void *user_data)
+{
+	l_free(user_data);
+}
+
+static void btp_mgmt_discovering_cb(uint16_t index, uint16_t len,
+				    const void *param, void 

*user_data)

Quoted 24 lines
tools/btpclient.c +24 -0
+{
+	const struct mgmt_ev_discovering *ev = param;
+	struct discovery_flags *df = user_data;
+
+	if (len < sizeof(*ev)) {
+		l_error("Too short (%u bytes) discovering event", len);
+		return;
+	}
+
+	l_info("MGMT: discovering %s", ev->discovering ? "on" : "off");
+
+	/* Start new discovery */
+	if (ev->discovering == 0 && (mgmt_flags & MGMT_OPS_DISCOVERY))
+		btp_mgmt_start_limited_discovery(df->flags);
+}
+
+static void btp_mgmt_setup_limited_discovery(uint8_t index, uint8_t flags)
+{
+	int ret;
+	struct discovery_flags *df;
+
+	/* Saves the flags so it can be used to start new discovery */
+	df = l_new(struct discovery_flags, 1);
+	df->flags = flags;

tools/btpclient.c static void set_discovery_filter_reply(struct l_dbus_proxy *proxy,

Quoted 10 lines
tools/btpclient.c +10 -0
+
+	/* Register event for discovering */
+	mgmt_register(mgmt, MGMT_EV_DISCOVERING, mgmt_index,
+		      btp_mgmt_discovering_cb, df,
+		      btp_mgmt_discovering_destroy);
+
+	ret = btp_mgmt_start_limited_discovery(flags);
+	if (ret == 0) {
+		l_error("Unable to send start_discovery cmd");
+		btp_send_error(btp, BTP_GAP_SERVICE, index, 

BTP_ERROR_FAIL);

tools/btpclient.c static void set_discovery_filter_reply(struct l_dbus_proxy *proxy,

Quoted 12 lines
tools/btpclient.c +10 -0
+		return;
+	}
+
+	/* Set flag that mgmt interface is used for scanning */
+	mgmt_flags |= MGMT_OPS_DISCOVERY;
+
+	btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_START_DISCOVERY,
+		 index, 0, NULL);
+}
+
 static void btp_gap_start_discovery(uint8_t index, const void *param,
 					uint16_t length, void 

*user_data)

tools/btpclient.c static void btp_gap_start_discovery(uint8_t index, · line 1427

Quoted 7 lines
tools/btpclient.c +0 -2
 {
@@ -1423,10 +1517,17 @@ static void btp_gap_start_discovery(uint8_t index,
 const void *param, return;
 	}
 
-	l_dbus_proxy_method_call(adapter->proxy, "SetDiscoveryFilter",
-						

set_discovery_filter_setup,

tools/btpclient.c static void btp_gap_start_discovery(uint8_t index, · line 1428

Quoted 1 line
tools/btpclient.c +0 -1
-						

set_discovery_filter_reply,

tools/btpclient.c static void btp_gap_start_discovery(uint8_t index, const void *param,

Quoted 9 lines
tools/btpclient.c +7 -1
-						L_UINT_TO_PTR(cp-
 flags), NULL);
+	/* Use BT MGMT interface to start limited discovery procedure since
+	 * it is not supported by D-BUS API
+	 */
+	if (cp->flags & BTP_GAP_DISCOVERY_FLAG_LIMITED)
+		btp_mgmt_setup_limited_discovery(index, cp->flags);
+	else {
+		l_dbus_proxy_method_call(adapter->proxy, 

"SetDiscoveryFilter",

tools/btpclient.c static void btp_gap_start_discovery(uint8_t index, const void *param,

Quoted 3 lines
tools/btpclient.c +3 -0
+					 set_discovery_filter_setup,
+					 set_discovery_filter_reply,
+					 L_UINT_TO_PTR(cp->flags), 

NULL);

Quoted 7 lines
tools/btpclient.c +1 -0
+	}
 }
 

static void clear_discovery_filter_setup(struct l_dbus_message *message,

tools/btpclient.c +0 -0
@@ -1501,6 +1602,29 @@ static void stop_discovery_reply(struct l_dbus_proxy
 *proxy, NULL, NULL);
 }

tools/btpclient.c static void stop_discovery_reply(struct l_dbus_proxy · line 1613

Quoted 10 lines
tools/btpclient.c +9 -0
 
+static void btp_mgmt_stop_discovery(uint8_t index)
+{
+	struct mgmt_cp_stop_discovery cp;
+	int ret;
+
+	memset(&cp, 0, sizeof(cp));
+	cp.type = SCAN_TYPE_DUAL;
+
+	ret = mgmt_send(mgmt, MGMT_OP_STOP_DISCOVERY, mgmt_index, 

sizeof(cp),

tools/btpclient.c static void stop_discovery_reply(struct l_dbus_proxy *proxy,

Quoted 4 lines
tools/btpclient.c +4 -0
+			&cp, NULL, NULL, NULL);
+	if (ret == 0) {
+		l_error("Unable to send stop_discovery cmd");
+		btp_send_error(btp, BTP_GAP_SERVICE, index, 

BTP_ERROR_FAIL);

tools/btpclient.c static void stop_discovery_reply(struct l_dbus_proxy *proxy,

Quoted 12 lines
tools/btpclient.c +10 -0
+		return;
+	}
+
+	/* Clear flag that mgmt interface is used for scanning */
+	mgmt_flags &= ~MGMT_OPS_DISCOVERY;
+
+	btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_STOP_DISCOVERY,
+		 index, 0, NULL);
+}
+
 static void btp_gap_stop_discovery(uint8_t index, const void *param,
 					uint16_t length, void 

*user_data)

tools/btpclient.c static void btp_gap_stop_discovery(uint8_t index, · line 1524

Quoted 7 lines
tools/btpclient.c +0 -2
 {
@@ -1520,8 +1644,14 @@ static void btp_gap_stop_discovery(uint8_t index,
 const void *param, return;
 	}
 
-	l_dbus_proxy_method_call(adapter->proxy, "StopDiscovery", NULL,
-					stop_discovery_reply, NULL, 

NULL);

tools/btpclient.c static void btp_gap_stop_discovery(uint8_t index, const void *param,

Quoted 7 lines
tools/btpclient.c +7 -0
+	/* If the discovery procedure is started by BT MGMT API for limited
+	 * discovering, it should be stopped by mgmt API.
+	 */
+	if (mgmt_flags & MGMT_OPS_DISCOVERY)
+		btp_mgmt_stop_discovery(index);
+	else
+		l_dbus_proxy_method_call(adapter->proxy, "StopDiscovery", 

NULL,

tools/btpclient.c static void btp_gap_stop_discovery(uint8_t index, · line 1654

Quoted 1 line
tools/btpclient.c +1 -0
+					 stop_discovery_reply, NULL, 

NULL);

Quoted 17 lines
tools/btpclient.c +2 -0
 }
 
 static void connect_reply(struct l_dbus_proxy *proxy,
@@ -3140,6 +3270,7 @@ static void usage(void)
 	l_info("\tbtpclient [options]");
 	l_info("options:\n"
 	"\t-s, --socket <socket>  Socket to use for BTP\n"
+	"\t-i, --index <id>       Specify the adapter index\n"
 	"\t-q, --quiet            Don't emit any logs\n"
 	"\t-v, --version          Show version\n"
 	"\t-h, --help             Show help options");
@@ -3147,12 +3278,52 @@ static void usage(void)
 
 static const struct option options[] = {
 	{ "socket",	1, 0, 's' },
+	{ "index",	1, 0, 'i' },
 	{ "quiet",	0, 0, 'q' },

tools/btpclient.c static void usage(void) · line 3292

Quoted 10 lines
tools/btpclient.c +5 -0
 	{ "version",	0, 0, 'v' },
 	{ "help",	0, 0, 'h' },
 	{ 0, 0, 0, 0 }
 };
 
+static void set_index(const char *arg)
+{
+	/* Use default index 0 */
+	if (!arg || !strcmp(arg, "none") || !strcmp(arg, "any") ||
+						!strcmp(arg, 

"all"))

Quoted 38 lines
tools/btpclient.c +34 -0
+		mgmt_index = MGMT_INDEX_NONE;
+	else if (strlen(arg) > 3 && !strncasecmp(arg, "hci", 3))
+		mgmt_index = atoi(&arg[3]);
+	else
+		mgmt_index = atoi(arg);
+}
+
+static int btp_mgmt_init(const char *index_opt)
+{
+	mgmt = mgmt_new_default();
+	if (!mgmt) {
+		l_info("Unable to open mgmt_socket\n");
+		return EXIT_FAILURE;
+	}
+
+	if (index_opt)
+		set_index(index_opt);
+
+	if (mgmt_index == MGMT_INDEX_NONE)
+		mgmt_index = 0;
+
+	return EXIT_SUCCESS;
+}
+
+static void btp_mgmt_release(void)
+{
+	l_error("MGMT: Release all management resources");
+	mgmt_cancel_all(mgmt);
+	mgmt_unregister_all(mgmt);
+	mgmt_unref(mgmt);
+}
+
+static const char *index_opt;
+
 int main(int argc, char *argv[])
 {
 	struct l_dbus_client *client;

tools/btpclient.c int main(int argc, char *argv[]) · line 3163

Quoted 4 lines
tools/btpclient.c +0 -1
@@ -3160,7 +3331,8 @@ int main(int argc, char *argv[])
 
 	l_log_set_stderr();
 
-	while ((opt = getopt_long(argc, argv, "+hs:vq", options, NULL)) != 

-1) {

tools/btpclient.c int main(int argc, char *argv[]) · line 3335

Quoted 2 lines
tools/btpclient.c +2 -0
+	while ((opt = getopt_long(argc, argv, "+hs:vqi:", options,
+								

NULL)) != -1) {

Quoted 31 lines
tools/btpclient.c +8 -0
 		switch (opt) {
 		case 's':
 			socket_path = l_strdup(optarg);
@@ -3173,6 +3345,9 @@ int main(int argc, char *argv[])
 		case 'v':
 			l_info("%s", VERSION);
 			return EXIT_SUCCESS;
+		case 'i':
+			index_opt = l_strdup(optarg);
+			break;
 		case 'h':
 		default:
 			usage();
@@ -3189,6 +3364,10 @@ int main(int argc, char *argv[])
 	if (!l_main_init())
 		return EXIT_FAILURE;
 
+	if (btp_mgmt_init(index_opt)) {
+		l_error("Unable to initialize the management interface");
+		return EXIT_FAILURE;
+	}
 
 	adapters = l_queue_new();
 
@@ -3210,6 +3389,7 @@ int main(int argc, char *argv[])
 	l_dbus_client_destroy(client);
 	l_dbus_destroy(dbus);
 	btp_cleanup(btp);
+	btp_mgmt_release();
 
 	l_queue_destroy(adapters, (l_queue_destroy_func_t)btp_adapter_free);
Signature · 2 lines
pozdrawiam
Szymon Janc
#3 lore raw

Re: [PATCH V2 2/2] tools/btpclient: Use mgmt api for limited discovery

Hi Tedd,

Quoted 10 lines · Szymon Janc

Hi Ted,

Quoted 6 lines · On Friday, 5 June 2020 08:10:03 CEST Tedd Ho-Jeong An wrote:

From: Tedd Ho-Jeong An <[email protected]>

There are a few test cases for limited discovery in GAP qualification test suite. But the d-bus API doesn't support it and the only way to start the limited discovery is using the management API.

Quoted 7 lines
Quoted 1 line

This patch adds support for limited discovery by using management API.

Isn't it enough by spec to check if limited discoverable flag is set? We provide this info in AdvertisingFlags so we should be conforming.

Also, if we want to be able to explicitly do Limited Discovery this should be added to SetDiscoveryFilter so that btpclient can stay D-Bus only.

We should probably use DiscoverableTimeout to indicate a limited discoverable flag instead of general discoverable, I will send a patch for that.

Quoted 315 lines
Quoted 66 lines
---
 tools/btpclient.c | 194 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 187 insertions(+), 7 deletions(-)
tools/btpclient.c +40 -0
index f9c693056..46f866117 100644
@@ -36,6 +36,10 @@
 #include "lib/bluetooth.h"
 #include "src/shared/btp.h"
 
+/* For BT_MGMT API */
+#include "lib/mgmt.h"
+#include "src/shared/mgmt.h"
+
 #define AD_PATH "/org/bluez/advertising"
 #define AG_PATH "/org/bluez/agent"
 #define AD_IFACE "org.bluez.LEAdvertisement1"
@@ -77,6 +81,14 @@ static struct btp *btp;
 
 static bool gap_service_registered;
 
+/* For BT_MGMT API */
+static struct mgmt *mgmt;
+static uint16_t mgmt_index;
+
+static uint32_t mgmt_flags;
+
+#define MGMT_OPS_DISCOVERY   0x01
+
 struct ad_data {
      uint8_t data[25];
      uint8_t len;
@@ -1403,6 +1415,88 @@ static void set_discovery_filter_reply(struct
 l_dbus_proxy *proxy, start_discovery_reply, NULL, NULL);
 }
 
+#define SCAN_TYPE_BREDR (1 << BDADDR_BREDR)
+#define SCAN_TYPE_LE ((1 << BDADDR_LE_PUBLIC) | (1 << BDADDR_LE_RANDOM))
+#define SCAN_TYPE_DUAL (SCAN_TYPE_BREDR | SCAN_TYPE_LE)
+
+struct discovery_flags {
+     uint8_t flags;
+};
+
+static int btp_mgmt_start_limited_discovery(uint8_t flags)
+{
+     struct mgmt_cp_start_discovery cp;
+     uint8_t type = SCAN_TYPE_DUAL;
+
+     memset(&cp, 0, sizeof(cp));
+
+     if (flags & (BTP_GAP_DISCOVERY_FLAG_LE |
+                  BTP_GAP_DISCOVERY_FLAG_BREDR)) {
+             type = SCAN_TYPE_DUAL;
+     } else if (flags & BTP_GAP_DISCOVERY_FLAG_LE) {
+             type &= ~SCAN_TYPE_BREDR;
+             type |= SCAN_TYPE_LE;
+     } else if (flags & BTP_GAP_DISCOVERY_FLAG_BREDR) {
+             type |= SCAN_TYPE_BREDR;
+             type &= ~SCAN_TYPE_LE;
+     }
+     cp.type = type;
+
+     return mgmt_send(mgmt, MGMT_OP_START_LIMITED_DISCOVERY, mgmt_index,

tools/btpclient.c static void set_discovery_filter_reply(struct · line 1455

Quoted 10 lines
tools/btpclient.c +10 -0
+                      sizeof(cp), &cp, NULL, NULL, NULL);
+}
+
+static void btp_mgmt_discovering_destroy(void *user_data)
+{
+     l_free(user_data);
+}
+
+static void btp_mgmt_discovering_cb(uint16_t index, uint16_t len,
+                                 const void *param, void

*user_data)

Quoted 24 lines
tools/btpclient.c +24 -0
+{
+     const struct mgmt_ev_discovering *ev = param;
+     struct discovery_flags *df = user_data;
+
+     if (len < sizeof(*ev)) {
+             l_error("Too short (%u bytes) discovering event", len);
+             return;
+     }
+
+     l_info("MGMT: discovering %s", ev->discovering ? "on" : "off");
+
+     /* Start new discovery */
+     if (ev->discovering == 0 && (mgmt_flags & MGMT_OPS_DISCOVERY))
+             btp_mgmt_start_limited_discovery(df->flags);
+}
+
+static void btp_mgmt_setup_limited_discovery(uint8_t index, uint8_t flags)
+{
+     int ret;
+     struct discovery_flags *df;
+
+     /* Saves the flags so it can be used to start new discovery */
+     df = l_new(struct discovery_flags, 1);
+     df->flags = flags;

tools/btpclient.c static void set_discovery_filter_reply(struct l_dbus_proxy *proxy,

Quoted 10 lines
tools/btpclient.c +10 -0
+
+     /* Register event for discovering */
+     mgmt_register(mgmt, MGMT_EV_DISCOVERING, mgmt_index,
+                   btp_mgmt_discovering_cb, df,
+                   btp_mgmt_discovering_destroy);
+
+     ret = btp_mgmt_start_limited_discovery(flags);
+     if (ret == 0) {
+             l_error("Unable to send start_discovery cmd");
+             btp_send_error(btp, BTP_GAP_SERVICE, index,

BTP_ERROR_FAIL);

tools/btpclient.c static void set_discovery_filter_reply(struct l_dbus_proxy *proxy,

Quoted 12 lines
tools/btpclient.c +10 -0
+             return;
+     }
+
+     /* Set flag that mgmt interface is used for scanning */
+     mgmt_flags |= MGMT_OPS_DISCOVERY;
+
+     btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_START_DISCOVERY,
+              index, 0, NULL);
+}
+
 static void btp_gap_start_discovery(uint8_t index, const void *param,
                                      uint16_t length, void

*user_data)

tools/btpclient.c static void btp_gap_start_discovery(uint8_t index, · line 1427

Quoted 7 lines
tools/btpclient.c +0 -2
 {
@@ -1423,10 +1517,17 @@ static void btp_gap_start_discovery(uint8_t index,
 const void *param, return;
      }
 
-     l_dbus_proxy_method_call(adapter->proxy, "SetDiscoveryFilter",
-

set_discovery_filter_setup,

tools/btpclient.c static void btp_gap_start_discovery(uint8_t index, · line 1428

Quoted 1 line
tools/btpclient.c +0 -1
-

set_discovery_filter_reply,

tools/btpclient.c static void btp_gap_start_discovery(uint8_t index, const void *param,

Quoted 9 lines
tools/btpclient.c +7 -1
-                                             L_UINT_TO_PTR(cp-
 flags), NULL);
+     /* Use BT MGMT interface to start limited discovery procedure since
+      * it is not supported by D-BUS API
+      */
+     if (cp->flags & BTP_GAP_DISCOVERY_FLAG_LIMITED)
+             btp_mgmt_setup_limited_discovery(index, cp->flags);
+     else {
+             l_dbus_proxy_method_call(adapter->proxy,

"SetDiscoveryFilter",

tools/btpclient.c static void btp_gap_start_discovery(uint8_t index, const void *param,

Quoted 3 lines
tools/btpclient.c +3 -0
+                                      set_discovery_filter_setup,
+                                      set_discovery_filter_reply,
+                                      L_UINT_TO_PTR(cp->flags),

NULL);

Quoted 7 lines
tools/btpclient.c +1 -0
+     }
 }
 

static void clear_discovery_filter_setup(struct l_dbus_message *message,

tools/btpclient.c +0 -0
@@ -1501,6 +1602,29 @@ static void stop_discovery_reply(struct l_dbus_proxy
 *proxy, NULL, NULL);
 }

tools/btpclient.c static void stop_discovery_reply(struct l_dbus_proxy · line 1613

Quoted 10 lines
tools/btpclient.c +9 -0
 
+static void btp_mgmt_stop_discovery(uint8_t index)
+{
+     struct mgmt_cp_stop_discovery cp;
+     int ret;
+
+     memset(&cp, 0, sizeof(cp));
+     cp.type = SCAN_TYPE_DUAL;
+
+     ret = mgmt_send(mgmt, MGMT_OP_STOP_DISCOVERY, mgmt_index,

sizeof(cp),

tools/btpclient.c static void stop_discovery_reply(struct l_dbus_proxy *proxy,

Quoted 4 lines
tools/btpclient.c +4 -0
+                     &cp, NULL, NULL, NULL);
+     if (ret == 0) {
+             l_error("Unable to send stop_discovery cmd");
+             btp_send_error(btp, BTP_GAP_SERVICE, index,

BTP_ERROR_FAIL);

tools/btpclient.c static void stop_discovery_reply(struct l_dbus_proxy *proxy,

Quoted 12 lines
tools/btpclient.c +10 -0
+             return;
+     }
+
+     /* Clear flag that mgmt interface is used for scanning */
+     mgmt_flags &= ~MGMT_OPS_DISCOVERY;
+
+     btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_STOP_DISCOVERY,
+              index, 0, NULL);
+}
+
 static void btp_gap_stop_discovery(uint8_t index, const void *param,
                                      uint16_t length, void

*user_data)

tools/btpclient.c static void btp_gap_stop_discovery(uint8_t index, · line 1524

Quoted 7 lines
tools/btpclient.c +0 -2
 {
@@ -1520,8 +1644,14 @@ static void btp_gap_stop_discovery(uint8_t index,
 const void *param, return;
      }
 
-     l_dbus_proxy_method_call(adapter->proxy, "StopDiscovery", NULL,
-                                     stop_discovery_reply, NULL,

NULL);

tools/btpclient.c static void btp_gap_stop_discovery(uint8_t index, const void *param,

Quoted 7 lines
tools/btpclient.c +7 -0
+     /* If the discovery procedure is started by BT MGMT API for limited
+      * discovering, it should be stopped by mgmt API.
+      */
+     if (mgmt_flags & MGMT_OPS_DISCOVERY)
+             btp_mgmt_stop_discovery(index);
+     else
+             l_dbus_proxy_method_call(adapter->proxy, "StopDiscovery",

NULL,

tools/btpclient.c static void btp_gap_stop_discovery(uint8_t index, · line 1654

Quoted 1 line
tools/btpclient.c +1 -0
+                                      stop_discovery_reply, NULL,

NULL);

Quoted 17 lines
tools/btpclient.c +2 -0
 }
 
 static void connect_reply(struct l_dbus_proxy *proxy,
@@ -3140,6 +3270,7 @@ static void usage(void)
      l_info("\tbtpclient [options]");
      l_info("options:\n"
      "\t-s, --socket <socket>  Socket to use for BTP\n"
+     "\t-i, --index <id>       Specify the adapter index\n"
      "\t-q, --quiet            Don't emit any logs\n"
      "\t-v, --version          Show version\n"
      "\t-h, --help             Show help options");
@@ -3147,12 +3278,52 @@ static void usage(void)
 
 static const struct option options[] = {
      { "socket",     1, 0, 's' },
+     { "index",      1, 0, 'i' },
      { "quiet",      0, 0, 'q' },

tools/btpclient.c static void usage(void) · line 3292

Quoted 10 lines
tools/btpclient.c +5 -0
      { "version",    0, 0, 'v' },
      { "help",       0, 0, 'h' },
      { 0, 0, 0, 0 }
 };
 
+static void set_index(const char *arg)
+{
+     /* Use default index 0 */
+     if (!arg || !strcmp(arg, "none") || !strcmp(arg, "any") ||
+                                             !strcmp(arg,

"all"))

Quoted 38 lines
tools/btpclient.c +34 -0
+             mgmt_index = MGMT_INDEX_NONE;
+     else if (strlen(arg) > 3 && !strncasecmp(arg, "hci", 3))
+             mgmt_index = atoi(&arg[3]);
+     else
+             mgmt_index = atoi(arg);
+}
+
+static int btp_mgmt_init(const char *index_opt)
+{
+     mgmt = mgmt_new_default();
+     if (!mgmt) {
+             l_info("Unable to open mgmt_socket\n");
+             return EXIT_FAILURE;
+     }
+
+     if (index_opt)
+             set_index(index_opt);
+
+     if (mgmt_index == MGMT_INDEX_NONE)
+             mgmt_index = 0;
+
+     return EXIT_SUCCESS;
+}
+
+static void btp_mgmt_release(void)
+{
+     l_error("MGMT: Release all management resources");
+     mgmt_cancel_all(mgmt);
+     mgmt_unregister_all(mgmt);
+     mgmt_unref(mgmt);
+}
+
+static const char *index_opt;
+
 int main(int argc, char *argv[])
 {
      struct l_dbus_client *client;

tools/btpclient.c int main(int argc, char *argv[]) · line 3163

Quoted 4 lines
tools/btpclient.c +0 -1
@@ -3160,7 +3331,8 @@ int main(int argc, char *argv[])
 
      l_log_set_stderr();
 
-     while ((opt = getopt_long(argc, argv, "+hs:vq", options, NULL)) !=

-1) {

tools/btpclient.c int main(int argc, char *argv[]) · line 3335

Quoted 2 lines
tools/btpclient.c +2 -0
+     while ((opt = getopt_long(argc, argv, "+hs:vqi:", options,
+

NULL)) != -1) {

Quoted 25 lines
tools/btpclient.c +7 -0
              switch (opt) {
              case 's':
                      socket_path = l_strdup(optarg);
@@ -3173,6 +3345,9 @@ int main(int argc, char *argv[])
              case 'v':
                      l_info("%s", VERSION);
                      return EXIT_SUCCESS;
+             case 'i':
+                     index_opt = l_strdup(optarg);
+                     break;
              case 'h':
              default:
                      usage();
@@ -3189,6 +3364,10 @@ int main(int argc, char *argv[])
      if (!l_main_init())
              return EXIT_FAILURE;
 
+     if (btp_mgmt_init(index_opt)) {
+             l_error("Unable to initialize the management interface");
+             return EXIT_FAILURE;
+     }
 
      adapters = l_queue_new();
 

tools/btpclient.c int main(int argc, char *argv[]) · line 3394

Quoted 6 lines
tools/btpclient.c +1 -0
@@ -3210,6 +3389,7 @@ int main(int argc, char *argv[])
      l_dbus_client_destroy(client);
      l_dbus_destroy(dbus);
      btp_cleanup(btp);
+     btp_mgmt_release();
 
      l_queue_destroy(adapters, (l_queue_destroy_func_t)btp_adapter_free);

--
pozdrawiam
Szymon Janc

Signature · 1 line
Luiz Augusto von Dentz
#4 lore raw

Re: [PATCH V2 2/2] tools/btpclient: Use mgmt api for limited discovery

Hi Tedd,

Quoted 19 lines · Luiz Augusto von Dentz

Hi Tedd,

Quoted 15 lines · Szymon Janc

Hi Ted,

Quoted 7 lines · On Friday, 5 June 2020 08:10:03 CEST Tedd Ho-Jeong An wrote:

From: Tedd Ho-Jeong An <[email protected]>

There are a few test cases for limited discovery in GAP qualification test suite. But the d-bus API doesn't support it and the only way to start the limited discovery is using the management API.

This patch adds support for limited discovery by using management API.

Isn't it enough by spec to check if limited discoverable flag is set? We provide this info in AdvertisingFlags so we should be conforming.

Quoted 6 lines
Quoted 2 lines

Also, if we want to be able to explicitly do Limited Discovery this should be added to SetDiscoveryFilter so that btpclient can stay D-Bus only.

We should probably use DiscoverableTimeout to indicate a limited discoverable flag instead of general discoverable, I will send a patch for that.

In fact it is already supported:

https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/advertising.c#n1067

Though there is a small bug related to it that it doesn't set NO_BREDR in case the adapter global discoverable is not set, but Ive send a fix for that.

Quoted 319 lines
Quoted 307 lines
Quoted 66 lines
---
 tools/btpclient.c | 194 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 187 insertions(+), 7 deletions(-)
tools/btpclient.c +40 -0
index f9c693056..46f866117 100644
@@ -36,6 +36,10 @@
 #include "lib/bluetooth.h"
 #include "src/shared/btp.h"
 
+/* For BT_MGMT API */
+#include "lib/mgmt.h"
+#include "src/shared/mgmt.h"
+
 #define AD_PATH "/org/bluez/advertising"
 #define AG_PATH "/org/bluez/agent"
 #define AD_IFACE "org.bluez.LEAdvertisement1"
@@ -77,6 +81,14 @@ static struct btp *btp;
 
 static bool gap_service_registered;
 
+/* For BT_MGMT API */
+static struct mgmt *mgmt;
+static uint16_t mgmt_index;
+
+static uint32_t mgmt_flags;
+
+#define MGMT_OPS_DISCOVERY   0x01
+
 struct ad_data {
      uint8_t data[25];
      uint8_t len;
@@ -1403,6 +1415,88 @@ static void set_discovery_filter_reply(struct
 l_dbus_proxy *proxy, start_discovery_reply, NULL, NULL);
 }
 
+#define SCAN_TYPE_BREDR (1 << BDADDR_BREDR)
+#define SCAN_TYPE_LE ((1 << BDADDR_LE_PUBLIC) | (1 << BDADDR_LE_RANDOM))
+#define SCAN_TYPE_DUAL (SCAN_TYPE_BREDR | SCAN_TYPE_LE)
+
+struct discovery_flags {
+     uint8_t flags;
+};
+
+static int btp_mgmt_start_limited_discovery(uint8_t flags)
+{
+     struct mgmt_cp_start_discovery cp;
+     uint8_t type = SCAN_TYPE_DUAL;
+
+     memset(&cp, 0, sizeof(cp));
+
+     if (flags & (BTP_GAP_DISCOVERY_FLAG_LE |
+                  BTP_GAP_DISCOVERY_FLAG_BREDR)) {
+             type = SCAN_TYPE_DUAL;
+     } else if (flags & BTP_GAP_DISCOVERY_FLAG_LE) {
+             type &= ~SCAN_TYPE_BREDR;
+             type |= SCAN_TYPE_LE;
+     } else if (flags & BTP_GAP_DISCOVERY_FLAG_BREDR) {
+             type |= SCAN_TYPE_BREDR;
+             type &= ~SCAN_TYPE_LE;
+     }
+     cp.type = type;
+
+     return mgmt_send(mgmt, MGMT_OP_START_LIMITED_DISCOVERY, mgmt_index,

tools/btpclient.c static void set_discovery_filter_reply(struct · line 1455

Quoted 10 lines
tools/btpclient.c +10 -0
+                      sizeof(cp), &cp, NULL, NULL, NULL);
+}
+
+static void btp_mgmt_discovering_destroy(void *user_data)
+{
+     l_free(user_data);
+}
+
+static void btp_mgmt_discovering_cb(uint16_t index, uint16_t len,
+                                 const void *param, void

*user_data)

Quoted 24 lines
tools/btpclient.c +24 -0
+{
+     const struct mgmt_ev_discovering *ev = param;
+     struct discovery_flags *df = user_data;
+
+     if (len < sizeof(*ev)) {
+             l_error("Too short (%u bytes) discovering event", len);
+             return;
+     }
+
+     l_info("MGMT: discovering %s", ev->discovering ? "on" : "off");
+
+     /* Start new discovery */
+     if (ev->discovering == 0 && (mgmt_flags & MGMT_OPS_DISCOVERY))
+             btp_mgmt_start_limited_discovery(df->flags);
+}
+
+static void btp_mgmt_setup_limited_discovery(uint8_t index, uint8_t flags)
+{
+     int ret;
+     struct discovery_flags *df;
+
+     /* Saves the flags so it can be used to start new discovery */
+     df = l_new(struct discovery_flags, 1);
+     df->flags = flags;

tools/btpclient.c static void set_discovery_filter_reply(struct l_dbus_proxy *proxy,

Quoted 10 lines
tools/btpclient.c +10 -0
+
+     /* Register event for discovering */
+     mgmt_register(mgmt, MGMT_EV_DISCOVERING, mgmt_index,
+                   btp_mgmt_discovering_cb, df,
+                   btp_mgmt_discovering_destroy);
+
+     ret = btp_mgmt_start_limited_discovery(flags);
+     if (ret == 0) {
+             l_error("Unable to send start_discovery cmd");
+             btp_send_error(btp, BTP_GAP_SERVICE, index,

BTP_ERROR_FAIL);

tools/btpclient.c static void set_discovery_filter_reply(struct l_dbus_proxy *proxy,

Quoted 12 lines
tools/btpclient.c +10 -0
+             return;
+     }
+
+     /* Set flag that mgmt interface is used for scanning */
+     mgmt_flags |= MGMT_OPS_DISCOVERY;
+
+     btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_START_DISCOVERY,
+              index, 0, NULL);
+}
+
 static void btp_gap_start_discovery(uint8_t index, const void *param,
                                      uint16_t length, void

*user_data)

tools/btpclient.c static void btp_gap_start_discovery(uint8_t index, · line 1427

Quoted 7 lines
tools/btpclient.c +0 -2
 {
@@ -1423,10 +1517,17 @@ static void btp_gap_start_discovery(uint8_t index,
 const void *param, return;
      }
 
-     l_dbus_proxy_method_call(adapter->proxy, "SetDiscoveryFilter",
-

set_discovery_filter_setup,

tools/btpclient.c static void btp_gap_start_discovery(uint8_t index, · line 1428

Quoted 1 line
tools/btpclient.c +0 -1
-

set_discovery_filter_reply,

tools/btpclient.c static void btp_gap_start_discovery(uint8_t index, const void *param,

Quoted 9 lines
tools/btpclient.c +7 -1
-                                             L_UINT_TO_PTR(cp-
 flags), NULL);
+     /* Use BT MGMT interface to start limited discovery procedure since
+      * it is not supported by D-BUS API
+      */
+     if (cp->flags & BTP_GAP_DISCOVERY_FLAG_LIMITED)
+             btp_mgmt_setup_limited_discovery(index, cp->flags);
+     else {
+             l_dbus_proxy_method_call(adapter->proxy,

"SetDiscoveryFilter",

tools/btpclient.c static void btp_gap_start_discovery(uint8_t index, const void *param,

Quoted 3 lines
tools/btpclient.c +3 -0
+                                      set_discovery_filter_setup,
+                                      set_discovery_filter_reply,
+                                      L_UINT_TO_PTR(cp->flags),

NULL);

Quoted 7 lines
tools/btpclient.c +1 -0
+     }
 }
 

static void clear_discovery_filter_setup(struct l_dbus_message *message,

tools/btpclient.c +0 -0
@@ -1501,6 +1602,29 @@ static void stop_discovery_reply(struct l_dbus_proxy
 *proxy, NULL, NULL);
 }

tools/btpclient.c static void stop_discovery_reply(struct l_dbus_proxy · line 1613

Quoted 10 lines
tools/btpclient.c +9 -0
 
+static void btp_mgmt_stop_discovery(uint8_t index)
+{
+     struct mgmt_cp_stop_discovery cp;
+     int ret;
+
+     memset(&cp, 0, sizeof(cp));
+     cp.type = SCAN_TYPE_DUAL;
+
+     ret = mgmt_send(mgmt, MGMT_OP_STOP_DISCOVERY, mgmt_index,

sizeof(cp),

tools/btpclient.c static void stop_discovery_reply(struct l_dbus_proxy *proxy,

Quoted 4 lines
tools/btpclient.c +4 -0
+                     &cp, NULL, NULL, NULL);
+     if (ret == 0) {
+             l_error("Unable to send stop_discovery cmd");
+             btp_send_error(btp, BTP_GAP_SERVICE, index,

BTP_ERROR_FAIL);

tools/btpclient.c static void stop_discovery_reply(struct l_dbus_proxy *proxy,

Quoted 12 lines
tools/btpclient.c +10 -0
+             return;
+     }
+
+     /* Clear flag that mgmt interface is used for scanning */
+     mgmt_flags &= ~MGMT_OPS_DISCOVERY;
+
+     btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_STOP_DISCOVERY,
+              index, 0, NULL);
+}
+
 static void btp_gap_stop_discovery(uint8_t index, const void *param,
                                      uint16_t length, void

*user_data)

tools/btpclient.c static void btp_gap_stop_discovery(uint8_t index, · line 1524

Quoted 7 lines
tools/btpclient.c +0 -2
 {
@@ -1520,8 +1644,14 @@ static void btp_gap_stop_discovery(uint8_t index,
 const void *param, return;
      }
 
-     l_dbus_proxy_method_call(adapter->proxy, "StopDiscovery", NULL,
-                                     stop_discovery_reply, NULL,

NULL);

tools/btpclient.c static void btp_gap_stop_discovery(uint8_t index, const void *param,

Quoted 7 lines
tools/btpclient.c +7 -0
+     /* If the discovery procedure is started by BT MGMT API for limited
+      * discovering, it should be stopped by mgmt API.
+      */
+     if (mgmt_flags & MGMT_OPS_DISCOVERY)
+             btp_mgmt_stop_discovery(index);
+     else
+             l_dbus_proxy_method_call(adapter->proxy, "StopDiscovery",

NULL,

tools/btpclient.c static void btp_gap_stop_discovery(uint8_t index, · line 1654

Quoted 1 line
tools/btpclient.c +1 -0
+                                      stop_discovery_reply, NULL,

NULL);

Quoted 17 lines
tools/btpclient.c +2 -0
 }
 
 static void connect_reply(struct l_dbus_proxy *proxy,
@@ -3140,6 +3270,7 @@ static void usage(void)
      l_info("\tbtpclient [options]");
      l_info("options:\n"
      "\t-s, --socket <socket>  Socket to use for BTP\n"
+     "\t-i, --index <id>       Specify the adapter index\n"
      "\t-q, --quiet            Don't emit any logs\n"
      "\t-v, --version          Show version\n"
      "\t-h, --help             Show help options");
@@ -3147,12 +3278,52 @@ static void usage(void)
 
 static const struct option options[] = {
      { "socket",     1, 0, 's' },
+     { "index",      1, 0, 'i' },
      { "quiet",      0, 0, 'q' },

tools/btpclient.c static void usage(void) · line 3292

Quoted 10 lines
tools/btpclient.c +5 -0
      { "version",    0, 0, 'v' },
      { "help",       0, 0, 'h' },
      { 0, 0, 0, 0 }
 };
 
+static void set_index(const char *arg)
+{
+     /* Use default index 0 */
+     if (!arg || !strcmp(arg, "none") || !strcmp(arg, "any") ||
+                                             !strcmp(arg,

"all"))

Quoted 38 lines
tools/btpclient.c +34 -0
+             mgmt_index = MGMT_INDEX_NONE;
+     else if (strlen(arg) > 3 && !strncasecmp(arg, "hci", 3))
+             mgmt_index = atoi(&arg[3]);
+     else
+             mgmt_index = atoi(arg);
+}
+
+static int btp_mgmt_init(const char *index_opt)
+{
+     mgmt = mgmt_new_default();
+     if (!mgmt) {
+             l_info("Unable to open mgmt_socket\n");
+             return EXIT_FAILURE;
+     }
+
+     if (index_opt)
+             set_index(index_opt);
+
+     if (mgmt_index == MGMT_INDEX_NONE)
+             mgmt_index = 0;
+
+     return EXIT_SUCCESS;
+}
+
+static void btp_mgmt_release(void)
+{
+     l_error("MGMT: Release all management resources");
+     mgmt_cancel_all(mgmt);
+     mgmt_unregister_all(mgmt);
+     mgmt_unref(mgmt);
+}
+
+static const char *index_opt;
+
 int main(int argc, char *argv[])
 {
      struct l_dbus_client *client;

tools/btpclient.c int main(int argc, char *argv[]) · line 3163

Quoted 4 lines
tools/btpclient.c +0 -1
@@ -3160,7 +3331,8 @@ int main(int argc, char *argv[])
 
      l_log_set_stderr();
 
-     while ((opt = getopt_long(argc, argv, "+hs:vq", options, NULL)) !=

-1) {

tools/btpclient.c int main(int argc, char *argv[]) · line 3335

Quoted 2 lines
tools/btpclient.c +2 -0
+     while ((opt = getopt_long(argc, argv, "+hs:vqi:", options,
+

NULL)) != -1) {

Quoted 30 lines
tools/btpclient.c +8 -0
              switch (opt) {
              case 's':
                      socket_path = l_strdup(optarg);
@@ -3173,6 +3345,9 @@ int main(int argc, char *argv[])
              case 'v':
                      l_info("%s", VERSION);
                      return EXIT_SUCCESS;
+             case 'i':
+                     index_opt = l_strdup(optarg);
+                     break;
              case 'h':
              default:
                      usage();
@@ -3189,6 +3364,10 @@ int main(int argc, char *argv[])
      if (!l_main_init())
              return EXIT_FAILURE;
 
+     if (btp_mgmt_init(index_opt)) {
+             l_error("Unable to initialize the management interface");
+             return EXIT_FAILURE;
+     }
 
      adapters = l_queue_new();
 
@@ -3210,6 +3389,7 @@ int main(int argc, char *argv[])
      l_dbus_client_destroy(client);
      l_dbus_destroy(dbus);
      btp_cleanup(btp);
+     btp_mgmt_release();
 
Quoted 8 lines

tools/btpclient.c int main(int argc, char *argv[]) · line 3394

Quoted 1 line
tools/btpclient.c +0 -0
      l_queue_destroy(adapters, (l_queue_destroy_func_t)btp_adapter_free);

--
pozdrawiam
Szymon Janc

--
Luiz Augusto von Dentz

Signature · 1 line
Luiz Augusto von Dentz
#5 lore raw

Re: [PATCH V2 2/2] tools/btpclient: Use mgmt api for limited discovery

In reply to Luiz Augusto von Dentz

Hi Luiz,

Quoted 14 lines · On Friday, 5 June 2020 19:22:56 CEST Luiz Augusto von Dentz wrote:

Hi Tedd,

Quoted 11 lines · Szymon Janc

Hi Ted,

Quoted 7 lines · On Friday, 5 June 2020 08:10:03 CEST Tedd Ho-Jeong An wrote:

From: Tedd Ho-Jeong An <[email protected]>

There are a few test cases for limited discovery in GAP qualification test suite. But the d-bus API doesn't support it and the only way to start the limited discovery is using the management API.

This patch adds support for limited discovery by using management API.

Quoted 8 lines
Quoted 5 lines

Isn't it enough by spec to check if limited discoverable flag is set? We provide this info in AdvertisingFlags so we should be conforming.

Also, if we want to be able to explicitly do Limited Discovery this should be added to SetDiscoveryFilter so that btpclient can stay D-Bus only.

We should probably use DiscoverableTimeout to indicate a limited discoverable flag instead of general discoverable, I will send a patch for that.

This is about doing limited discovery as scanner, not advertising as limited discoverable :-)

Quoted 398 lines
Quoted 398 lines
Quoted 77 lines

---

 tools/btpclient.c | 194 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 187 insertions(+), 7 deletions(-)
tools/btpclient.c +4 -0
index f9c693056..46f866117 100644
@@ -36,6 +36,10 @@
 
 #include "lib/bluetooth.h"
 #include "src/shared/btp.h"
 
+/* For BT_MGMT API */
+#include "lib/mgmt.h"
+#include "src/shared/mgmt.h"
+
 
 #define AD_PATH "/org/bluez/advertising"

#define AG_PATH "/org/bluez/agent"
#define AD_IFACE "org.bluez.LEAdvertisement1"

tools/btpclient.c +8 -0
@@ -77,6 +81,14 @@ static struct btp *btp;
 
 static bool gap_service_registered;
 
+/* For BT_MGMT API */
+static struct mgmt *mgmt;
+static uint16_t mgmt_index;
+
+static uint32_t mgmt_flags;
+
+#define MGMT_OPS_DISCOVERY   0x01
+
 
 struct ad_data {
 
      uint8_t data[25];
      uint8_t len;
tools/btpclient.c +28 -0
@@ -1403,6 +1415,88 @@ static void set_discovery_filter_reply(struct
 l_dbus_proxy *proxy, start_discovery_reply, NULL, NULL);
 
 }
 
+#define SCAN_TYPE_BREDR (1 << BDADDR_BREDR)
+#define SCAN_TYPE_LE ((1 << BDADDR_LE_PUBLIC) | (1 <<
 BDADDR_LE_RANDOM))
+#define SCAN_TYPE_DUAL (SCAN_TYPE_BREDR | SCAN_TYPE_LE)
+
+struct discovery_flags {
+     uint8_t flags;
+};
+
+static int btp_mgmt_start_limited_discovery(uint8_t flags)
+{
+     struct mgmt_cp_start_discovery cp;
+     uint8_t type = SCAN_TYPE_DUAL;
+
+     memset(&cp, 0, sizeof(cp));
+
+     if (flags & (BTP_GAP_DISCOVERY_FLAG_LE |
+                  BTP_GAP_DISCOVERY_FLAG_BREDR)) {
+             type = SCAN_TYPE_DUAL;
+     } else if (flags & BTP_GAP_DISCOVERY_FLAG_LE) {
+             type &= ~SCAN_TYPE_BREDR;
+             type |= SCAN_TYPE_LE;
+     } else if (flags & BTP_GAP_DISCOVERY_FLAG_BREDR) {
+             type |= SCAN_TYPE_BREDR;
+             type &= ~SCAN_TYPE_LE;
+     }
+     cp.type = type;
+
+     return mgmt_send(mgmt, MGMT_OP_START_LIMITED_DISCOVERY,
 mgmt_index,

tools/btpclient.c static void set_discovery_filter_reply(struct · line 1458

Quoted 10 lines
tools/btpclient.c +10 -0
+                      sizeof(cp), &cp, NULL, NULL, NULL);
+}
+
+static void btp_mgmt_discovering_destroy(void *user_data)
+{
+     l_free(user_data);
+}
+
+static void btp_mgmt_discovering_cb(uint16_t index, uint16_t len,
+                                 const void *param, void

*user_data)

Quoted 25 lines
tools/btpclient.c +17 -0
+{
+     const struct mgmt_ev_discovering *ev = param;
+     struct discovery_flags *df = user_data;
+
+     if (len < sizeof(*ev)) {
+             l_error("Too short (%u bytes) discovering event", len);
+             return;
+     }
+
+     l_info("MGMT: discovering %s", ev->discovering ? "on" : "off");
+
+     /* Start new discovery */
+     if (ev->discovering == 0 && (mgmt_flags & MGMT_OPS_DISCOVERY))
+             btp_mgmt_start_limited_discovery(df->flags);
+}
+
+static void btp_mgmt_setup_limited_discovery(uint8_t index, uint8_t

flags)

tools/btpclient.c +7 -0
+{
+     int ret;
+     struct discovery_flags *df;
+
+     /* Saves the flags so it can be used to start new discovery */
+     df = l_new(struct discovery_flags, 1);
+     df->flags = flags;

tools/btpclient.c static void set_discovery_filter_reply(struct l_dbus_proxy *proxy,

Quoted 10 lines
tools/btpclient.c +10 -0
+
+     /* Register event for discovering */
+     mgmt_register(mgmt, MGMT_EV_DISCOVERING, mgmt_index,
+                   btp_mgmt_discovering_cb, df,
+                   btp_mgmt_discovering_destroy);
+
+     ret = btp_mgmt_start_limited_discovery(flags);
+     if (ret == 0) {
+             l_error("Unable to send start_discovery cmd");
+             btp_send_error(btp, BTP_GAP_SERVICE, index,

BTP_ERROR_FAIL);

Quoted 4 lines
tools/btpclient.c +4 -0
+             return;
+     }
+
+     /* Set flag that mgmt interface is used for scanning */

tools/btpclient.c static void set_discovery_filter_reply(struct l_dbus_proxy *proxy,

Quoted 10 lines
tools/btpclient.c +6 -0
+     mgmt_flags |= MGMT_OPS_DISCOVERY;
+
+     btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_START_DISCOVERY,
+              index, 0, NULL);
+}
+
 
 static void btp_gap_start_discovery(uint8_t index, const void *param,
 
                                      uint16_t length, void

*user_data)

tools/btpclient.c static void btp_gap_start_discovery(uint8_t · line 1429

Quoted 10 lines

{

tools/btpclient.c +0 -2
@@ -1423,10 +1517,17 @@ static void btp_gap_start_discovery(uint8_t
 index,
 const void *param, return;
 
      }
 
-     l_dbus_proxy_method_call(adapter->proxy, "SetDiscoveryFilter",
-

set_discovery_filter_setup,

tools/btpclient.c static void btp_gap_start_discovery(uint8_t · line 1430

Quoted 1 line
tools/btpclient.c +0 -1
-

set_discovery_filter_reply,

tools/btpclient.c static void btp_gap_start_discovery(uint8_t index, const void *param,

Quoted 12 lines
tools/btpclient.c +0 -1
-                                             L_UINT_TO_PTR(cp-
 

flags), NULL);

+ /* Use BT MGMT interface to start limited discovery procedure
since

tools/btpclient.c +6 -0
+      * it is not supported by D-BUS API
+      */
+     if (cp->flags & BTP_GAP_DISCOVERY_FLAG_LIMITED)
+             btp_mgmt_setup_limited_discovery(index, cp->flags);
+     else {
+             l_dbus_proxy_method_call(adapter->proxy,

"SetDiscoveryFilter",

tools/btpclient.c static void btp_gap_start_discovery(uint8_t index, const void *param,

Quoted 3 lines
tools/btpclient.c +3 -0
+                                      set_discovery_filter_setup,
+                                      set_discovery_filter_reply,
+                                      L_UINT_TO_PTR(cp->flags),

NULL);

Quoted 13 lines
tools/btpclient.c +1 -0
+     }
 
 }
 
 static void clear_discovery_filter_setup(struct l_dbus_message
 *message,
@@ -1501,6 +1602,29 @@ static void stop_discovery_reply(struct

l_dbus_proxy
*proxy, NULL, NULL);

}

tools/btpclient.c static void stop_discovery_reply(struct l_dbus_proxy *proxy,

Quoted 9 lines
tools/btpclient.c +9 -0
+static void btp_mgmt_stop_discovery(uint8_t index)
+{
+     struct mgmt_cp_stop_discovery cp;
+     int ret;
+
+     memset(&cp, 0, sizeof(cp));
+     cp.type = SCAN_TYPE_DUAL;
+
+     ret = mgmt_send(mgmt, MGMT_OP_STOP_DISCOVERY, mgmt_index,

sizeof(cp),

tools/btpclient.c static void stop_discovery_reply(struct l_dbus_proxy *proxy,

Quoted 4 lines
tools/btpclient.c +4 -0
+                     &cp, NULL, NULL, NULL);
+     if (ret == 0) {
+             l_error("Unable to send stop_discovery cmd");
+             btp_send_error(btp, BTP_GAP_SERVICE, index,

BTP_ERROR_FAIL);

Quoted 4 lines
tools/btpclient.c +4 -0
+             return;
+     }
+
+     /* Clear flag that mgmt interface is used for scanning */

tools/btpclient.c static void stop_discovery_reply(struct l_dbus_proxy *proxy,

Quoted 10 lines
tools/btpclient.c +6 -0
+     mgmt_flags &= ~MGMT_OPS_DISCOVERY;
+
+     btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_STOP_DISCOVERY,
+              index, 0, NULL);
+}
+
 
 static void btp_gap_stop_discovery(uint8_t index, const void *param,
 
                                      uint16_t length, void

*user_data)

tools/btpclient.c static void btp_gap_stop_discovery(uint8_t index, · line 1525

Quoted 9 lines

{

tools/btpclient.c +0 -2
@@ -1520,8 +1644,14 @@ static void btp_gap_stop_discovery(uint8_t index,
 const void *param, return;
 
      }
 
-     l_dbus_proxy_method_call(adapter->proxy, "StopDiscovery", NULL,
-                                     stop_discovery_reply, NULL,

NULL);

tools/btpclient.c static void btp_gap_stop_discovery(uint8_t index, const void *param,

Quoted 8 lines
tools/btpclient.c +1 -0
+     /* If the discovery procedure is started by BT MGMT API for

limited

tools/btpclient.c +6 -0
+      * discovering, it should be stopped by mgmt API.
+      */
+     if (mgmt_flags & MGMT_OPS_DISCOVERY)
+             btp_mgmt_stop_discovery(index);
+     else
+             l_dbus_proxy_method_call(adapter->proxy, "StopDiscovery",

NULL,

Quoted 1 line

+ stop_discovery_reply, NULL,

NULL);

Quoted 26 lines

}

static void connect_reply(struct l_dbus_proxy *proxy,

tools/btpclient.c +1 -0
@@ -3140,6 +3270,7 @@ static void usage(void)
 
      l_info("\tbtpclient [options]");
      l_info("options:\n"
      "\t-s, --socket <socket>  Socket to use for BTP\n"
 
+     "\t-i, --index <id>       Specify the adapter index\n"
 
      "\t-q, --quiet            Don't emit any logs\n"
      "\t-v, --version          Show version\n"
      "\t-h, --help             Show help options");
tools/btpclient.c +1 -0
@@ -3147,12 +3278,52 @@ static void usage(void)
 
 static const struct option options[] = {
 
      { "socket",     1, 0, 's' },
 
+     { "index",      1, 0, 'i' },
 
      { "quiet",      0, 0, 'q' },
      { "version",    0, 0, 'v' },

tools/btpclient.c static void usage(void)

Quoted 10 lines
tools/btpclient.c +5 -0
      { "help",       0, 0, 'h' },
      { 0, 0, 0, 0 }
 
 };
 
+static void set_index(const char *arg)
+{
+     /* Use default index 0 */
+     if (!arg || !strcmp(arg, "none") || !strcmp(arg, "any") ||
+                                             !strcmp(arg,

"all"))

Quoted 41 lines
tools/btpclient.c +34 -0
+             mgmt_index = MGMT_INDEX_NONE;
+     else if (strlen(arg) > 3 && !strncasecmp(arg, "hci", 3))
+             mgmt_index = atoi(&arg[3]);
+     else
+             mgmt_index = atoi(arg);
+}
+
+static int btp_mgmt_init(const char *index_opt)
+{
+     mgmt = mgmt_new_default();
+     if (!mgmt) {
+             l_info("Unable to open mgmt_socket\n");
+             return EXIT_FAILURE;
+     }
+
+     if (index_opt)
+             set_index(index_opt);
+
+     if (mgmt_index == MGMT_INDEX_NONE)
+             mgmt_index = 0;
+
+     return EXIT_SUCCESS;
+}
+
+static void btp_mgmt_release(void)
+{
+     l_error("MGMT: Release all management resources");
+     mgmt_cancel_all(mgmt);
+     mgmt_unregister_all(mgmt);
+     mgmt_unref(mgmt);
+}
+
+static const char *index_opt;
+
 
 int main(int argc, char *argv[])
 {
 
      struct l_dbus_client *client;

tools/btpclient.c int main(int argc, char *argv[]) · line 3163

Quoted 4 lines
tools/btpclient.c +0 -1
@@ -3160,7 +3331,8 @@ int main(int argc, char *argv[])
 
      l_log_set_stderr();
 
-     while ((opt = getopt_long(argc, argv, "+hs:vq", options, NULL)) !=

-1) {

tools/btpclient.c int main(int argc, char *argv[]) · line 3335

Quoted 2 lines
tools/btpclient.c +2 -0
+     while ((opt = getopt_long(argc, argv, "+hs:vqi:", options,
+

NULL)) != -1) {

Quoted 41 lines
tools/btpclient.c +0 -0
              switch (opt) {
 
              case 's':
                      socket_path = l_strdup(optarg);
tools/btpclient.c +3 -0
@@ -3173,6 +3345,9 @@ int main(int argc, char *argv[])
 
              case 'v':
                      l_info("%s", VERSION);
                      return EXIT_SUCCESS;
 
+             case 'i':
+                     index_opt = l_strdup(optarg);
+                     break;
 
              case 'h':
              
              default:
                      usage();
tools/btpclient.c +4 -0
@@ -3189,6 +3364,10 @@ int main(int argc, char *argv[])
 
      if (!l_main_init())
 
              return EXIT_FAILURE;
 
+     if (btp_mgmt_init(index_opt)) {
+             l_error("Unable to initialize the management interface");
+             return EXIT_FAILURE;
+     }
 
      adapters = l_queue_new();
tools/btpclient.c +1 -0
@@ -3210,6 +3389,7 @@ int main(int argc, char *argv[])
 
      l_dbus_client_destroy(client);
      l_dbus_destroy(dbus);
      btp_cleanup(btp);
 
+     btp_mgmt_release();
 
Quoted 2 lines
      l_queue_destroy(adapters,
      (l_queue_destroy_func_t)btp_adapter_free);

--
pozdrawiam
Szymon Janc

Signature · 2 lines
pozdrawiam
Szymon Janc
#6 lore raw

Re: [PATCH V2 2/2] tools/btpclient: Use mgmt api for limited discovery

In reply to Szymon Janc

Hi Szymon,

On 6/5/20, 2:04 AM, "Szymon Janc" <[email protected]> wrote:

Hi Ted,

On Friday, 5 June 2020 08:10:03 CEST Tedd Ho-Jeong An wrote:
> From: Tedd Ho-Jeong An <[email protected]>
>
> There are a few test cases for limited discovery in GAP qualification > test suite. But the d-bus API doesn't support it and the only way to > start the limited discovery is using the management API.
>
> This patch adds support for limited discovery by using management API.

Isn't it enough by spec to check if limited discoverable flag is set? We provide this info in AdvertisingFlags so we should be conforming.

GAS.TS describes that IUT doesn't find a device in the General Discoverable Mode while performing the Limited Discovery. (GAP/DISC/LIMP/BV-02-C)

Also, if we want to be able to explicitly do Limited Discovery this should be added to SetDiscoveryFilter so that btpclient can stay D-Bus only.

I will take a look into it. Thanks for the pointing it out. I wasn't sure the scope of btpclient.

Quoted 66 lines
---
 tools/btpclient.c | 194 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 187 insertions(+), 7 deletions(-)
tools/btpclient.c +40 -0
index f9c693056..46f866117 100644
@@ -36,6 +36,10 @@
 #include "lib/bluetooth.h"
 #include "src/shared/btp.h"
 
+/* For BT_MGMT API */
+#include "lib/mgmt.h"
+#include "src/shared/mgmt.h"
+
 #define AD_PATH "/org/bluez/advertising"
 #define AG_PATH "/org/bluez/agent"
 #define AD_IFACE "org.bluez.LEAdvertisement1"
@@ -77,6 +81,14 @@ static struct btp *btp;
 
 static bool gap_service_registered;
 
+/* For BT_MGMT API */
+static struct mgmt *mgmt;
+static uint16_t mgmt_index;
+
+static uint32_t mgmt_flags;
+
+#define MGMT_OPS_DISCOVERY	0x01
+
 struct ad_data {
 	uint8_t data[25];
 	uint8_t len;
@@ -1403,6 +1415,88 @@ static void set_discovery_filter_reply(struct
 l_dbus_proxy *proxy, start_discovery_reply, NULL, NULL);
 }
 
+#define SCAN_TYPE_BREDR (1 << BDADDR_BREDR)
+#define SCAN_TYPE_LE ((1 << BDADDR_LE_PUBLIC) | (1 << BDADDR_LE_RANDOM))
+#define SCAN_TYPE_DUAL (SCAN_TYPE_BREDR | SCAN_TYPE_LE)
+
+struct discovery_flags {
+	uint8_t flags;
+};
+
+static int btp_mgmt_start_limited_discovery(uint8_t flags)
+{
+	struct mgmt_cp_start_discovery cp;
+	uint8_t type = SCAN_TYPE_DUAL;
+
+	memset(&cp, 0, sizeof(cp));
+
+	if (flags & (BTP_GAP_DISCOVERY_FLAG_LE |
+		     BTP_GAP_DISCOVERY_FLAG_BREDR)) {
+		type = SCAN_TYPE_DUAL;
+	} else if (flags & BTP_GAP_DISCOVERY_FLAG_LE) {
+		type &= ~SCAN_TYPE_BREDR;
+		type |= SCAN_TYPE_LE;
+	} else if (flags & BTP_GAP_DISCOVERY_FLAG_BREDR) {
+		type |= SCAN_TYPE_BREDR;
+		type &= ~SCAN_TYPE_LE;
+	}
+	cp.type = type;
+
+	return mgmt_send(mgmt, MGMT_OP_START_LIMITED_DISCOVERY, mgmt_index,

tools/btpclient.c static void set_discovery_filter_reply(struct · line 1455

Quoted 10 lines
tools/btpclient.c +10 -0
+			 sizeof(cp), &cp, NULL, NULL, NULL);
+}
+
+static void btp_mgmt_discovering_destroy(void *user_data)
+{
+	l_free(user_data);
+}
+
+static void btp_mgmt_discovering_cb(uint16_t index, uint16_t len,
+				    const void *param, void 
    *user_data)
    > +{
    > +	const struct mgmt_ev_discovering *ev = param;
    > +	struct discovery_flags *df = user_data;
    > +
    > +	if (len < sizeof(*ev)) {
    > +		l_error("Too short (%u bytes) discovering event", len);
    > +		return;
    > +	}
    > +
    > +	l_info("MGMT: discovering %s", ev->discovering ? "on" : "off");
    > +
    > +	/* Start new discovery */
    > +	if (ev->discovering == 0 && (mgmt_flags & MGMT_OPS_DISCOVERY))
    > +		btp_mgmt_start_limited_discovery(df->flags);
    > +}
    > +
    > +static void btp_mgmt_setup_limited_discovery(uint8_t index, uint8_t flags)
    > +{
    > +	int ret;
    > +	struct discovery_flags *df;
    > +
    > +	/* Saves the flags so it can be used to start new discovery */
    > +	df = l_new(struct discovery_flags, 1);
    > +	df->flags = flags;
    > +
    > +	/* Register event for discovering */
    > +	mgmt_register(mgmt, MGMT_EV_DISCOVERING, mgmt_index,
    > +		      btp_mgmt_discovering_cb, df,
    > +		      btp_mgmt_discovering_destroy);
    > +
    > +	ret = btp_mgmt_start_limited_discovery(flags);
    > +	if (ret == 0) {
    > +		l_error("Unable to send start_discovery cmd");
    > +		btp_send_error(btp, BTP_GAP_SERVICE, index, 
    BTP_ERROR_FAIL);
    > +		return;
    > +	}
    > +
    > +	/* Set flag that mgmt interface is used for scanning */
    > +	mgmt_flags |= MGMT_OPS_DISCOVERY;
    > +
    > +	btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_START_DISCOVERY,
    > +		 index, 0, NULL);
    > +}
    > +
    >  static void btp_gap_start_discovery(uint8_t index, const void *param,
    >  					uint16_t length, void 
    *user_data)
    >  {
    > @@ -1423,10 +1517,17 @@ static void btp_gap_start_discovery(uint8_t index,
    > const void *param, return;
    >  	}
    > 
    > -	l_dbus_proxy_method_call(adapter->proxy, "SetDiscoveryFilter",
    > -						
    set_discovery_filter_setup,
    > -						
    set_discovery_filter_reply,
    > -						L_UINT_TO_PTR(cp-
    >flags), NULL);
    > +	/* Use BT MGMT interface to start limited discovery procedure since
    > +	 * it is not supported by D-BUS API
    > +	 */
    > +	if (cp->flags & BTP_GAP_DISCOVERY_FLAG_LIMITED)
    > +		btp_mgmt_setup_limited_discovery(index, cp->flags);
    > +	else {
    > +		l_dbus_proxy_method_call(adapter->proxy, 
    "SetDiscoveryFilter",
    > +					 set_discovery_filter_setup,
    > +					 set_discovery_filter_reply,
    > +					 L_UINT_TO_PTR(cp->flags), 
    NULL);
    > +	}
    >  }
    > 
    >  static void clear_discovery_filter_setup(struct l_dbus_message *message,
    > @@ -1501,6 +1602,29 @@ static void stop_discovery_reply(struct l_dbus_proxy
    > *proxy, NULL, NULL);
    >  }
    > 
    > +static void btp_mgmt_stop_discovery(uint8_t index)
    > +{
    > +	struct mgmt_cp_stop_discovery cp;
    > +	int ret;
    > +
    > +	memset(&cp, 0, sizeof(cp));
    > +	cp.type = SCAN_TYPE_DUAL;
    > +
    > +	ret = mgmt_send(mgmt, MGMT_OP_STOP_DISCOVERY, mgmt_index, 
    sizeof(cp),
    > +			&cp, NULL, NULL, NULL);
    > +	if (ret == 0) {
    > +		l_error("Unable to send stop_discovery cmd");
    > +		btp_send_error(btp, BTP_GAP_SERVICE, index, 
    BTP_ERROR_FAIL);
    > +		return;
    > +	}
    > +
    > +	/* Clear flag that mgmt interface is used for scanning */
    > +	mgmt_flags &= ~MGMT_OPS_DISCOVERY;
    > +
    > +	btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_STOP_DISCOVERY,
    > +		 index, 0, NULL);
    > +}
    > +
    >  static void btp_gap_stop_discovery(uint8_t index, const void *param,
    >  					uint16_t length, void 
    *user_data)
    >  {
    > @@ -1520,8 +1644,14 @@ static void btp_gap_stop_discovery(uint8_t index,
    > const void *param, return;
    >  	}
    > 
    > -	l_dbus_proxy_method_call(adapter->proxy, "StopDiscovery", NULL,
    > -					stop_discovery_reply, NULL, 
    NULL);
    > +	/* If the discovery procedure is started by BT MGMT API for limited
    > +	 * discovering, it should be stopped by mgmt API.
    > +	 */
    > +	if (mgmt_flags & MGMT_OPS_DISCOVERY)
    > +		btp_mgmt_stop_discovery(index);
    > +	else
    > +		l_dbus_proxy_method_call(adapter->proxy, "StopDiscovery", 
    NULL,
    > +					 stop_discovery_reply, NULL, 
    NULL);
    >  }
    > 
    >  static void connect_reply(struct l_dbus_proxy *proxy,
    > @@ -3140,6 +3270,7 @@ static void usage(void)
    >  	l_info("\tbtpclient [options]");
    >  	l_info("options:\n"
    >  	"\t-s, --socket <socket>  Socket to use for BTP\n"
    > +	"\t-i, --index <id>       Specify the adapter index\n"
    >  	"\t-q, --quiet            Don't emit any logs\n"
    >  	"\t-v, --version          Show version\n"
    >  	"\t-h, --help             Show help options");
    > @@ -3147,12 +3278,52 @@ static void usage(void)
    > 
    >  static const struct option options[] = {
    >  	{ "socket",	1, 0, 's' },
    > +	{ "index",	1, 0, 'i' },
    >  	{ "quiet",	0, 0, 'q' },
    >  	{ "version",	0, 0, 'v' },
    >  	{ "help",	0, 0, 'h' },
    >  	{ 0, 0, 0, 0 }
    >  };
    > 
    > +static void set_index(const char *arg)
    > +{
    > +	/* Use default index 0 */
    > +	if (!arg || !strcmp(arg, "none") || !strcmp(arg, "any") ||
    > +						!strcmp(arg, 
    "all"))
    > +		mgmt_index = MGMT_INDEX_NONE;
    > +	else if (strlen(arg) > 3 && !strncasecmp(arg, "hci", 3))
    > +		mgmt_index = atoi(&arg[3]);
    > +	else
    > +		mgmt_index = atoi(arg);
    > +}
    > +
    > +static int btp_mgmt_init(const char *index_opt)
    > +{
    > +	mgmt = mgmt_new_default();
    > +	if (!mgmt) {
    > +		l_info("Unable to open mgmt_socket\n");
    > +		return EXIT_FAILURE;
    > +	}
    > +
    > +	if (index_opt)
    > +		set_index(index_opt);
    > +
    > +	if (mgmt_index == MGMT_INDEX_NONE)
    > +		mgmt_index = 0;
    > +
    > +	return EXIT_SUCCESS;
    > +}
    > +
    > +static void btp_mgmt_release(void)
    > +{
    > +	l_error("MGMT: Release all management resources");
    > +	mgmt_cancel_all(mgmt);
    > +	mgmt_unregister_all(mgmt);
    > +	mgmt_unref(mgmt);
    > +}
    > +
    > +static const char *index_opt;
    > +
    >  int main(int argc, char *argv[])
    >  {
    >  	struct l_dbus_client *client;
    > @@ -3160,7 +3331,8 @@ int main(int argc, char *argv[])
    > 
    >  	l_log_set_stderr();
    > 
    > -	while ((opt = getopt_long(argc, argv, "+hs:vq", options, NULL)) != 
    -1) {
    > +	while ((opt = getopt_long(argc, argv, "+hs:vqi:", options,
    > +								
    NULL)) != -1) {
    >  		switch (opt) {
    >  		case 's':
    >  			socket_path = l_strdup(optarg);
    > @@ -3173,6 +3345,9 @@ int main(int argc, char *argv[])
    >  		case 'v':
    >  			l_info("%s", VERSION);
    >  			return EXIT_SUCCESS;
    > +		case 'i':
    > +			index_opt = l_strdup(optarg);
    > +			break;
    >  		case 'h':
    >  		default:
    >  			usage();
    > @@ -3189,6 +3364,10 @@ int main(int argc, char *argv[])
    >  	if (!l_main_init())
    >  		return EXIT_FAILURE;
    > 
    > +	if (btp_mgmt_init(index_opt)) {
    > +		l_error("Unable to initialize the management interface");
    > +		return EXIT_FAILURE;
    > +	}
    > 
    >  	adapters = l_queue_new();
    > 
    > @@ -3210,6 +3389,7 @@ int main(int argc, char *argv[])
    >  	l_dbus_client_destroy(client);
    >  	l_dbus_destroy(dbus);
    >  	btp_cleanup(btp);
    > +	btp_mgmt_release();
    > 
    >  	l_queue_destroy(adapters, (l_queue_destroy_func_t)btp_adapter_free);


    -- 
    pozdrawiam
    Szymon Janc

Regards,
Tedd