All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH BlueZ 1/8] tools/btpclient: Fix start adv commend comment
@ 2018-01-19 16:41 Grzegorz Kolodziejczyk
  2018-01-19 16:41 ` [PATCH BlueZ 2/8] tools/btpclient: Initial check of ad_proxy presence in stop adv cmd Grzegorz Kolodziejczyk
                   ` (7 more replies)
  0 siblings, 8 replies; 16+ messages in thread
From: Grzegorz Kolodziejczyk @ 2018-01-19 16:41 UTC (permalink / raw)
  To: linux-bluetooth

Comment should be aproperiate for advertising command. Device needs to
be powered to advertise.
---
 tools/btpclient.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/btpclient.c b/tools/btpclient.c
index af0e75290..33116ce1b 100644
--- a/tools/btpclient.c
+++ b/tools/btpclient.c
@@ -1038,7 +1038,7 @@ static void btp_gap_start_advertising(uint8_t index, const void *param,
 		goto failed;
 	}
 
-	/* Adapter needs to be powered to be able to remove devices */
+	/* Adapter needs to be powered to be able to advertise */
 	if (!l_dbus_proxy_get_property(adapter->proxy, "Powered", "b", &prop) ||
 							!prop || ad.registered)
 		goto failed;
-- 
2.13.6


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

* [PATCH BlueZ 2/8] tools/btpclient: Initial check of ad_proxy presence in stop adv cmd
  2018-01-19 16:41 [PATCH BlueZ 1/8] tools/btpclient: Fix start adv commend comment Grzegorz Kolodziejczyk
@ 2018-01-19 16:41 ` Grzegorz Kolodziejczyk
  2018-01-19 16:41 ` [PATCH BlueZ 3/8] tools/btpclient: Add set io capabilities command Grzegorz Kolodziejczyk
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 16+ messages in thread
From: Grzegorz Kolodziejczyk @ 2018-01-19 16:41 UTC (permalink / raw)
  To: linux-bluetooth

This patch covers with fail response if no advertising proxy was
registered at command beginning.
---
 tools/btpclient.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/tools/btpclient.c b/tools/btpclient.c
index 33116ce1b..f2c79b3a3 100644
--- a/tools/btpclient.c
+++ b/tools/btpclient.c
@@ -1156,19 +1156,15 @@ static void btp_gap_stop_advertising(uint8_t index, const void *param,
 	}
 
 	if (!l_dbus_proxy_get_property(adapter->proxy, "Powered", "b", &prop) ||
-							!prop || !ad.registered)
+				!prop || !adapter->ad_proxy || !ad.registered)
 		goto failed;
 
-	if (adapter->ad_proxy) {
-		if (!l_dbus_proxy_method_call(adapter->ad_proxy,
+	if (!l_dbus_proxy_method_call(adapter->ad_proxy,
 						"UnregisterAdvertisement",
 						unreg_advertising_setup,
 						stop_advertising_reply,
-						NULL, NULL)) {
-			status = BTP_ERROR_FAIL;
-			goto failed;
-		}
-	}
+						NULL, NULL))
+		goto failed;
 
 	return;
 
-- 
2.13.6


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

* [PATCH BlueZ 3/8] tools/btpclient: Add set io capabilities command
  2018-01-19 16:41 [PATCH BlueZ 1/8] tools/btpclient: Fix start adv commend comment Grzegorz Kolodziejczyk
  2018-01-19 16:41 ` [PATCH BlueZ 2/8] tools/btpclient: Initial check of ad_proxy presence in stop adv cmd Grzegorz Kolodziejczyk
@ 2018-01-19 16:41 ` Grzegorz Kolodziejczyk
  2018-01-23 13:48   ` Szymon Janc
  2018-01-19 16:41 ` [PATCH BlueZ 4/8] tools/btpclient: Restore default settings on reset Grzegorz Kolodziejczyk
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Grzegorz Kolodziejczyk @ 2018-01-19 16:41 UTC (permalink / raw)
  To: linux-bluetooth

This patch adds support for set io capabilities command.
---
 tools/btpclient.c | 361 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 361 insertions(+)

diff --git a/tools/btpclient.c b/tools/btpclient.c
index f2c79b3a3..708092937 100644
--- a/tools/btpclient.c
+++ b/tools/btpclient.c
@@ -36,7 +36,9 @@
 #include "src/shared/btp.h"
 
 #define AD_PATH "/org/bluez/advertising"
+#define AG_PATH "/org/bluez/agent"
 #define AD_IFACE "org.bluez.LEAdvertisement1"
+#define AG_IFACE "org.bluez.Agent1"
 
 /* List of assigned numbers for advetising data and scan response */
 #define AD_TYPE_FLAGS				0x01
@@ -97,6 +99,12 @@ static struct ad {
 	bool appearance;
 } ad;
 
+static struct btp_agent {
+	bool registered;
+	struct l_dbus_proxy *proxy;
+	struct l_dbus_message *pending_req;
+} ag;
+
 static char *dupuuid2str(const uint8_t *uuid, uint8_t len)
 {
 	switch (len) {
@@ -198,6 +206,31 @@ static struct btp_device *find_device_by_address(struct btp_adapter *adapter,
 	return NULL;
 }
 
+static bool match_device_paths(const void *device, const void *path)
+{
+	const struct btp_device *dev = device;
+
+	return !strcmp(l_dbus_proxy_get_path(dev->proxy), path);
+}
+
+static struct btp_device *find_device_by_path(const char *path)
+{
+	const struct l_queue_entry *entry;
+	struct btp_device *device;
+
+	for (entry = l_queue_get_entries(adapters); entry;
+							entry = entry->next) {
+		struct btp_adapter *adapter = entry->data;
+
+		device = l_queue_find(adapter->devices, match_device_paths,
+									path);
+		if (device)
+			return device;
+	}
+
+	return NULL;
+}
+
 static bool match_adapter_dev_proxy(const void *device, const void *proxy)
 {
 	const struct btp_device *d = device;
@@ -269,6 +302,7 @@ static void btp_gap_read_commands(uint8_t index, const void *param,
 	commands |= (1 << BTP_OP_GAP_STOP_DISCOVERY);
 	commands |= (1 << BTP_OP_GAP_CONNECT);
 	commands |= (1 << BTP_OP_GAP_DISCONNECT);
+	commands |= (1 << BTP_OP_GAP_SET_IO_CAPA);
 
 	commands = L_CPU_TO_LE16(commands);
 
@@ -418,6 +452,43 @@ static void unreg_advertising_reply(struct l_dbus_proxy *proxy,
 		l_info("Unable to unregister ad interface");
 }
 
+static void unreg_agent_setup(struct l_dbus_message *message, void *user_data)
+{
+	struct l_dbus_message_builder *builder;
+
+	builder = l_dbus_message_builder_new(message);
+
+	l_dbus_message_builder_append_basic(builder, 'o', AG_PATH);
+
+	l_dbus_message_builder_finalize(builder);
+	l_dbus_message_builder_destroy(builder);
+}
+
+static void unreg_agent_reply(struct l_dbus_proxy *proxy,
+						struct l_dbus_message *result,
+						void *user_data)
+{
+	if (l_dbus_message_is_error(result)) {
+		const char *name;
+
+		l_dbus_message_get_error(result, &name, NULL);
+
+		l_error("Failed to unregister agent %s (%s)",
+					l_dbus_proxy_get_path(proxy), name);
+		return;
+	}
+
+	if (!l_dbus_object_remove_interface(dbus, AG_PATH,
+						L_DBUS_INTERFACE_PROPERTIES))
+		l_info("Unable to remove propety instance");
+	if (!l_dbus_object_remove_interface(dbus, AG_PATH, AG_IFACE))
+		l_info("Unable to remove agent instance");
+	if (!l_dbus_unregister_interface(dbus, AG_IFACE))
+		l_info("Unable to unregister agent interface");
+
+	ag.registered = false;
+}
+
 static void btp_gap_reset(uint8_t index, const void *param, uint16_t length,
 								void *user_data)
 {
@@ -458,6 +529,15 @@ static void btp_gap_reset(uint8_t index, const void *param, uint16_t length,
 			goto failed;
 		}
 
+	if (ag.registered)
+		if (!l_dbus_proxy_method_call(ag.proxy, "UnregisterAgent",
+							unreg_agent_setup,
+							unreg_agent_reply,
+							NULL, NULL)) {
+			status = BTP_ERROR_FAIL;
+			goto failed;
+		}
+
 	/* TODO for we assume all went well */
 	btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_RESET, index, 0, NULL);
 	return;
@@ -1513,6 +1593,278 @@ failed:
 	btp_send_error(btp, BTP_GAP_SERVICE, index, status);
 }
 
+static struct l_dbus_message *ag_release_call(struct l_dbus *dbus,
+						struct l_dbus_message *message,
+						void *user_data)
+{
+	struct l_dbus_message *reply;
+
+	reply = l_dbus_message_new_method_return(message);
+	l_dbus_message_set_arguments(reply, "");
+
+	return reply;
+}
+
+static struct l_dbus_message *ag_request_passkey_call(struct l_dbus *dbus,
+						struct l_dbus_message *message,
+						void *user_data)
+{
+	struct btp_gap_passkey_req_ev ev;
+	struct btp_device *device;
+	struct btp_adapter *adapter;
+	const char *path, *str_addr, *str_addr_type;
+
+	l_dbus_message_get_arguments(message, "o", &path);
+
+	device = find_device_by_path(path);
+
+	if (!l_dbus_proxy_get_property(device->proxy, "Address", "s", &str_addr)
+		|| !l_dbus_proxy_get_property(device->proxy, "AddressType", "s",
+		&str_addr_type)) {
+		l_info("Cannot get device properties");
+
+		return NULL;
+	}
+
+	ev.address_type = strcmp(str_addr_type, "public") ?
+							BTP_GAP_ADDR_RANDOM :
+							BTP_GAP_ADDR_PUBLIC;
+	if (!str2ba(str_addr, &ev.address))
+		return NULL;
+
+	adapter = find_adapter_by_device(device);
+
+	ag.pending_req = l_dbus_message_ref(message);
+
+	btp_send(btp, BTP_GAP_SERVICE, BTP_EV_GAP_PASSKEY_REQUEST,
+					adapter->index, sizeof(ev), &ev);
+
+	return NULL;
+}
+
+static struct l_dbus_message *ag_display_passkey_call(struct l_dbus *dbus,
+						struct l_dbus_message *message,
+						void *user_data)
+{
+	struct l_dbus_message *reply;
+
+	reply = l_dbus_message_new_method_return(message);
+	l_dbus_message_set_arguments(reply, "");
+
+	return reply;
+}
+
+static struct l_dbus_message *ag_request_confirmation_call(struct l_dbus *dbus,
+						struct l_dbus_message *message,
+						void *user_data)
+{
+	struct l_dbus_message *reply;
+
+	reply = l_dbus_message_new_method_return(message);
+	l_dbus_message_set_arguments(reply, "");
+
+	return reply;
+}
+
+static struct l_dbus_message *ag_authorize_service_call(struct l_dbus *dbus,
+						struct l_dbus_message *message,
+						void *user_data)
+{
+	struct l_dbus_message *reply;
+
+	reply = l_dbus_message_new_method_return(message);
+	l_dbus_message_set_arguments(reply, "");
+
+	return reply;
+}
+
+static struct l_dbus_message *ag_cancel_call(struct l_dbus *dbus,
+						struct l_dbus_message *message,
+						void *user_data)
+{
+	struct l_dbus_message *reply;
+
+	reply = l_dbus_message_new_method_return(message);
+	l_dbus_message_set_arguments(reply, "");
+
+	return reply;
+}
+
+static void setup_ag_interface(struct l_dbus_interface *iface)
+{
+	l_dbus_interface_method(iface, "Release", 0, ag_release_call, "", "");
+	l_dbus_interface_method(iface, "RequestPasskey", 0,
+					ag_request_passkey_call, "u", "o",
+					"passkey", "device");
+	l_dbus_interface_method(iface, "DisplayPasskey", 0,
+					ag_display_passkey_call, "", "ouq",
+					"device", "passkey", "entered");
+	l_dbus_interface_method(iface, "RequestConfirmation", 0,
+					ag_request_confirmation_call, "", "ou",
+					"device", "passkey");
+	l_dbus_interface_method(iface, "RequestAuthorization", 0,
+					ag_request_confirmation_call, "", "o",
+					"device");
+	l_dbus_interface_method(iface, "AuthorizeService", 0,
+					ag_authorize_service_call, "", "os",
+					"device", "uuid");
+	l_dbus_interface_method(iface, "Cancel", 0, ag_cancel_call, "", "");
+}
+
+struct set_io_capabilities_data {
+	uint8_t capa;
+	struct btp_adapter *adapter;
+};
+
+static void set_io_capabilities_setup(struct l_dbus_message *message,
+								void *user_data)
+{
+	struct set_io_capabilities_data *sicd = user_data;
+	struct l_dbus_message_builder *builder;
+	char *capa_str;
+
+	builder = l_dbus_message_builder_new(message);
+
+	l_dbus_message_builder_append_basic(builder, 'o', AG_PATH);
+
+	switch (sicd->capa) {
+	case BTP_GAP_IOCAPA_DISPLAY_ONLY:
+		capa_str = "DisplayOnly";
+		break;
+	case BTP_GAP_IOCAPA_DISPLAY_YESNO:
+		capa_str = "DisplayYesNo";
+		break;
+	case BTP_GAP_IOCAPA_KEYBOARD_ONLY:
+		capa_str = "KeyboardOnly";
+		break;
+	case BTP_GAP_IOCAPA_NO_INPUT_NO_OUTPUT:
+		capa_str = "NoInputNoOutput";
+		break;
+	case BTP_GAP_IOCAPA_KEYBOARD_DISPLAY:
+		capa_str = "KeyboardDisplay";
+		break;
+	default:
+		l_error("Wrong iocapa given!");
+		l_dbus_message_builder_finalize(builder);
+		l_dbus_message_builder_destroy(builder);
+
+		return;
+	}
+
+	l_dbus_message_builder_append_basic(builder, 's', capa_str);
+
+	l_dbus_message_builder_finalize(builder);
+	l_dbus_message_builder_destroy(builder);
+}
+
+static void set_io_capabilities_reply(struct l_dbus_proxy *proxy,
+						struct l_dbus_message *result,
+						void *user_data)
+{
+	struct set_io_capabilities_data *sicd = user_data;
+
+	if (!sicd->adapter) {
+		btp_send_error(btp, BTP_GAP_SERVICE, BTP_INDEX_NON_CONTROLLER,
+								BTP_ERROR_FAIL);
+		return;
+	}
+
+	if (l_dbus_message_is_error(result)) {
+		const char *name, *desc;
+
+		if (!l_dbus_object_remove_interface(dbus, AG_PATH, AG_IFACE))
+			l_info("Unable to remove agent instance");
+		if (!l_dbus_unregister_interface(dbus, AG_IFACE))
+			l_info("Unable to unregister agent interface");
+
+		l_dbus_message_get_error(result, &name, &desc);
+		l_error("Failed to set io capabilities (%s), %s", name, desc);
+
+		btp_send_error(btp, BTP_GAP_SERVICE, sicd->adapter->index,
+								BTP_ERROR_FAIL);
+		return;
+	}
+
+	ag.registered = true;
+
+	btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_SET_IO_CAPA,
+						sicd->adapter->index, 0, NULL);
+}
+
+static void set_io_capabilities_destroy(void *user_data)
+{
+	l_free(user_data);
+}
+
+static void btp_gap_set_io_capabilities(uint8_t index, const void *param,
+					uint16_t length, void *user_data)
+{
+	struct btp_adapter *adapter = find_adapter_by_index(index);
+	const struct btp_gap_set_io_capa_cp *cp = param;
+	uint8_t status = BTP_ERROR_FAIL;
+	struct set_io_capabilities_data *data;
+	bool prop;
+
+	if (!adapter) {
+		status = BTP_ERROR_INVALID_INDEX;
+		goto failed;
+	}
+
+	/* Adapter needs to be powered to be able to set io cap */
+	if (!l_dbus_proxy_get_property(adapter->proxy, "Powered", "b", &prop) ||
+							!prop || ag.registered)
+		goto failed;
+
+	if (!l_dbus_register_interface(dbus, AG_IFACE, setup_ag_interface, NULL,
+								false)) {
+		l_info("Unable to register agent interface");
+		goto failed;
+	}
+
+	if (!l_dbus_object_add_interface(dbus, AG_PATH, AG_IFACE, NULL)) {
+		l_info("Unable to instantiate agent interface");
+
+		if (!l_dbus_unregister_interface(dbus, AD_IFACE))
+			l_info("Unable to unregister agent interface");
+
+		goto failed;
+	}
+
+	if (!l_dbus_object_add_interface(dbus, AG_PATH,
+						L_DBUS_INTERFACE_PROPERTIES,
+						NULL)) {
+		l_info("Unable to instantiate the ag properties interface");
+
+		if (!l_dbus_object_remove_interface(dbus, AG_PATH, AG_IFACE))
+			l_info("Unable to remove agent instance");
+		if (!l_dbus_unregister_interface(dbus, AG_IFACE))
+			l_info("Unable to unregister agent interface");
+
+		goto failed;
+	}
+
+	data = l_new(struct set_io_capabilities_data, 1);
+	data->adapter = adapter;
+	data->capa = cp->capa;
+
+	if (!l_dbus_proxy_method_call(ag.proxy, "RegisterAgent",
+						set_io_capabilities_setup,
+						set_io_capabilities_reply, data,
+						set_io_capabilities_destroy)) {
+		if (!l_dbus_object_remove_interface(dbus, AG_PATH, AG_IFACE))
+			l_info("Unable to remove agent instance");
+		if (!l_dbus_unregister_interface(dbus, AG_IFACE))
+			l_info("Unable to unregister agent interface");
+
+		goto failed;
+	}
+
+	return;
+
+failed:
+	btp_send_error(btp, BTP_GAP_SERVICE, index, status);
+}
+
 static void btp_gap_device_found_ev(struct l_dbus_proxy *proxy)
 {
 	struct btp_device_found_ev ev;
@@ -1634,6 +1986,9 @@ static void register_gap_service(void)
 
 	btp_register(btp, BTP_GAP_SERVICE, BTP_OP_GAP_DISCONNECT,
 						btp_gap_disconnect, NULL, NULL);
+
+	btp_register(btp, BTP_GAP_SERVICE, BTP_OP_GAP_SET_IO_CAPA,
+				btp_gap_set_io_capabilities, NULL, NULL);
 }
 
 static void btp_core_read_commands(uint8_t index, const void *param,
@@ -1889,6 +2244,12 @@ static void proxy_added(struct l_dbus_proxy *proxy, void *user_data)
 
 		return;
 	}
+
+	if (!strcmp(interface, "org.bluez.AgentManager1")) {
+		ag.proxy = proxy;
+
+		return;
+	}
 }
 
 static bool device_match_by_proxy(const void *a, const void *b)
-- 
2.13.6


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

* [PATCH BlueZ 4/8] tools/btpclient: Restore default settings on reset
  2018-01-19 16:41 [PATCH BlueZ 1/8] tools/btpclient: Fix start adv commend comment Grzegorz Kolodziejczyk
  2018-01-19 16:41 ` [PATCH BlueZ 2/8] tools/btpclient: Initial check of ad_proxy presence in stop adv cmd Grzegorz Kolodziejczyk
  2018-01-19 16:41 ` [PATCH BlueZ 3/8] tools/btpclient: Add set io capabilities command Grzegorz Kolodziejczyk
@ 2018-01-19 16:41 ` Grzegorz Kolodziejczyk
  2018-01-23 13:48   ` Szymon Janc
  2018-01-19 16:41 ` [PATCH BlueZ 5/8] tools/btpclient: Cleanup advertising data " Grzegorz Kolodziejczyk
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Grzegorz Kolodziejczyk @ 2018-01-19 16:41 UTC (permalink / raw)
  To: linux-bluetooth

Reset command will restore default settings of adapter.
---
 tools/btpclient.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/tools/btpclient.c b/tools/btpclient.c
index 708092937..c5f88e673 100644
--- a/tools/btpclient.c
+++ b/tools/btpclient.c
@@ -56,6 +56,7 @@ struct btp_adapter {
 	uint8_t index;
 	uint32_t supported_settings;
 	uint32_t current_settings;
+	uint32_t default_settings;
 	struct l_queue *devices;
 };
 
@@ -538,6 +539,8 @@ static void btp_gap_reset(uint8_t index, const void *param, uint16_t length,
 			goto failed;
 		}
 
+	adapter->current_settings = adapter->default_settings;
+
 	/* TODO for we assume all went well */
 	btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_RESET, index, 0, NULL);
 	return;
@@ -2207,6 +2210,8 @@ static void proxy_added(struct l_dbus_proxy *proxy, void *user_data)
 		extract_settings(proxy, &adapter->current_settings,
 						&adapter->supported_settings);
 
+		adapter->default_settings = adapter->current_settings;
+
 		l_queue_push_tail(adapters, adapter);
 		return;
 	}
-- 
2.13.6


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

* [PATCH BlueZ 5/8] tools/btpclient: Cleanup advertising data on reset
  2018-01-19 16:41 [PATCH BlueZ 1/8] tools/btpclient: Fix start adv commend comment Grzegorz Kolodziejczyk
                   ` (2 preceding siblings ...)
  2018-01-19 16:41 ` [PATCH BlueZ 4/8] tools/btpclient: Restore default settings on reset Grzegorz Kolodziejczyk
@ 2018-01-19 16:41 ` Grzegorz Kolodziejczyk
  2018-01-19 16:41 ` [PATCH BlueZ 6/8] tools/btpclient: Add pair, unpair commands Grzegorz Kolodziejczyk
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 16+ messages in thread
From: Grzegorz Kolodziejczyk @ 2018-01-19 16:41 UTC (permalink / raw)
  To: linux-bluetooth

This patch adds advertising data cleanup routine to reset command if
registered.
---
 tools/btpclient.c | 71 ++++++++++++++++++++++++++++++-------------------------
 1 file changed, 39 insertions(+), 32 deletions(-)

diff --git a/tools/btpclient.c b/tools/btpclient.c
index c5f88e673..53c0d4c05 100644
--- a/tools/btpclient.c
+++ b/tools/btpclient.c
@@ -413,6 +413,37 @@ static void remove_device_reply(struct l_dbus_proxy *proxy,
 	l_queue_remove(adapter->devices, device);
 }
 
+static void update_current_settings(struct btp_adapter *adapter,
+							uint32_t new_settings)
+{
+	struct btp_new_settings_ev ev;
+
+	adapter->current_settings = new_settings;
+
+	ev.current_settings = L_CPU_TO_LE32(adapter->current_settings);
+
+	btp_send(btp, BTP_GAP_SERVICE, BTP_EV_GAP_NEW_SETTINGS, adapter->index,
+							sizeof(ev), &ev);
+}
+
+static void ad_cleanup_service(void *service)
+{
+	struct service_data *s = service;
+
+	l_free(s->uuid);
+	l_free(s);
+}
+
+static void ad_cleanup(void)
+{
+	l_free(ad.local_name);
+	l_queue_destroy(ad.uuids, l_free);
+	l_queue_destroy(ad.services, ad_cleanup_service);
+	l_queue_destroy(ad.manufacturers, l_free);
+
+	memset(&ad, 0, sizeof(ad));
+}
+
 static void unreg_advertising_setup(struct l_dbus_message *message,
 								void *user_data)
 {
@@ -430,6 +461,7 @@ static void unreg_advertising_reply(struct l_dbus_proxy *proxy,
 {
 	const char *path = l_dbus_proxy_get_path(proxy);
 	struct btp_adapter *adapter = find_adapter_by_path(path);
+	uint32_t new_settings;
 
 	if (!adapter)
 		return;
@@ -451,6 +483,12 @@ static void unreg_advertising_reply(struct l_dbus_proxy *proxy,
 		l_info("Unable to remove propety instance");
 	if (!l_dbus_unregister_interface(dbus, AD_IFACE))
 		l_info("Unable to unregister ad interface");
+
+	new_settings = adapter->current_settings;
+	new_settings &= ~BTP_GAP_SETTING_ADVERTISING;
+	update_current_settings(adapter, new_settings);
+
+	ad_cleanup();
 }
 
 static void unreg_agent_setup(struct l_dbus_message *message, void *user_data)
@@ -520,7 +558,7 @@ static void btp_gap_reset(uint8_t index, const void *param, uint16_t length,
 						NULL);
 	}
 
-	if (adapter->ad_proxy)
+	if (adapter->ad_proxy && ad.registered)
 		if (!l_dbus_proxy_method_call(adapter->ad_proxy,
 						"UnregisterAdvertisement",
 						unreg_advertising_setup,
@@ -613,19 +651,6 @@ failed:
 	btp_send_error(btp, BTP_GAP_SERVICE, index, status);
 }
 
-static void update_current_settings(struct btp_adapter *adapter,
-							uint32_t new_settings)
-{
-	struct btp_new_settings_ev ev;
-
-	adapter->current_settings = new_settings;
-
-	ev.current_settings = L_CPU_TO_LE32(adapter->current_settings);
-
-	btp_send(btp, BTP_GAP_SERVICE, BTP_EV_GAP_NEW_SETTINGS, adapter->index,
-							sizeof(ev), &ev);
-}
-
 static void btp_gap_set_connectable(uint8_t index, const void *param,
 					uint16_t length, void *user_data)
 {
@@ -726,24 +751,6 @@ failed:
 	btp_send_error(btp, BTP_GAP_SERVICE, index, status);
 }
 
-static void ad_cleanup_service(void *service)
-{
-	struct service_data *s = service;
-
-	l_free(s->uuid);
-	l_free(s);
-}
-
-static void ad_cleanup(void)
-{
-	l_free(ad.local_name);
-	l_queue_destroy(ad.uuids, l_free);
-	l_queue_destroy(ad.services, ad_cleanup_service);
-	l_queue_destroy(ad.manufacturers, l_free);
-
-	memset(&ad, 0, sizeof(ad));
-}
-
 static void ad_init(void)
 {
 	ad.uuids = l_queue_new();
-- 
2.13.6


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

* [PATCH BlueZ 6/8] tools/btpclient: Add pair, unpair commands
  2018-01-19 16:41 [PATCH BlueZ 1/8] tools/btpclient: Fix start adv commend comment Grzegorz Kolodziejczyk
                   ` (3 preceding siblings ...)
  2018-01-19 16:41 ` [PATCH BlueZ 5/8] tools/btpclient: Cleanup advertising data " Grzegorz Kolodziejczyk
@ 2018-01-19 16:41 ` Grzegorz Kolodziejczyk
  2018-01-23 13:53   ` Szymon Janc
  2018-01-19 16:41 ` [PATCH BlueZ 7/8] tools/btpclient: Add passkey entry cmd and passkey display event Grzegorz Kolodziejczyk
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Grzegorz Kolodziejczyk @ 2018-01-19 16:41 UTC (permalink / raw)
  To: linux-bluetooth

This patch adds pair and unpair commands for btp client.
---
 tools/btpclient.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 124 insertions(+)

diff --git a/tools/btpclient.c b/tools/btpclient.c
index 53c0d4c05..9d44fba41 100644
--- a/tools/btpclient.c
+++ b/tools/btpclient.c
@@ -304,6 +304,8 @@ static void btp_gap_read_commands(uint8_t index, const void *param,
 	commands |= (1 << BTP_OP_GAP_CONNECT);
 	commands |= (1 << BTP_OP_GAP_DISCONNECT);
 	commands |= (1 << BTP_OP_GAP_SET_IO_CAPA);
+	commands |= (1 << BTP_OP_GAP_PAIR);
+	commands |= (1 << BTP_OP_GAP_UNPAIR);
 
 	commands = L_CPU_TO_LE16(commands);
 
@@ -1875,6 +1877,122 @@ failed:
 	btp_send_error(btp, BTP_GAP_SERVICE, index, status);
 }
 
+static void pair_reply(struct l_dbus_proxy *proxy,
+				struct l_dbus_message *result, void *user_data)
+{
+	uint8_t adapter_index = L_PTR_TO_UINT(user_data);
+	struct btp_adapter *adapter = find_adapter_by_index(adapter_index);
+
+	if (!adapter)
+		return;
+
+	if (l_dbus_message_is_error(result)) {
+		const char *name, *desc;
+
+		l_dbus_message_get_error(result, &name, &desc);
+		l_error("Failed to pair (%s), %s", name, desc);
+
+		return;
+	}
+}
+
+static void btp_gap_pair(uint8_t index, const void *param, uint16_t length,
+								void *user_data)
+{
+	struct btp_adapter *adapter = find_adapter_by_index(index);
+	const struct btp_gap_pair_cp *cp = param;
+	uint8_t status = BTP_ERROR_FAIL;
+	struct btp_device *device;
+	bool prop;
+
+	if (!adapter) {
+		status = BTP_ERROR_INVALID_INDEX;
+		goto failed;
+	}
+
+	/* Adapter needs to be powered to be able to pair */
+	if (!l_dbus_proxy_get_property(adapter->proxy, "Powered", "b", &prop) ||
+									!prop)
+		goto failed;
+
+	device = find_device_by_address(adapter, &cp->address,
+							cp->address_type);
+
+	if (!device)
+		goto failed;
+
+	btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_PAIR, adapter->index, 0,
+									NULL);
+
+	l_dbus_proxy_method_call(device->proxy, "Pair", NULL, pair_reply,
+					L_UINT_TO_PTR(adapter->index), NULL);
+
+	return;
+
+failed:
+	btp_send_error(btp, BTP_GAP_SERVICE, index, status);
+}
+
+static void unpair_reply(struct l_dbus_proxy *proxy,
+				struct l_dbus_message *result, void *user_data)
+{
+	uint8_t adapter_index = L_PTR_TO_UINT(user_data);
+	struct btp_adapter *adapter = find_adapter_by_index(adapter_index);
+
+	if (!adapter) {
+		btp_send_error(btp, BTP_GAP_SERVICE, BTP_INDEX_NON_CONTROLLER,
+								BTP_ERROR_FAIL);
+		return;
+	}
+
+	if (l_dbus_message_is_error(result)) {
+		const char *name, *desc;
+
+		l_dbus_message_get_error(result, &name, &desc);
+		l_error("Failed to unpair (%s), %s", name, desc);
+
+		btp_send_error(btp, BTP_GAP_SERVICE, adapter_index,
+								BTP_ERROR_FAIL);
+		return;
+	}
+
+	btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_UNPAIR, adapter_index, 0, NULL);
+}
+
+static void btp_gap_unpair(uint8_t index, const void *param, uint16_t length,
+								void *user_data)
+{
+	struct btp_adapter *adapter = find_adapter_by_index(index);
+	const struct btp_gap_pair_cp *cp = param;
+	uint8_t status = BTP_ERROR_FAIL;
+	struct btp_device *device;
+	bool prop;
+
+	if (!adapter) {
+		status = BTP_ERROR_INVALID_INDEX;
+		goto failed;
+	}
+
+	/* Adapter needs to be powered to be able to unpair */
+	if (!l_dbus_proxy_get_property(adapter->proxy, "Powered", "b", &prop) ||
+									!prop)
+		goto failed;
+
+	device = find_device_by_address(adapter, &cp->address,
+							cp->address_type);
+
+	if (!device)
+		goto failed;
+
+	l_dbus_proxy_method_call(device->proxy, "Unpair", NULL, unpair_reply,
+					L_UINT_TO_PTR(adapter->index), NULL);
+
+	return;
+
+failed:
+	btp_send_error(btp, BTP_GAP_SERVICE, index, status);
+}
+
 static void btp_gap_device_found_ev(struct l_dbus_proxy *proxy)
 {
 	struct btp_device_found_ev ev;
@@ -1999,6 +2117,12 @@ static void register_gap_service(void)
 
 	btp_register(btp, BTP_GAP_SERVICE, BTP_OP_GAP_SET_IO_CAPA,
 				btp_gap_set_io_capabilities, NULL, NULL);
+
+	btp_register(btp, BTP_GAP_SERVICE, BTP_OP_GAP_PAIR, btp_gap_pair, NULL,
+									NULL);
+
+	btp_register(btp, BTP_GAP_SERVICE, BTP_OP_GAP_UNPAIR, btp_gap_unpair,
+								NULL, NULL);
 }
 
 static void btp_core_read_commands(uint8_t index, const void *param,
-- 
2.13.6


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

* [PATCH BlueZ 7/8] tools/btpclient: Add passkey entry cmd and passkey display event
  2018-01-19 16:41 [PATCH BlueZ 1/8] tools/btpclient: Fix start adv commend comment Grzegorz Kolodziejczyk
                   ` (4 preceding siblings ...)
  2018-01-19 16:41 ` [PATCH BlueZ 6/8] tools/btpclient: Add pair, unpair commands Grzegorz Kolodziejczyk
@ 2018-01-19 16:41 ` Grzegorz Kolodziejczyk
  2018-01-19 16:41 ` [PATCH BlueZ 8/8] tools/btpclient: Add passkey confirm ev and passkey confirm rsp cmd Grzegorz Kolodziejczyk
  2018-01-23 13:44 ` [PATCH BlueZ 1/8] tools/btpclient: Fix start adv commend comment Szymon Janc
  7 siblings, 0 replies; 16+ messages in thread
From: Grzegorz Kolodziejczyk @ 2018-01-19 16:41 UTC (permalink / raw)
  To: linux-bluetooth

This patch adds passkey entry command handler and passkey display event.
---
 tools/btpclient.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 92 insertions(+)

diff --git a/tools/btpclient.c b/tools/btpclient.c
index 9d44fba41..55e5170a7 100644
--- a/tools/btpclient.c
+++ b/tools/btpclient.c
@@ -1658,11 +1658,44 @@ static struct l_dbus_message *ag_display_passkey_call(struct l_dbus *dbus,
 						struct l_dbus_message *message,
 						void *user_data)
 {
+	struct btp_gap_passkey_display_ev ev;
+	struct btp_device *device;
+	struct btp_adapter *adapter;
 	struct l_dbus_message *reply;
+	const char *path, *str_addr, *str_addr_type;
+	uint32_t passkey;
+	uint16_t entered;
 
 	reply = l_dbus_message_new_method_return(message);
 	l_dbus_message_set_arguments(reply, "");
 
+	l_dbus_message_get_arguments(message, "ouq", &path, &passkey, &entered);
+
+	device = find_device_by_path(path);
+
+	if (!l_dbus_proxy_get_property(device->proxy, "Address", "s", &str_addr)
+		|| !l_dbus_proxy_get_property(device->proxy, "AddressType", "s",
+		&str_addr_type)) {
+		l_info("Cannot get device properties");
+
+		return reply;
+	}
+
+	ev.passkey = L_CPU_TO_LE32(passkey);
+	ev.address_type = strcmp(str_addr_type, "public") ?
+							BTP_GAP_ADDR_RANDOM :
+							BTP_GAP_ADDR_PUBLIC;
+	if (str2ba(str_addr, &ev.address) < 0) {
+		l_info("Incorrect device addres");
+
+		return reply;
+	}
+
+	adapter = find_adapter_by_device(device);
+
+	btp_send(btp, BTP_GAP_SERVICE, BTP_EV_GAP_PASSKEY_DISPLAY,
+					adapter->index, sizeof(ev), &ev);
+
 	return reply;
 }
 
@@ -1993,6 +2026,62 @@ failed:
 	btp_send_error(btp, BTP_GAP_SERVICE, index, status);
 }
 
+static void passkey_entry_rsp_reply(struct l_dbus_message *result,
+								void *user_data)
+{
+	struct btp_adapter *adapter = user_data;
+
+	if (l_dbus_message_is_error(result)) {
+		const char *name, *desc;
+
+		l_dbus_message_get_error(result, &name, &desc);
+		l_error("Failed to reply with passkey (%s), %s", name, desc);
+
+		btp_send_error(btp, BTP_GAP_SERVICE, adapter->index,
+								BTP_ERROR_FAIL);
+		return;
+	}
+
+	l_dbus_message_unref(ag.pending_req);
+
+	btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_PASSKEY_ENTRY_RSP,
+						adapter->index, 0, NULL);
+}
+
+static void btp_gap_passkey_entry_rsp(uint8_t index, const void *param,
+					uint16_t length, void *user_data)
+{
+	const struct btp_gap_passkey_entry_rsp_cp *cp = param;
+	struct btp_adapter *adapter = find_adapter_by_index(index);
+	struct l_dbus_message_builder *builder;
+	uint8_t status = BTP_ERROR_FAIL;
+	uint32_t passkey = L_CPU_TO_LE32(cp->passkey);
+	bool prop;
+
+	if (!adapter) {
+		status = BTP_ERROR_INVALID_INDEX;
+		goto failed;
+	}
+
+	/* Adapter needs to be powered to be able to response with passkey */
+	if (!l_dbus_proxy_get_property(adapter->proxy, "Powered", "b", &prop) ||
+						!prop || !ag.pending_req)
+		goto failed;
+
+	builder = l_dbus_message_builder_new(ag.pending_req);
+	l_dbus_message_builder_append_basic(builder, 'u', &passkey);
+	l_dbus_message_builder_finalize(builder);
+	l_dbus_message_builder_destroy(builder);
+
+	l_dbus_send_with_reply(dbus, ag.pending_req, passkey_entry_rsp_reply,
+								adapter, NULL);
+
+	return;
+
+failed:
+	btp_send_error(btp, BTP_GAP_SERVICE, index, status);
+}
+
 static void btp_gap_device_found_ev(struct l_dbus_proxy *proxy)
 {
 	struct btp_device_found_ev ev;
@@ -2123,6 +2212,9 @@ static void register_gap_service(void)
 
 	btp_register(btp, BTP_GAP_SERVICE, BTP_OP_GAP_UNPAIR, btp_gap_unpair,
 								NULL, NULL);
+
+	btp_register(btp, BTP_GAP_SERVICE, BTP_OP_GAP_PASSKEY_ENTRY_RSP,
+					btp_gap_passkey_entry_rsp, NULL, NULL);
 }
 
 static void btp_core_read_commands(uint8_t index, const void *param,
-- 
2.13.6


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

* [PATCH BlueZ 8/8] tools/btpclient: Add passkey confirm ev and passkey confirm rsp cmd
  2018-01-19 16:41 [PATCH BlueZ 1/8] tools/btpclient: Fix start adv commend comment Grzegorz Kolodziejczyk
                   ` (5 preceding siblings ...)
  2018-01-19 16:41 ` [PATCH BlueZ 7/8] tools/btpclient: Add passkey entry cmd and passkey display event Grzegorz Kolodziejczyk
@ 2018-01-19 16:41 ` Grzegorz Kolodziejczyk
  2018-01-23 14:03   ` Szymon Janc
  2018-01-23 13:44 ` [PATCH BlueZ 1/8] tools/btpclient: Fix start adv commend comment Szymon Janc
  7 siblings, 1 reply; 16+ messages in thread
From: Grzegorz Kolodziejczyk @ 2018-01-19 16:41 UTC (permalink / raw)
  To: linux-bluetooth

This patch adds passkey confirm command handler and passkey confirm
event.
---
 tools/btpclient.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 94 insertions(+)

diff --git a/tools/btpclient.c b/tools/btpclient.c
index 55e5170a7..780c2a8db 100644
--- a/tools/btpclient.c
+++ b/tools/btpclient.c
@@ -1703,11 +1703,43 @@ static struct l_dbus_message *ag_request_confirmation_call(struct l_dbus *dbus,
 						struct l_dbus_message *message,
 						void *user_data)
 {
+	struct btp_gap_passkey_confirm_ev ev;
+	struct btp_device *device;
+	struct btp_adapter *adapter;
 	struct l_dbus_message *reply;
+	const char *path, *str_addr, *str_addr_type;
+	uint32_t passkey;
 
 	reply = l_dbus_message_new_method_return(message);
 	l_dbus_message_set_arguments(reply, "");
 
+	l_dbus_message_get_arguments(message, "ou", &path, &passkey);
+
+	device = find_device_by_path(path);
+
+	if (!l_dbus_proxy_get_property(device->proxy, "Address", "s", &str_addr)
+		|| !l_dbus_proxy_get_property(device->proxy, "AddressType", "s",
+		&str_addr_type)) {
+		l_info("Cannot get device properties");
+
+		return reply;
+	}
+
+	ev.passkey = L_CPU_TO_LE32(passkey);
+	ev.address_type = strcmp(str_addr_type, "public") ?
+							BTP_GAP_ADDR_RANDOM :
+							BTP_GAP_ADDR_PUBLIC;
+	if (str2ba(str_addr, &ev.address) < 0) {
+		l_info("Incorrect device address");
+
+		return reply;
+	}
+
+	adapter = find_adapter_by_device(device);
+
+	btp_send(btp, BTP_GAP_SERVICE, BTP_EV_GAP_PASSKEY_CONFIRM,
+					adapter->index, sizeof(ev), &ev);
+
 	return reply;
 }
 
@@ -2082,6 +2114,65 @@ failed:
 	btp_send_error(btp, BTP_GAP_SERVICE, index, status);
 }
 
+static void passkey_confirm_rsp_reply(struct l_dbus_message *result,
+								void *user_data)
+{
+	struct btp_adapter *adapter = user_data;
+
+	if (l_dbus_message_is_error(result)) {
+		const char *name, *desc;
+
+		l_dbus_message_get_error(result, &name, &desc);
+		l_error("Failed to confirm passkey (%s), %s", name, desc);
+
+		btp_send_error(btp, BTP_GAP_SERVICE, adapter->index,
+								BTP_ERROR_FAIL);
+		return;
+	}
+
+	l_dbus_message_unref(ag.pending_req);
+
+	btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_PASSKEY_CONFIRM_RSP,
+						adapter->index, 0, NULL);
+}
+
+static void btp_gap_confirm_entry_rsp(uint8_t index, const void *param,
+					uint16_t length, void *user_data)
+{
+	const struct btp_gap_passkey_confirm_rsp_cp *cp = param;
+	struct btp_adapter *adapter = find_adapter_by_index(index);
+	struct l_dbus_message *reply;
+	uint8_t status = BTP_ERROR_FAIL;
+	bool prop;
+
+	if (!adapter) {
+		status = BTP_ERROR_INVALID_INDEX;
+		goto failed;
+	}
+
+	/* Adapter needs to be powered to be able to confirm passkey */
+	if (!l_dbus_proxy_get_property(adapter->proxy, "Powered", "b", &prop) ||
+						!prop || !ag.pending_req)
+		goto failed;
+
+	if (cp->match) {
+		reply = l_dbus_message_new_method_return(ag.pending_req);
+		l_dbus_message_set_arguments(reply, "");
+	} else {
+		reply = l_dbus_message_new_error(ag.pending_req,
+						"org.bluez.Error.Rejected",
+						"Passkey missmatch");
+	}
+
+	l_dbus_send_with_reply(dbus, ag.pending_req, passkey_confirm_rsp_reply,
+								adapter, NULL);
+
+	return;
+
+failed:
+	btp_send_error(btp, BTP_GAP_SERVICE, index, status);
+}
+
 static void btp_gap_device_found_ev(struct l_dbus_proxy *proxy)
 {
 	struct btp_device_found_ev ev;
@@ -2215,6 +2306,9 @@ static void register_gap_service(void)
 
 	btp_register(btp, BTP_GAP_SERVICE, BTP_OP_GAP_PASSKEY_ENTRY_RSP,
 					btp_gap_passkey_entry_rsp, NULL, NULL);
+
+	btp_register(btp, BTP_GAP_SERVICE, BTP_OP_GAP_PASSKEY_CONFIRM_RSP,
+					btp_gap_confirm_entry_rsp, NULL, NULL);
 }
 
 static void btp_core_read_commands(uint8_t index, const void *param,
-- 
2.13.6


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

* Re: [PATCH BlueZ 1/8] tools/btpclient: Fix start adv commend comment
  2018-01-19 16:41 [PATCH BlueZ 1/8] tools/btpclient: Fix start adv commend comment Grzegorz Kolodziejczyk
                   ` (6 preceding siblings ...)
  2018-01-19 16:41 ` [PATCH BlueZ 8/8] tools/btpclient: Add passkey confirm ev and passkey confirm rsp cmd Grzegorz Kolodziejczyk
@ 2018-01-23 13:44 ` Szymon Janc
  7 siblings, 0 replies; 16+ messages in thread
From: Szymon Janc @ 2018-01-23 13:44 UTC (permalink / raw)
  To: Grzegorz Kolodziejczyk; +Cc: linux-bluetooth

Hi Grzegorz,

On Friday, 19 January 2018 17:41:26 CET Grzegorz Kolodziejczyk wrote:
> Comment should be aproperiate for advertising command. Device needs to
> be powered to advertise.
> ---
>  tools/btpclient.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/tools/btpclient.c b/tools/btpclient.c
> index af0e75290..33116ce1b 100644
> --- a/tools/btpclient.c
> +++ b/tools/btpclient.c
> @@ -1038,7 +1038,7 @@ static void btp_gap_start_advertising(uint8_t index,
> const void *param, goto failed;
>  	}
> 
> -	/* Adapter needs to be powered to be able to remove devices */
> +	/* Adapter needs to be powered to be able to advertise */
>  	if (!l_dbus_proxy_get_property(adapter->proxy, "Powered", "b", &prop) ||
>  							!prop || ad.registered)
>  		goto failed;

Patches 1 and 2 are now applied. Thanks.

-- 
pozdrawiam
Szymon Janc



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

* Re: [PATCH BlueZ 3/8] tools/btpclient: Add set io capabilities command
  2018-01-19 16:41 ` [PATCH BlueZ 3/8] tools/btpclient: Add set io capabilities command Grzegorz Kolodziejczyk
@ 2018-01-23 13:48   ` Szymon Janc
  2018-01-23 15:06     ` Grzegorz Kołodziejczyk
  0 siblings, 1 reply; 16+ messages in thread
From: Szymon Janc @ 2018-01-23 13:48 UTC (permalink / raw)
  To: Grzegorz Kolodziejczyk; +Cc: linux-bluetooth

Hi Grzegorz,

On Friday, 19 January 2018 17:41:28 CET Grzegorz Kolodziejczyk wrote:
> This patch adds support for set io capabilities command.
> ---
>  tools/btpclient.c | 361
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 361
> insertions(+)
> 
> diff --git a/tools/btpclient.c b/tools/btpclient.c
> index f2c79b3a3..708092937 100644
> --- a/tools/btpclient.c
> +++ b/tools/btpclient.c
> @@ -36,7 +36,9 @@
>  #include "src/shared/btp.h"
> 
>  #define AD_PATH "/org/bluez/advertising"
> +#define AG_PATH "/org/bluez/agent"
>  #define AD_IFACE "org.bluez.LEAdvertisement1"
> +#define AG_IFACE "org.bluez.Agent1"
> 
>  /* List of assigned numbers for advetising data and scan response */
>  #define AD_TYPE_FLAGS				0x01
> @@ -97,6 +99,12 @@ static struct ad {
>  	bool appearance;
>  } ad;
> 
> +static struct btp_agent {
> +	bool registered;
> +	struct l_dbus_proxy *proxy;
> +	struct l_dbus_message *pending_req;
> +} ag;
> +
>  static char *dupuuid2str(const uint8_t *uuid, uint8_t len)
>  {
>  	switch (len) {
> @@ -198,6 +206,31 @@ static struct btp_device *find_device_by_address(struct
> btp_adapter *adapter, return NULL;
>  }
> 
> +static bool match_device_paths(const void *device, const void *path)
> +{
> +	const struct btp_device *dev = device;
> +
> +	return !strcmp(l_dbus_proxy_get_path(dev->proxy), path);
> +}
> +
> +static struct btp_device *find_device_by_path(const char *path)
> +{
> +	const struct l_queue_entry *entry;
> +	struct btp_device *device;
> +
> +	for (entry = l_queue_get_entries(adapters); entry;
> +							entry = entry->next) {
> +		struct btp_adapter *adapter = entry->data;
> +
> +		device = l_queue_find(adapter->devices, match_device_paths,
> +									path);
> +		if (device)
> +			return device;
> +	}
> +
> +	return NULL;
> +}
> +
>  static bool match_adapter_dev_proxy(const void *device, const void *proxy)
>  {
>  	const struct btp_device *d = device;
> @@ -269,6 +302,7 @@ static void btp_gap_read_commands(uint8_t index, const
> void *param, commands |= (1 << BTP_OP_GAP_STOP_DISCOVERY);
>  	commands |= (1 << BTP_OP_GAP_CONNECT);
>  	commands |= (1 << BTP_OP_GAP_DISCONNECT);
> +	commands |= (1 << BTP_OP_GAP_SET_IO_CAPA);
> 
>  	commands = L_CPU_TO_LE16(commands);
> 
> @@ -418,6 +452,43 @@ static void unreg_advertising_reply(struct l_dbus_proxy
> *proxy, l_info("Unable to unregister ad interface");
>  }
> 
> +static void unreg_agent_setup(struct l_dbus_message *message, void
> *user_data) +{
> +	struct l_dbus_message_builder *builder;
> +
> +	builder = l_dbus_message_builder_new(message);
> +
> +	l_dbus_message_builder_append_basic(builder, 'o', AG_PATH);
> +
> +	l_dbus_message_builder_finalize(builder);
> +	l_dbus_message_builder_destroy(builder);
> +}
> +
> +static void unreg_agent_reply(struct l_dbus_proxy *proxy,
> +						struct l_dbus_message *result,
> +						void *user_data)
> +{
> +	if (l_dbus_message_is_error(result)) {
> +		const char *name;
> +
> +		l_dbus_message_get_error(result, &name, NULL);
> +
> +		l_error("Failed to unregister agent %s (%s)",
> +					l_dbus_proxy_get_path(proxy), name);
> +		return;
> +	}
> +
> +	if (!l_dbus_object_remove_interface(dbus, AG_PATH,
> +						L_DBUS_INTERFACE_PROPERTIES))
> +		l_info("Unable to remove propety instance");
> +	if (!l_dbus_object_remove_interface(dbus, AG_PATH, AG_IFACE))
> +		l_info("Unable to remove agent instance");
> +	if (!l_dbus_unregister_interface(dbus, AG_IFACE))
> +		l_info("Unable to unregister agent interface");
> +
> +	ag.registered = false;
> +}
> +
>  static void btp_gap_reset(uint8_t index, const void *param, uint16_t
> length, void *user_data)
>  {
> @@ -458,6 +529,15 @@ static void btp_gap_reset(uint8_t index, const void
> *param, uint16_t length, goto failed;
>  		}
> 
> +	if (ag.registered)
> +		if (!l_dbus_proxy_method_call(ag.proxy, "UnregisterAgent",
> +							unreg_agent_setup,
> +							unreg_agent_reply,
> +							NULL, NULL)) {
> +			status = BTP_ERROR_FAIL;
> +			goto failed;
> +		}
> +
>  	/* TODO for we assume all went well */
>  	btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_RESET, index, 0, NULL);
>  	return;
> @@ -1513,6 +1593,278 @@ failed:
>  	btp_send_error(btp, BTP_GAP_SERVICE, index, status);
>  }
> 
> +static struct l_dbus_message *ag_release_call(struct l_dbus *dbus,
> +						struct l_dbus_message *message,
> +						void *user_data)
> +{
> +	struct l_dbus_message *reply;
> +
> +	reply = l_dbus_message_new_method_return(message);
> +	l_dbus_message_set_arguments(reply, "");
> +
> +	return reply;
> +}
> +
> +static struct l_dbus_message *ag_request_passkey_call(struct l_dbus *dbus,
> +						struct l_dbus_message *message,
> +						void *user_data)
> +{
> +	struct btp_gap_passkey_req_ev ev;
> +	struct btp_device *device;
> +	struct btp_adapter *adapter;
> +	const char *path, *str_addr, *str_addr_type;
> +
> +	l_dbus_message_get_arguments(message, "o", &path);
> +
> +	device = find_device_by_path(path);
> +
> +	if (!l_dbus_proxy_get_property(device->proxy, "Address", "s", &str_addr)
> +		|| !l_dbus_proxy_get_property(device->proxy, "AddressType", "s",
> +		&str_addr_type)) {
> +		l_info("Cannot get device properties");
> +
> +		return NULL;
> +	}
> +
> +	ev.address_type = strcmp(str_addr_type, "public") ?
> +							BTP_GAP_ADDR_RANDOM :
> +							BTP_GAP_ADDR_PUBLIC;
> +	if (!str2ba(str_addr, &ev.address))
> +		return NULL;
> +
> +	adapter = find_adapter_by_device(device);
> +
> +	ag.pending_req = l_dbus_message_ref(message);
> +
> +	btp_send(btp, BTP_GAP_SERVICE, BTP_EV_GAP_PASSKEY_REQUEST,
> +					adapter->index, sizeof(ev), &ev);
> +
> +	return NULL;
> +}
> +
> +static struct l_dbus_message *ag_display_passkey_call(struct l_dbus *dbus,
> +						struct l_dbus_message *message,
> +						void *user_data)
> +{
> +	struct l_dbus_message *reply;
> +
> +	reply = l_dbus_message_new_method_return(message);
> +	l_dbus_message_set_arguments(reply, "");
> +
> +	return reply;
> +}
> +
> +static struct l_dbus_message *ag_request_confirmation_call(struct l_dbus
> *dbus, +						struct l_dbus_message *message,
> +						void *user_data)
> +{
> +	struct l_dbus_message *reply;
> +
> +	reply = l_dbus_message_new_method_return(message);
> +	l_dbus_message_set_arguments(reply, "");
> +
> +	return reply;
> +}
> +
> +static struct l_dbus_message *ag_authorize_service_call(struct l_dbus
> *dbus, +						struct l_dbus_message *message,
> +						void *user_data)
> +{
> +	struct l_dbus_message *reply;
> +
> +	reply = l_dbus_message_new_method_return(message);
> +	l_dbus_message_set_arguments(reply, "");
> +
> +	return reply;
> +}
> +
> +static struct l_dbus_message *ag_cancel_call(struct l_dbus *dbus,
> +						struct l_dbus_message *message,
> +						void *user_data)
> +{
> +	struct l_dbus_message *reply;
> +
> +	reply = l_dbus_message_new_method_return(message);
> +	l_dbus_message_set_arguments(reply, "");
> +
> +	return reply;
> +}
> +
> +static void setup_ag_interface(struct l_dbus_interface *iface)
> +{
> +	l_dbus_interface_method(iface, "Release", 0, ag_release_call, "", "");
> +	l_dbus_interface_method(iface, "RequestPasskey", 0,
> +					ag_request_passkey_call, "u", "o",
> +					"passkey", "device");
> +	l_dbus_interface_method(iface, "DisplayPasskey", 0,
> +					ag_display_passkey_call, "", "ouq",
> +					"device", "passkey", "entered");
> +	l_dbus_interface_method(iface, "RequestConfirmation", 0,
> +					ag_request_confirmation_call, "", "ou",
> +					"device", "passkey");
> +	l_dbus_interface_method(iface, "RequestAuthorization", 0,
> +					ag_request_confirmation_call, "", "o",
> +					"device");
> +	l_dbus_interface_method(iface, "AuthorizeService", 0,
> +					ag_authorize_service_call, "", "os",
> +					"device", "uuid");
> +	l_dbus_interface_method(iface, "Cancel", 0, ag_cancel_call, "", "");
> +}
> +
> +struct set_io_capabilities_data {
> +	uint8_t capa;
> +	struct btp_adapter *adapter;
> +};
> +
> +static void set_io_capabilities_setup(struct l_dbus_message *message,
> +								void *user_data)
> +{
> +	struct set_io_capabilities_data *sicd = user_data;
> +	struct l_dbus_message_builder *builder;
> +	char *capa_str;
> +
> +	builder = l_dbus_message_builder_new(message);
> +
> +	l_dbus_message_builder_append_basic(builder, 'o', AG_PATH);
> +
> +	switch (sicd->capa) {
> +	case BTP_GAP_IOCAPA_DISPLAY_ONLY:
> +		capa_str = "DisplayOnly";
> +		break;
> +	case BTP_GAP_IOCAPA_DISPLAY_YESNO:
> +		capa_str = "DisplayYesNo";
> +		break;
> +	case BTP_GAP_IOCAPA_KEYBOARD_ONLY:
> +		capa_str = "KeyboardOnly";
> +		break;
> +	case BTP_GAP_IOCAPA_NO_INPUT_NO_OUTPUT:
> +		capa_str = "NoInputNoOutput";
> +		break;
> +	case BTP_GAP_IOCAPA_KEYBOARD_DISPLAY:
> +		capa_str = "KeyboardDisplay";
> +		break;
> +	default:
> +		l_error("Wrong iocapa given!");
> +		l_dbus_message_builder_finalize(builder);
> +		l_dbus_message_builder_destroy(builder);
> +
> +		return;
> +	}

setup callback should only build message, not verify parameters as it returns 
void. Please check those in btp_gap_set_io_capabilities().

> +
> +	l_dbus_message_builder_append_basic(builder, 's', capa_str);
> +
> +	l_dbus_message_builder_finalize(builder);
> +	l_dbus_message_builder_destroy(builder);
> +}
> +
> +static void set_io_capabilities_reply(struct l_dbus_proxy *proxy,
> +						struct l_dbus_message *result,
> +						void *user_data)
> +{
> +	struct set_io_capabilities_data *sicd = user_data;
> +
> +	if (!sicd->adapter) {
> +		btp_send_error(btp, BTP_GAP_SERVICE, BTP_INDEX_NON_CONTROLLER,
> +								BTP_ERROR_FAIL);
> +		return;
> +	}
> +
> +	if (l_dbus_message_is_error(result)) {
> +		const char *name, *desc;
> +
> +		if (!l_dbus_object_remove_interface(dbus, AG_PATH, AG_IFACE))
> +			l_info("Unable to remove agent instance");
> +		if (!l_dbus_unregister_interface(dbus, AG_IFACE))
> +			l_info("Unable to unregister agent interface");
> +
> +		l_dbus_message_get_error(result, &name, &desc);
> +		l_error("Failed to set io capabilities (%s), %s", name, desc);
> +
> +		btp_send_error(btp, BTP_GAP_SERVICE, sicd->adapter->index,
> +								BTP_ERROR_FAIL);
> +		return;
> +	}
> +
> +	ag.registered = true;
> +
> +	btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_SET_IO_CAPA,
> +						sicd->adapter->index, 0, NULL);
> +}
> +
> +static void set_io_capabilities_destroy(void *user_data)
> +{
> +	l_free(user_data);
> +}
> +
> +static void btp_gap_set_io_capabilities(uint8_t index, const void *param,
> +					uint16_t length, void *user_data)
> +{
> +	struct btp_adapter *adapter = find_adapter_by_index(index);
> +	const struct btp_gap_set_io_capa_cp *cp = param;
> +	uint8_t status = BTP_ERROR_FAIL;
> +	struct set_io_capabilities_data *data;
> +	bool prop;
> +
> +	if (!adapter) {
> +		status = BTP_ERROR_INVALID_INDEX;
> +		goto failed;
> +	}
> +
> +	/* Adapter needs to be powered to be able to set io cap */
> +	if (!l_dbus_proxy_get_property(adapter->proxy, "Powered", "b", &prop) ||
> +							!prop || ag.registered)
> +		goto failed;
> +
> +	if (!l_dbus_register_interface(dbus, AG_IFACE, setup_ag_interface, NULL,
> +								false)) {
> +		l_info("Unable to register agent interface");
> +		goto failed;
> +	}
> +
> +	if (!l_dbus_object_add_interface(dbus, AG_PATH, AG_IFACE, NULL)) {
> +		l_info("Unable to instantiate agent interface");
> +
> +		if (!l_dbus_unregister_interface(dbus, AD_IFACE))
> +			l_info("Unable to unregister agent interface");
> +
> +		goto failed;
> +	}
> +
> +	if (!l_dbus_object_add_interface(dbus, AG_PATH,
> +						L_DBUS_INTERFACE_PROPERTIES,
> +						NULL)) {
> +		l_info("Unable to instantiate the ag properties interface");
> +
> +		if (!l_dbus_object_remove_interface(dbus, AG_PATH, AG_IFACE))
> +			l_info("Unable to remove agent instance");
> +		if (!l_dbus_unregister_interface(dbus, AG_IFACE))
> +			l_info("Unable to unregister agent interface");
> +
> +		goto failed;
> +	}
> +
> +	data = l_new(struct set_io_capabilities_data, 1);
> +	data->adapter = adapter;
> +	data->capa = cp->capa;
> +
> +	if (!l_dbus_proxy_method_call(ag.proxy, "RegisterAgent",
> +						set_io_capabilities_setup,
> +						set_io_capabilities_reply, data,
> +						set_io_capabilities_destroy)) {
> +		if (!l_dbus_object_remove_interface(dbus, AG_PATH, AG_IFACE))
> +			l_info("Unable to remove agent instance");
> +		if (!l_dbus_unregister_interface(dbus, AG_IFACE))
> +			l_info("Unable to unregister agent interface");
> +
> +		goto failed;
> +	}
> +
> +	return;
> +
> +failed:
> +	btp_send_error(btp, BTP_GAP_SERVICE, index, status);
> +}
> +
>  static void btp_gap_device_found_ev(struct l_dbus_proxy *proxy)
>  {
>  	struct btp_device_found_ev ev;
> @@ -1634,6 +1986,9 @@ static void register_gap_service(void)
> 
>  	btp_register(btp, BTP_GAP_SERVICE, BTP_OP_GAP_DISCONNECT,
>  						btp_gap_disconnect, NULL, NULL);
> +
> +	btp_register(btp, BTP_GAP_SERVICE, BTP_OP_GAP_SET_IO_CAPA,
> +				btp_gap_set_io_capabilities, NULL, NULL);
>  }
> 
>  static void btp_core_read_commands(uint8_t index, const void *param,
> @@ -1889,6 +2244,12 @@ static void proxy_added(struct l_dbus_proxy *proxy,
> void *user_data)
> 
>  		return;
>  	}
> +
> +	if (!strcmp(interface, "org.bluez.AgentManager1")) {
> +		ag.proxy = proxy;
> +
> +		return;
> +	}
>  }
> 
>  static bool device_match_by_proxy(const void *a, const void *b)

More general comment. We should register default agent on startup so that 
system agent is never used when btpclient is running. When this command is 
called and iocapa is differrent than currently used we should unregister 
current agent and register new default.


-- 
pozdrawiam
Szymon Janc



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

* Re: [PATCH BlueZ 4/8] tools/btpclient: Restore default settings on reset
  2018-01-19 16:41 ` [PATCH BlueZ 4/8] tools/btpclient: Restore default settings on reset Grzegorz Kolodziejczyk
@ 2018-01-23 13:48   ` Szymon Janc
  0 siblings, 0 replies; 16+ messages in thread
From: Szymon Janc @ 2018-01-23 13:48 UTC (permalink / raw)
  To: Grzegorz Kolodziejczyk; +Cc: linux-bluetooth

Hi Grzegorz,

On Friday, 19 January 2018 17:41:29 CET Grzegorz Kolodziejczyk wrote:
> Reset command will restore default settings of adapter.
> ---
>  tools/btpclient.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/tools/btpclient.c b/tools/btpclient.c
> index 708092937..c5f88e673 100644
> --- a/tools/btpclient.c
> +++ b/tools/btpclient.c
> @@ -56,6 +56,7 @@ struct btp_adapter {
>  	uint8_t index;
>  	uint32_t supported_settings;
>  	uint32_t current_settings;
> +	uint32_t default_settings;
>  	struct l_queue *devices;
>  };
> 
> @@ -538,6 +539,8 @@ static void btp_gap_reset(uint8_t index, const void
> *param, uint16_t length, goto failed;
>  		}
> 
> +	adapter->current_settings = adapter->default_settings;
> +
>  	/* TODO for we assume all went well */
>  	btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_RESET, index, 0, NULL);
>  	return;
> @@ -2207,6 +2210,8 @@ static void proxy_added(struct l_dbus_proxy *proxy,
> void *user_data) extract_settings(proxy, &adapter->current_settings,
>  						&adapter->supported_settings);
> 
> +		adapter->default_settings = adapter->current_settings;
> +
>  		l_queue_push_tail(adapters, adapter);
>  		return;
>  	}

Patch applied, thanks.

-- 
pozdrawiam
Szymon Janc



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

* Re: [PATCH BlueZ 6/8] tools/btpclient: Add pair, unpair commands
  2018-01-19 16:41 ` [PATCH BlueZ 6/8] tools/btpclient: Add pair, unpair commands Grzegorz Kolodziejczyk
@ 2018-01-23 13:53   ` Szymon Janc
  2018-01-23 15:08     ` Grzegorz Kołodziejczyk
  0 siblings, 1 reply; 16+ messages in thread
From: Szymon Janc @ 2018-01-23 13:53 UTC (permalink / raw)
  To: Grzegorz Kolodziejczyk; +Cc: linux-bluetooth

Hi Grzegorz,

On Friday, 19 January 2018 17:41:31 CET Grzegorz Kolodziejczyk wrote:
> This patch adds pair and unpair commands for btp client.
> ---
>  tools/btpclient.c | 124
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124
> insertions(+)
> 
> diff --git a/tools/btpclient.c b/tools/btpclient.c
> index 53c0d4c05..9d44fba41 100644
> --- a/tools/btpclient.c
> +++ b/tools/btpclient.c
> @@ -304,6 +304,8 @@ static void btp_gap_read_commands(uint8_t index, const
> void *param, commands |= (1 << BTP_OP_GAP_CONNECT);
>  	commands |= (1 << BTP_OP_GAP_DISCONNECT);
>  	commands |= (1 << BTP_OP_GAP_SET_IO_CAPA);
> +	commands |= (1 << BTP_OP_GAP_PAIR);
> +	commands |= (1 << BTP_OP_GAP_UNPAIR);
> 
>  	commands = L_CPU_TO_LE16(commands);
> 
> @@ -1875,6 +1877,122 @@ failed:
>  	btp_send_error(btp, BTP_GAP_SERVICE, index, status);
>  }
> 
> +static void pair_reply(struct l_dbus_proxy *proxy,
> +				struct l_dbus_message *result, void *user_data)
> +{
> +	uint8_t adapter_index = L_PTR_TO_UINT(user_data);
> +	struct btp_adapter *adapter = find_adapter_by_index(adapter_index);
> +
> +	if (!adapter)
> +		return;
> +
> +	if (l_dbus_message_is_error(result)) {
> +		const char *name, *desc;
> +
> +		l_dbus_message_get_error(result, &name, &desc);
> +		l_error("Failed to pair (%s), %s", name, desc);
> +
> +		return;
> +	}
> +}
> +
> +static void btp_gap_pair(uint8_t index, const void *param, uint16_t length,
> +								void *user_data)
> +{
> +	struct btp_adapter *adapter = find_adapter_by_index(index);
> +	const struct btp_gap_pair_cp *cp = param;
> +	uint8_t status = BTP_ERROR_FAIL;
> +	struct btp_device *device;
> +	bool prop;
> +
> +	if (!adapter) {
> +		status = BTP_ERROR_INVALID_INDEX;
> +		goto failed;
> +	}
> +
> +	/* Adapter needs to be powered to be able to pair */
> +	if (!l_dbus_proxy_get_property(adapter->proxy, "Powered", "b", &prop) ||
> +									!prop)
> +		goto failed;
> +
> +	device = find_device_by_address(adapter, &cp->address,
> +							cp->address_type);
> +
> +	if (!device)
> +		goto failed;
> +
> +	btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_PAIR, adapter->index, 0,

Please comment here that on BTP this command is suppose to initiate pairing 
only and successful pairing result is reported via event later on.

> +									NULL);
> +
> +	l_dbus_proxy_method_call(device->proxy, "Pair", NULL, pair_reply,
> +					L_UINT_TO_PTR(adapter->index), NULL);
> +
> +	return;
> +
> +failed:
> +	btp_send_error(btp, BTP_GAP_SERVICE, index, status);
> +}
> +
> +static void unpair_reply(struct l_dbus_proxy *proxy,
> +				struct l_dbus_message *result, void *user_data)
> +{
> +	uint8_t adapter_index = L_PTR_TO_UINT(user_data);
> +	struct btp_adapter *adapter = find_adapter_by_index(adapter_index);
> +
> +	if (!adapter) {
> +		btp_send_error(btp, BTP_GAP_SERVICE, BTP_INDEX_NON_CONTROLLER,
> +								BTP_ERROR_FAIL);
> +		return;
> +	}
> +
> +	if (l_dbus_message_is_error(result)) {
> +		const char *name, *desc;
> +
> +		l_dbus_message_get_error(result, &name, &desc);
> +		l_error("Failed to unpair (%s), %s", name, desc);
> +
> +		btp_send_error(btp, BTP_GAP_SERVICE, adapter_index,
> +								BTP_ERROR_FAIL);
> +		return;
> +	}
> +
> +	btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_UNPAIR, adapter_index, 0, NULL);
> +}
> +
> +static void btp_gap_unpair(uint8_t index, const void *param, uint16_t
> length, +								void *user_data)
> +{
> +	struct btp_adapter *adapter = find_adapter_by_index(index);
> +	const struct btp_gap_pair_cp *cp = param;
> +	uint8_t status = BTP_ERROR_FAIL;
> +	struct btp_device *device;
> +	bool prop;
> +
> +	if (!adapter) {
> +		status = BTP_ERROR_INVALID_INDEX;
> +		goto failed;
> +	}
> +
> +	/* Adapter needs to be powered to be able to unpair */
> +	if (!l_dbus_proxy_get_property(adapter->proxy, "Powered", "b", &prop) ||
> +									!prop)
> +		goto failed;
> +
> +	device = find_device_by_address(adapter, &cp->address,
> +							cp->address_type);
> +
> +	if (!device)
> +		goto failed;
> +
> +	l_dbus_proxy_method_call(device->proxy, "Unpair", NULL, unpair_reply,
> +					L_UINT_TO_PTR(adapter->index), NULL);

There is no "Unpair" command in Device1 interface :)  Use RemoveDevice from 
Adapter1.

> +	return;
> +
> +failed:
> +	btp_send_error(btp, BTP_GAP_SERVICE, index, status);
> +}
> +
>  static void btp_gap_device_found_ev(struct l_dbus_proxy *proxy)
>  {
>  	struct btp_device_found_ev ev;
> @@ -1999,6 +2117,12 @@ static void register_gap_service(void)
> 
>  	btp_register(btp, BTP_GAP_SERVICE, BTP_OP_GAP_SET_IO_CAPA,
>  				btp_gap_set_io_capabilities, NULL, NULL);
> +
> +	btp_register(btp, BTP_GAP_SERVICE, BTP_OP_GAP_PAIR, btp_gap_pair, NULL,
> +									NULL);
> +
> +	btp_register(btp, BTP_GAP_SERVICE, BTP_OP_GAP_UNPAIR, btp_gap_unpair,
> +								NULL, NULL);
>  }
> 
>  static void btp_core_read_commands(uint8_t index, const void *param,


-- 
pozdrawiam
Szymon Janc



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

* Re: [PATCH BlueZ 8/8] tools/btpclient: Add passkey confirm ev and passkey confirm rsp cmd
  2018-01-19 16:41 ` [PATCH BlueZ 8/8] tools/btpclient: Add passkey confirm ev and passkey confirm rsp cmd Grzegorz Kolodziejczyk
@ 2018-01-23 14:03   ` Szymon Janc
  2018-01-23 15:09     ` Grzegorz Kołodziejczyk
  0 siblings, 1 reply; 16+ messages in thread
From: Szymon Janc @ 2018-01-23 14:03 UTC (permalink / raw)
  To: Grzegorz Kolodziejczyk; +Cc: linux-bluetooth

Hi Grzegorz,

On Friday, 19 January 2018 17:41:33 CET Grzegorz Kolodziejczyk wrote:
> This patch adds passkey confirm command handler and passkey confirm
> event.
> ---
>  tools/btpclient.c | 94
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94
> insertions(+)
> 
> diff --git a/tools/btpclient.c b/tools/btpclient.c
> index 55e5170a7..780c2a8db 100644
> --- a/tools/btpclient.c
> +++ b/tools/btpclient.c
> @@ -1703,11 +1703,43 @@ static struct l_dbus_message
> *ag_request_confirmation_call(struct l_dbus *dbus, struct l_dbus_message
> *message,
>  						void *user_data)
>  {
> +	struct btp_gap_passkey_confirm_ev ev;
> +	struct btp_device *device;
> +	struct btp_adapter *adapter;
>  	struct l_dbus_message *reply;
> +	const char *path, *str_addr, *str_addr_type;
> +	uint32_t passkey;
> 
>  	reply = l_dbus_message_new_method_return(message);
>  	l_dbus_message_set_arguments(reply, "");
> 
> +	l_dbus_message_get_arguments(message, "ou", &path, &passkey);
> +
> +	device = find_device_by_path(path);
> +
> +	if (!l_dbus_proxy_get_property(device->proxy, "Address", "s", &str_addr)
> +		|| !l_dbus_proxy_get_property(device->proxy, "AddressType", "s",
> +		&str_addr_type)) {
> +		l_info("Cannot get device properties");
> +
> +		return reply;
> +	}
> +
> +	ev.passkey = L_CPU_TO_LE32(passkey);
> +	ev.address_type = strcmp(str_addr_type, "public") ?
> +							BTP_GAP_ADDR_RANDOM :
> +							BTP_GAP_ADDR_PUBLIC;
> +	if (str2ba(str_addr, &ev.address) < 0) {
> +		l_info("Incorrect device address");
> +
> +		return reply;
> +	}
> +
> +	adapter = find_adapter_by_device(device);
> +
> +	btp_send(btp, BTP_GAP_SERVICE, BTP_EV_GAP_PASSKEY_CONFIRM,
> +					adapter->index, sizeof(ev), &ev);
> +
>  	return reply;

So ag.pending request should be stored here. And reply here should be returned 
only in case of error.

>  }
> 
> @@ -2082,6 +2114,65 @@ failed:
>  	btp_send_error(btp, BTP_GAP_SERVICE, index, status);
>  }
> 
> +static void passkey_confirm_rsp_reply(struct l_dbus_message *result,
> +								void *user_data)
> +{
> +	struct btp_adapter *adapter = user_data;
> +
> +	if (l_dbus_message_is_error(result)) {
> +		const char *name, *desc;
> +
> +		l_dbus_message_get_error(result, &name, &desc);
> +		l_error("Failed to confirm passkey (%s), %s", name, desc);
> +
> +		btp_send_error(btp, BTP_GAP_SERVICE, adapter->index,
> +								BTP_ERROR_FAIL);
> +		return;
> +	}
> +
> +	l_dbus_message_unref(ag.pending_req);
> +
> +	btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_PASSKEY_CONFIRM_RSP,
> +						adapter->index, 0, NULL);
> +}
> +
> +static void btp_gap_confirm_entry_rsp(uint8_t index, const void *param,
> +					uint16_t length, void *user_data)
> +{
> +	const struct btp_gap_passkey_confirm_rsp_cp *cp = param;
> +	struct btp_adapter *adapter = find_adapter_by_index(index);
> +	struct l_dbus_message *reply;
> +	uint8_t status = BTP_ERROR_FAIL;
> +	bool prop;
> +
> +	if (!adapter) {
> +		status = BTP_ERROR_INVALID_INDEX;
> +		goto failed;
> +	}
> +
> +	/* Adapter needs to be powered to be able to confirm passkey */
> +	if (!l_dbus_proxy_get_property(adapter->proxy, "Powered", "b", &prop) ||
> +						!prop || !ag.pending_req)
> +		goto failed;
> +
> +	if (cp->match) {
> +		reply = l_dbus_message_new_method_return(ag.pending_req);
> +		l_dbus_message_set_arguments(reply, "");
> +	} else {
> +		reply = l_dbus_message_new_error(ag.pending_req,
> +						"org.bluez.Error.Rejected",
> +						"Passkey missmatch");
> +	}
> +
> +	l_dbus_send_with_reply(dbus, ag.pending_req, passkey_confirm_rsp_reply,
> +								adapter, NULL);
> +
> +	return;
> +
> +failed:
> +	btp_send_error(btp, BTP_GAP_SERVICE, index, status);
> +}
> +
>  static void btp_gap_device_found_ev(struct l_dbus_proxy *proxy)
>  {
>  	struct btp_device_found_ev ev;
> @@ -2215,6 +2306,9 @@ static void register_gap_service(void)
> 
>  	btp_register(btp, BTP_GAP_SERVICE, BTP_OP_GAP_PASSKEY_ENTRY_RSP,
>  					btp_gap_passkey_entry_rsp, NULL, NULL);
> +
> +	btp_register(btp, BTP_GAP_SERVICE, BTP_OP_GAP_PASSKEY_CONFIRM_RSP,
> +					btp_gap_confirm_entry_rsp, NULL, NULL);
>  }
> 
>  static void btp_core_read_commands(uint8_t index, const void *param,


-- 
pozdrawiam
Szymon Janc



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

* Re: [PATCH BlueZ 3/8] tools/btpclient: Add set io capabilities command
  2018-01-23 13:48   ` Szymon Janc
@ 2018-01-23 15:06     ` Grzegorz Kołodziejczyk
  0 siblings, 0 replies; 16+ messages in thread
From: Grzegorz Kołodziejczyk @ 2018-01-23 15:06 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth

Hi Szymon,

2018-01-23 14:48 GMT+01:00 Szymon Janc <szymon.janc@codecoup.pl>:
> Hi Grzegorz,
>
> On Friday, 19 January 2018 17:41:28 CET Grzegorz Kolodziejczyk wrote:
>> This patch adds support for set io capabilities command.
>> ---
>>  tools/btpclient.c | 361
>> ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 3=
61
>> insertions(+)
>>
>> diff --git a/tools/btpclient.c b/tools/btpclient.c
>> index f2c79b3a3..708092937 100644
>> --- a/tools/btpclient.c
>> +++ b/tools/btpclient.c
>> @@ -36,7 +36,9 @@
>>  #include "src/shared/btp.h"
>>
>>  #define AD_PATH "/org/bluez/advertising"
>> +#define AG_PATH "/org/bluez/agent"
>>  #define AD_IFACE "org.bluez.LEAdvertisement1"
>> +#define AG_IFACE "org.bluez.Agent1"
>>
>>  /* List of assigned numbers for advetising data and scan response */
>>  #define AD_TYPE_FLAGS                                0x01
>> @@ -97,6 +99,12 @@ static struct ad {
>>       bool appearance;
>>  } ad;
>>
>> +static struct btp_agent {
>> +     bool registered;
>> +     struct l_dbus_proxy *proxy;
>> +     struct l_dbus_message *pending_req;
>> +} ag;
>> +
>>  static char *dupuuid2str(const uint8_t *uuid, uint8_t len)
>>  {
>>       switch (len) {
>> @@ -198,6 +206,31 @@ static struct btp_device *find_device_by_address(st=
ruct
>> btp_adapter *adapter, return NULL;
>>  }
>>
>> +static bool match_device_paths(const void *device, const void *path)
>> +{
>> +     const struct btp_device *dev =3D device;
>> +
>> +     return !strcmp(l_dbus_proxy_get_path(dev->proxy), path);
>> +}
>> +
>> +static struct btp_device *find_device_by_path(const char *path)
>> +{
>> +     const struct l_queue_entry *entry;
>> +     struct btp_device *device;
>> +
>> +     for (entry =3D l_queue_get_entries(adapters); entry;
>> +                                                     entry =3D entry->n=
ext) {
>> +             struct btp_adapter *adapter =3D entry->data;
>> +
>> +             device =3D l_queue_find(adapter->devices, match_device_pat=
hs,
>> +                                                                     pa=
th);
>> +             if (device)
>> +                     return device;
>> +     }
>> +
>> +     return NULL;
>> +}
>> +
>>  static bool match_adapter_dev_proxy(const void *device, const void *pro=
xy)
>>  {
>>       const struct btp_device *d =3D device;
>> @@ -269,6 +302,7 @@ static void btp_gap_read_commands(uint8_t index, con=
st
>> void *param, commands |=3D (1 << BTP_OP_GAP_STOP_DISCOVERY);
>>       commands |=3D (1 << BTP_OP_GAP_CONNECT);
>>       commands |=3D (1 << BTP_OP_GAP_DISCONNECT);
>> +     commands |=3D (1 << BTP_OP_GAP_SET_IO_CAPA);
>>
>>       commands =3D L_CPU_TO_LE16(commands);
>>
>> @@ -418,6 +452,43 @@ static void unreg_advertising_reply(struct l_dbus_p=
roxy
>> *proxy, l_info("Unable to unregister ad interface");
>>  }
>>
>> +static void unreg_agent_setup(struct l_dbus_message *message, void
>> *user_data) +{
>> +     struct l_dbus_message_builder *builder;
>> +
>> +     builder =3D l_dbus_message_builder_new(message);
>> +
>> +     l_dbus_message_builder_append_basic(builder, 'o', AG_PATH);
>> +
>> +     l_dbus_message_builder_finalize(builder);
>> +     l_dbus_message_builder_destroy(builder);
>> +}
>> +
>> +static void unreg_agent_reply(struct l_dbus_proxy *proxy,
>> +                                             struct l_dbus_message *res=
ult,
>> +                                             void *user_data)
>> +{
>> +     if (l_dbus_message_is_error(result)) {
>> +             const char *name;
>> +
>> +             l_dbus_message_get_error(result, &name, NULL);
>> +
>> +             l_error("Failed to unregister agent %s (%s)",
>> +                                     l_dbus_proxy_get_path(proxy), name=
);
>> +             return;
>> +     }
>> +
>> +     if (!l_dbus_object_remove_interface(dbus, AG_PATH,
>> +                                             L_DBUS_INTERFACE_PROPERTIE=
S))
>> +             l_info("Unable to remove propety instance");
>> +     if (!l_dbus_object_remove_interface(dbus, AG_PATH, AG_IFACE))
>> +             l_info("Unable to remove agent instance");
>> +     if (!l_dbus_unregister_interface(dbus, AG_IFACE))
>> +             l_info("Unable to unregister agent interface");
>> +
>> +     ag.registered =3D false;
>> +}
>> +
>>  static void btp_gap_reset(uint8_t index, const void *param, uint16_t
>> length, void *user_data)
>>  {
>> @@ -458,6 +529,15 @@ static void btp_gap_reset(uint8_t index, const void
>> *param, uint16_t length, goto failed;
>>               }
>>
>> +     if (ag.registered)
>> +             if (!l_dbus_proxy_method_call(ag.proxy, "UnregisterAgent",
>> +                                                     unreg_agent_setup,
>> +                                                     unreg_agent_reply,
>> +                                                     NULL, NULL)) {
>> +                     status =3D BTP_ERROR_FAIL;
>> +                     goto failed;
>> +             }
>> +
>>       /* TODO for we assume all went well */
>>       btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_RESET, index, 0, NULL);
>>       return;
>> @@ -1513,6 +1593,278 @@ failed:
>>       btp_send_error(btp, BTP_GAP_SERVICE, index, status);
>>  }
>>
>> +static struct l_dbus_message *ag_release_call(struct l_dbus *dbus,
>> +                                             struct l_dbus_message *mes=
sage,
>> +                                             void *user_data)
>> +{
>> +     struct l_dbus_message *reply;
>> +
>> +     reply =3D l_dbus_message_new_method_return(message);
>> +     l_dbus_message_set_arguments(reply, "");
>> +
>> +     return reply;
>> +}
>> +
>> +static struct l_dbus_message *ag_request_passkey_call(struct l_dbus *db=
us,
>> +                                             struct l_dbus_message *mes=
sage,
>> +                                             void *user_data)
>> +{
>> +     struct btp_gap_passkey_req_ev ev;
>> +     struct btp_device *device;
>> +     struct btp_adapter *adapter;
>> +     const char *path, *str_addr, *str_addr_type;
>> +
>> +     l_dbus_message_get_arguments(message, "o", &path);
>> +
>> +     device =3D find_device_by_path(path);
>> +
>> +     if (!l_dbus_proxy_get_property(device->proxy, "Address", "s", &str=
_addr)
>> +             || !l_dbus_proxy_get_property(device->proxy, "AddressType"=
, "s",
>> +             &str_addr_type)) {
>> +             l_info("Cannot get device properties");
>> +
>> +             return NULL;
>> +     }
>> +
>> +     ev.address_type =3D strcmp(str_addr_type, "public") ?
>> +                                                     BTP_GAP_ADDR_RANDO=
M :
>> +                                                     BTP_GAP_ADDR_PUBLI=
C;
>> +     if (!str2ba(str_addr, &ev.address))
>> +             return NULL;
>> +
>> +     adapter =3D find_adapter_by_device(device);
>> +
>> +     ag.pending_req =3D l_dbus_message_ref(message);
>> +
>> +     btp_send(btp, BTP_GAP_SERVICE, BTP_EV_GAP_PASSKEY_REQUEST,
>> +                                     adapter->index, sizeof(ev), &ev);
>> +
>> +     return NULL;
>> +}
>> +
>> +static struct l_dbus_message *ag_display_passkey_call(struct l_dbus *db=
us,
>> +                                             struct l_dbus_message *mes=
sage,
>> +                                             void *user_data)
>> +{
>> +     struct l_dbus_message *reply;
>> +
>> +     reply =3D l_dbus_message_new_method_return(message);
>> +     l_dbus_message_set_arguments(reply, "");
>> +
>> +     return reply;
>> +}
>> +
>> +static struct l_dbus_message *ag_request_confirmation_call(struct l_dbu=
s
>> *dbus, +                                              struct l_dbus_mess=
age *message,
>> +                                             void *user_data)
>> +{
>> +     struct l_dbus_message *reply;
>> +
>> +     reply =3D l_dbus_message_new_method_return(message);
>> +     l_dbus_message_set_arguments(reply, "");
>> +
>> +     return reply;
>> +}
>> +
>> +static struct l_dbus_message *ag_authorize_service_call(struct l_dbus
>> *dbus, +                                              struct l_dbus_mess=
age *message,
>> +                                             void *user_data)
>> +{
>> +     struct l_dbus_message *reply;
>> +
>> +     reply =3D l_dbus_message_new_method_return(message);
>> +     l_dbus_message_set_arguments(reply, "");
>> +
>> +     return reply;
>> +}
>> +
>> +static struct l_dbus_message *ag_cancel_call(struct l_dbus *dbus,
>> +                                             struct l_dbus_message *mes=
sage,
>> +                                             void *user_data)
>> +{
>> +     struct l_dbus_message *reply;
>> +
>> +     reply =3D l_dbus_message_new_method_return(message);
>> +     l_dbus_message_set_arguments(reply, "");
>> +
>> +     return reply;
>> +}
>> +
>> +static void setup_ag_interface(struct l_dbus_interface *iface)
>> +{
>> +     l_dbus_interface_method(iface, "Release", 0, ag_release_call, "", =
"");
>> +     l_dbus_interface_method(iface, "RequestPasskey", 0,
>> +                                     ag_request_passkey_call, "u", "o",
>> +                                     "passkey", "device");
>> +     l_dbus_interface_method(iface, "DisplayPasskey", 0,
>> +                                     ag_display_passkey_call, "", "ouq"=
,
>> +                                     "device", "passkey", "entered");
>> +     l_dbus_interface_method(iface, "RequestConfirmation", 0,
>> +                                     ag_request_confirmation_call, "", =
"ou",
>> +                                     "device", "passkey");
>> +     l_dbus_interface_method(iface, "RequestAuthorization", 0,
>> +                                     ag_request_confirmation_call, "", =
"o",
>> +                                     "device");
>> +     l_dbus_interface_method(iface, "AuthorizeService", 0,
>> +                                     ag_authorize_service_call, "", "os=
",
>> +                                     "device", "uuid");
>> +     l_dbus_interface_method(iface, "Cancel", 0, ag_cancel_call, "", ""=
);
>> +}
>> +
>> +struct set_io_capabilities_data {
>> +     uint8_t capa;
>> +     struct btp_adapter *adapter;
>> +};
>> +
>> +static void set_io_capabilities_setup(struct l_dbus_message *message,
>> +                                                             void *user=
_data)
>> +{
>> +     struct set_io_capabilities_data *sicd =3D user_data;
>> +     struct l_dbus_message_builder *builder;
>> +     char *capa_str;
>> +
>> +     builder =3D l_dbus_message_builder_new(message);
>> +
>> +     l_dbus_message_builder_append_basic(builder, 'o', AG_PATH);
>> +
>> +     switch (sicd->capa) {
>> +     case BTP_GAP_IOCAPA_DISPLAY_ONLY:
>> +             capa_str =3D "DisplayOnly";
>> +             break;
>> +     case BTP_GAP_IOCAPA_DISPLAY_YESNO:
>> +             capa_str =3D "DisplayYesNo";
>> +             break;
>> +     case BTP_GAP_IOCAPA_KEYBOARD_ONLY:
>> +             capa_str =3D "KeyboardOnly";
>> +             break;
>> +     case BTP_GAP_IOCAPA_NO_INPUT_NO_OUTPUT:
>> +             capa_str =3D "NoInputNoOutput";
>> +             break;
>> +     case BTP_GAP_IOCAPA_KEYBOARD_DISPLAY:
>> +             capa_str =3D "KeyboardDisplay";
>> +             break;
>> +     default:
>> +             l_error("Wrong iocapa given!");
>> +             l_dbus_message_builder_finalize(builder);
>> +             l_dbus_message_builder_destroy(builder);
>> +
>> +             return;
>> +     }
>
> setup callback should only build message, not verify parameters as it ret=
urns
> void. Please check those in btp_gap_set_io_capabilities().
Ok.
>
>> +
>> +     l_dbus_message_builder_append_basic(builder, 's', capa_str);
>> +
>> +     l_dbus_message_builder_finalize(builder);
>> +     l_dbus_message_builder_destroy(builder);
>> +}
>> +
>> +static void set_io_capabilities_reply(struct l_dbus_proxy *proxy,
>> +                                             struct l_dbus_message *res=
ult,
>> +                                             void *user_data)
>> +{
>> +     struct set_io_capabilities_data *sicd =3D user_data;
>> +
>> +     if (!sicd->adapter) {
>> +             btp_send_error(btp, BTP_GAP_SERVICE, BTP_INDEX_NON_CONTROL=
LER,
>> +                                                             BTP_ERROR_=
FAIL);
>> +             return;
>> +     }
>> +
>> +     if (l_dbus_message_is_error(result)) {
>> +             const char *name, *desc;
>> +
>> +             if (!l_dbus_object_remove_interface(dbus, AG_PATH, AG_IFAC=
E))
>> +                     l_info("Unable to remove agent instance");
>> +             if (!l_dbus_unregister_interface(dbus, AG_IFACE))
>> +                     l_info("Unable to unregister agent interface");
>> +
>> +             l_dbus_message_get_error(result, &name, &desc);
>> +             l_error("Failed to set io capabilities (%s), %s", name, de=
sc);
>> +
>> +             btp_send_error(btp, BTP_GAP_SERVICE, sicd->adapter->index,
>> +                                                             BTP_ERROR_=
FAIL);
>> +             return;
>> +     }
>> +
>> +     ag.registered =3D true;
>> +
>> +     btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_SET_IO_CAPA,
>> +                                             sicd->adapter->index, 0, N=
ULL);
>> +}
>> +
>> +static void set_io_capabilities_destroy(void *user_data)
>> +{
>> +     l_free(user_data);
>> +}
>> +
>> +static void btp_gap_set_io_capabilities(uint8_t index, const void *para=
m,
>> +                                     uint16_t length, void *user_data)
>> +{
>> +     struct btp_adapter *adapter =3D find_adapter_by_index(index);
>> +     const struct btp_gap_set_io_capa_cp *cp =3D param;
>> +     uint8_t status =3D BTP_ERROR_FAIL;
>> +     struct set_io_capabilities_data *data;
>> +     bool prop;
>> +
>> +     if (!adapter) {
>> +             status =3D BTP_ERROR_INVALID_INDEX;
>> +             goto failed;
>> +     }
>> +
>> +     /* Adapter needs to be powered to be able to set io cap */
>> +     if (!l_dbus_proxy_get_property(adapter->proxy, "Powered", "b", &pr=
op) ||
>> +                                                     !prop || ag.regist=
ered)
>> +             goto failed;
>> +
>> +     if (!l_dbus_register_interface(dbus, AG_IFACE, setup_ag_interface,=
 NULL,
>> +                                                             false)) {
>> +             l_info("Unable to register agent interface");
>> +             goto failed;
>> +     }
>> +
>> +     if (!l_dbus_object_add_interface(dbus, AG_PATH, AG_IFACE, NULL)) {
>> +             l_info("Unable to instantiate agent interface");
>> +
>> +             if (!l_dbus_unregister_interface(dbus, AD_IFACE))
>> +                     l_info("Unable to unregister agent interface");
>> +
>> +             goto failed;
>> +     }
>> +
>> +     if (!l_dbus_object_add_interface(dbus, AG_PATH,
>> +                                             L_DBUS_INTERFACE_PROPERTIE=
S,
>> +                                             NULL)) {
>> +             l_info("Unable to instantiate the ag properties interface"=
);
>> +
>> +             if (!l_dbus_object_remove_interface(dbus, AG_PATH, AG_IFAC=
E))
>> +                     l_info("Unable to remove agent instance");
>> +             if (!l_dbus_unregister_interface(dbus, AG_IFACE))
>> +                     l_info("Unable to unregister agent interface");
>> +
>> +             goto failed;
>> +     }
>> +
>> +     data =3D l_new(struct set_io_capabilities_data, 1);
>> +     data->adapter =3D adapter;
>> +     data->capa =3D cp->capa;
>> +
>> +     if (!l_dbus_proxy_method_call(ag.proxy, "RegisterAgent",
>> +                                             set_io_capabilities_setup,
>> +                                             set_io_capabilities_reply,=
 data,
>> +                                             set_io_capabilities_destro=
y)) {
>> +             if (!l_dbus_object_remove_interface(dbus, AG_PATH, AG_IFAC=
E))
>> +                     l_info("Unable to remove agent instance");
>> +             if (!l_dbus_unregister_interface(dbus, AG_IFACE))
>> +                     l_info("Unable to unregister agent interface");
>> +
>> +             goto failed;
>> +     }
>> +
>> +     return;
>> +
>> +failed:
>> +     btp_send_error(btp, BTP_GAP_SERVICE, index, status);
>> +}
>> +
>>  static void btp_gap_device_found_ev(struct l_dbus_proxy *proxy)
>>  {
>>       struct btp_device_found_ev ev;
>> @@ -1634,6 +1986,9 @@ static void register_gap_service(void)
>>
>>       btp_register(btp, BTP_GAP_SERVICE, BTP_OP_GAP_DISCONNECT,
>>                                               btp_gap_disconnect, NULL, =
NULL);
>> +
>> +     btp_register(btp, BTP_GAP_SERVICE, BTP_OP_GAP_SET_IO_CAPA,
>> +                             btp_gap_set_io_capabilities, NULL, NULL);
>>  }
>>
>>  static void btp_core_read_commands(uint8_t index, const void *param,
>> @@ -1889,6 +2244,12 @@ static void proxy_added(struct l_dbus_proxy *prox=
y,
>> void *user_data)
>>
>>               return;
>>       }
>> +
>> +     if (!strcmp(interface, "org.bluez.AgentManager1")) {
>> +             ag.proxy =3D proxy;
>> +
>> +             return;
>> +     }
>>  }
>>
>>  static bool device_match_by_proxy(const void *a, const void *b)
>
> More general comment. We should register default agent on startup so that
> system agent is never used when btpclient is running. When this command i=
s
> called and iocapa is differrent than currently used we should unregister
> current agent and register new default.
Agree
>
>
> --
> pozdrawiam
> Szymon Janc
>
>

pozdrawiam,
Grzegorz Ko=C5=82odziejczyk

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

* Re: [PATCH BlueZ 6/8] tools/btpclient: Add pair, unpair commands
  2018-01-23 13:53   ` Szymon Janc
@ 2018-01-23 15:08     ` Grzegorz Kołodziejczyk
  0 siblings, 0 replies; 16+ messages in thread
From: Grzegorz Kołodziejczyk @ 2018-01-23 15:08 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth

Hi Szymon,

2018-01-23 14:53 GMT+01:00 Szymon Janc <szymon.janc@codecoup.pl>:
> Hi Grzegorz,
>
> On Friday, 19 January 2018 17:41:31 CET Grzegorz Kolodziejczyk wrote:
>> This patch adds pair and unpair commands for btp client.
>> ---
>>  tools/btpclient.c | 124
>> ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1=
24
>> insertions(+)
>>
>> diff --git a/tools/btpclient.c b/tools/btpclient.c
>> index 53c0d4c05..9d44fba41 100644
>> --- a/tools/btpclient.c
>> +++ b/tools/btpclient.c
>> @@ -304,6 +304,8 @@ static void btp_gap_read_commands(uint8_t index, con=
st
>> void *param, commands |=3D (1 << BTP_OP_GAP_CONNECT);
>>       commands |=3D (1 << BTP_OP_GAP_DISCONNECT);
>>       commands |=3D (1 << BTP_OP_GAP_SET_IO_CAPA);
>> +     commands |=3D (1 << BTP_OP_GAP_PAIR);
>> +     commands |=3D (1 << BTP_OP_GAP_UNPAIR);
>>
>>       commands =3D L_CPU_TO_LE16(commands);
>>
>> @@ -1875,6 +1877,122 @@ failed:
>>       btp_send_error(btp, BTP_GAP_SERVICE, index, status);
>>  }
>>
>> +static void pair_reply(struct l_dbus_proxy *proxy,
>> +                             struct l_dbus_message *result, void *user_=
data)
>> +{
>> +     uint8_t adapter_index =3D L_PTR_TO_UINT(user_data);
>> +     struct btp_adapter *adapter =3D find_adapter_by_index(adapter_inde=
x);
>> +
>> +     if (!adapter)
>> +             return;
>> +
>> +     if (l_dbus_message_is_error(result)) {
>> +             const char *name, *desc;
>> +
>> +             l_dbus_message_get_error(result, &name, &desc);
>> +             l_error("Failed to pair (%s), %s", name, desc);
>> +
>> +             return;
>> +     }
>> +}
>> +
>> +static void btp_gap_pair(uint8_t index, const void *param, uint16_t len=
gth,
>> +                                                             void *user=
_data)
>> +{
>> +     struct btp_adapter *adapter =3D find_adapter_by_index(index);
>> +     const struct btp_gap_pair_cp *cp =3D param;
>> +     uint8_t status =3D BTP_ERROR_FAIL;
>> +     struct btp_device *device;
>> +     bool prop;
>> +
>> +     if (!adapter) {
>> +             status =3D BTP_ERROR_INVALID_INDEX;
>> +             goto failed;
>> +     }
>> +
>> +     /* Adapter needs to be powered to be able to pair */
>> +     if (!l_dbus_proxy_get_property(adapter->proxy, "Powered", "b", &pr=
op) ||
>> +                                                                     !p=
rop)
>> +             goto failed;
>> +
>> +     device =3D find_device_by_address(adapter, &cp->address,
>> +                                                     cp->address_type);
>> +
>> +     if (!device)
>> +             goto failed;
>> +
>> +     btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_PAIR, adapter->index, 0,
>
> Please comment here that on BTP this command is suppose to initiate pairi=
ng
> only and successful pairing result is reported via event later on.
Ok
>
>> +                                                                     NU=
LL);
>> +
>> +     l_dbus_proxy_method_call(device->proxy, "Pair", NULL, pair_reply,
>> +                                     L_UINT_TO_PTR(adapter->index), NUL=
L);
>> +
>> +     return;
>> +
>> +failed:
>> +     btp_send_error(btp, BTP_GAP_SERVICE, index, status);
>> +}
>> +
>> +static void unpair_reply(struct l_dbus_proxy *proxy,
>> +                             struct l_dbus_message *result, void *user_=
data)
>> +{
>> +     uint8_t adapter_index =3D L_PTR_TO_UINT(user_data);
>> +     struct btp_adapter *adapter =3D find_adapter_by_index(adapter_inde=
x);
>> +
>> +     if (!adapter) {
>> +             btp_send_error(btp, BTP_GAP_SERVICE, BTP_INDEX_NON_CONTROL=
LER,
>> +                                                             BTP_ERROR_=
FAIL);
>> +             return;
>> +     }
>> +
>> +     if (l_dbus_message_is_error(result)) {
>> +             const char *name, *desc;
>> +
>> +             l_dbus_message_get_error(result, &name, &desc);
>> +             l_error("Failed to unpair (%s), %s", name, desc);
>> +
>> +             btp_send_error(btp, BTP_GAP_SERVICE, adapter_index,
>> +                                                             BTP_ERROR_=
FAIL);
>> +             return;
>> +     }
>> +
>> +     btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_UNPAIR, adapter_index, 0=
, NULL);
>> +}
>> +
>> +static void btp_gap_unpair(uint8_t index, const void *param, uint16_t
>> length, +                                                             vo=
id *user_data)
>> +{
>> +     struct btp_adapter *adapter =3D find_adapter_by_index(index);
>> +     const struct btp_gap_pair_cp *cp =3D param;
>> +     uint8_t status =3D BTP_ERROR_FAIL;
>> +     struct btp_device *device;
>> +     bool prop;
>> +
>> +     if (!adapter) {
>> +             status =3D BTP_ERROR_INVALID_INDEX;
>> +             goto failed;
>> +     }
>> +
>> +     /* Adapter needs to be powered to be able to unpair */
>> +     if (!l_dbus_proxy_get_property(adapter->proxy, "Powered", "b", &pr=
op) ||
>> +                                                                     !p=
rop)
>> +             goto failed;
>> +
>> +     device =3D find_device_by_address(adapter, &cp->address,
>> +                                                     cp->address_type);
>> +
>> +     if (!device)
>> +             goto failed;
>> +
>> +     l_dbus_proxy_method_call(device->proxy, "Unpair", NULL, unpair_rep=
ly,
>> +                                     L_UINT_TO_PTR(adapter->index), NUL=
L);
>
> There is no "Unpair" command in Device1 interface :)  Use RemoveDevice fr=
om
> Adapter1.
Right, that was copy-paste mistake
>
>> +     return;
>> +
>> +failed:
>> +     btp_send_error(btp, BTP_GAP_SERVICE, index, status);
>> +}
>> +
>>  static void btp_gap_device_found_ev(struct l_dbus_proxy *proxy)
>>  {
>>       struct btp_device_found_ev ev;
>> @@ -1999,6 +2117,12 @@ static void register_gap_service(void)
>>
>>       btp_register(btp, BTP_GAP_SERVICE, BTP_OP_GAP_SET_IO_CAPA,
>>                               btp_gap_set_io_capabilities, NULL, NULL);
>> +
>> +     btp_register(btp, BTP_GAP_SERVICE, BTP_OP_GAP_PAIR, btp_gap_pair, =
NULL,
>> +                                                                     NU=
LL);
>> +
>> +     btp_register(btp, BTP_GAP_SERVICE, BTP_OP_GAP_UNPAIR, btp_gap_unpa=
ir,
>> +                                                             NULL, NULL=
);
>>  }
>>
>>  static void btp_core_read_commands(uint8_t index, const void *param,
>
>
> --
> pozdrawiam
> Szymon Janc
>
>

pozdrawiam,
Grzegorz Ko=C5=82odziejczyk

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

* Re: [PATCH BlueZ 8/8] tools/btpclient: Add passkey confirm ev and passkey confirm rsp cmd
  2018-01-23 14:03   ` Szymon Janc
@ 2018-01-23 15:09     ` Grzegorz Kołodziejczyk
  0 siblings, 0 replies; 16+ messages in thread
From: Grzegorz Kołodziejczyk @ 2018-01-23 15:09 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth

Hi Szymon,


2018-01-23 15:03 GMT+01:00 Szymon Janc <szymon.janc@codecoup.pl>:
> Hi Grzegorz,
>
> On Friday, 19 January 2018 17:41:33 CET Grzegorz Kolodziejczyk wrote:
>> This patch adds passkey confirm command handler and passkey confirm
>> event.
>> ---
>>  tools/btpclient.c | 94
>> +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, =
94
>> insertions(+)
>>
>> diff --git a/tools/btpclient.c b/tools/btpclient.c
>> index 55e5170a7..780c2a8db 100644
>> --- a/tools/btpclient.c
>> +++ b/tools/btpclient.c
>> @@ -1703,11 +1703,43 @@ static struct l_dbus_message
>> *ag_request_confirmation_call(struct l_dbus *dbus, struct l_dbus_message
>> *message,
>>                                               void *user_data)
>>  {
>> +     struct btp_gap_passkey_confirm_ev ev;
>> +     struct btp_device *device;
>> +     struct btp_adapter *adapter;
>>       struct l_dbus_message *reply;
>> +     const char *path, *str_addr, *str_addr_type;
>> +     uint32_t passkey;
>>
>>       reply =3D l_dbus_message_new_method_return(message);
>>       l_dbus_message_set_arguments(reply, "");
>>
>> +     l_dbus_message_get_arguments(message, "ou", &path, &passkey);
>> +
>> +     device =3D find_device_by_path(path);
>> +
>> +     if (!l_dbus_proxy_get_property(device->proxy, "Address", "s", &str=
_addr)
>> +             || !l_dbus_proxy_get_property(device->proxy, "AddressType"=
, "s",
>> +             &str_addr_type)) {
>> +             l_info("Cannot get device properties");
>> +
>> +             return reply;
>> +     }
>> +
>> +     ev.passkey =3D L_CPU_TO_LE32(passkey);
>> +     ev.address_type =3D strcmp(str_addr_type, "public") ?
>> +                                                     BTP_GAP_ADDR_RANDO=
M :
>> +                                                     BTP_GAP_ADDR_PUBLI=
C;
>> +     if (str2ba(str_addr, &ev.address) < 0) {
>> +             l_info("Incorrect device address");
>> +
>> +             return reply;
>> +     }
>> +
>> +     adapter =3D find_adapter_by_device(device);
>> +
>> +     btp_send(btp, BTP_GAP_SERVICE, BTP_EV_GAP_PASSKEY_CONFIRM,
>> +                                     adapter->index, sizeof(ev), &ev);
>> +
>>       return reply;
>
> So ag.pending request should be stored here. And reply here should be ret=
urned
> only in case of error.
Will fix it
>
>>  }
>>
>> @@ -2082,6 +2114,65 @@ failed:
>>       btp_send_error(btp, BTP_GAP_SERVICE, index, status);
>>  }
>>
>> +static void passkey_confirm_rsp_reply(struct l_dbus_message *result,
>> +                                                             void *user=
_data)
>> +{
>> +     struct btp_adapter *adapter =3D user_data;
>> +
>> +     if (l_dbus_message_is_error(result)) {
>> +             const char *name, *desc;
>> +
>> +             l_dbus_message_get_error(result, &name, &desc);
>> +             l_error("Failed to confirm passkey (%s), %s", name, desc);
>> +
>> +             btp_send_error(btp, BTP_GAP_SERVICE, adapter->index,
>> +                                                             BTP_ERROR_=
FAIL);
>> +             return;
>> +     }
>> +
>> +     l_dbus_message_unref(ag.pending_req);
>> +
>> +     btp_send(btp, BTP_GAP_SERVICE, BTP_OP_GAP_PASSKEY_CONFIRM_RSP,
>> +                                             adapter->index, 0, NULL);
>> +}
>> +
>> +static void btp_gap_confirm_entry_rsp(uint8_t index, const void *param,
>> +                                     uint16_t length, void *user_data)
>> +{
>> +     const struct btp_gap_passkey_confirm_rsp_cp *cp =3D param;
>> +     struct btp_adapter *adapter =3D find_adapter_by_index(index);
>> +     struct l_dbus_message *reply;
>> +     uint8_t status =3D BTP_ERROR_FAIL;
>> +     bool prop;
>> +
>> +     if (!adapter) {
>> +             status =3D BTP_ERROR_INVALID_INDEX;
>> +             goto failed;
>> +     }
>> +
>> +     /* Adapter needs to be powered to be able to confirm passkey */
>> +     if (!l_dbus_proxy_get_property(adapter->proxy, "Powered", "b", &pr=
op) ||
>> +                                             !prop || !ag.pending_req)
>> +             goto failed;
>> +
>> +     if (cp->match) {
>> +             reply =3D l_dbus_message_new_method_return(ag.pending_req)=
;
>> +             l_dbus_message_set_arguments(reply, "");
>> +     } else {
>> +             reply =3D l_dbus_message_new_error(ag.pending_req,
>> +                                             "org.bluez.Error.Rejected"=
,
>> +                                             "Passkey missmatch");
>> +     }
>> +
>> +     l_dbus_send_with_reply(dbus, ag.pending_req, passkey_confirm_rsp_r=
eply,
>> +                                                             adapter, N=
ULL);
>> +
>> +     return;
>> +
>> +failed:
>> +     btp_send_error(btp, BTP_GAP_SERVICE, index, status);
>> +}
>> +
>>  static void btp_gap_device_found_ev(struct l_dbus_proxy *proxy)
>>  {
>>       struct btp_device_found_ev ev;
>> @@ -2215,6 +2306,9 @@ static void register_gap_service(void)
>>
>>       btp_register(btp, BTP_GAP_SERVICE, BTP_OP_GAP_PASSKEY_ENTRY_RSP,
>>                                       btp_gap_passkey_entry_rsp, NULL, N=
ULL);
>> +
>> +     btp_register(btp, BTP_GAP_SERVICE, BTP_OP_GAP_PASSKEY_CONFIRM_RSP,
>> +                                     btp_gap_confirm_entry_rsp, NULL, N=
ULL);
>>  }
>>
>>  static void btp_core_read_commands(uint8_t index, const void *param,
>
>
> --
> pozdrawiam
> Szymon Janc
>
>

pozdrawiam,
Grzegorz Ko=C5=82odziejczyk

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

end of thread, other threads:[~2018-01-23 15:09 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-19 16:41 [PATCH BlueZ 1/8] tools/btpclient: Fix start adv commend comment Grzegorz Kolodziejczyk
2018-01-19 16:41 ` [PATCH BlueZ 2/8] tools/btpclient: Initial check of ad_proxy presence in stop adv cmd Grzegorz Kolodziejczyk
2018-01-19 16:41 ` [PATCH BlueZ 3/8] tools/btpclient: Add set io capabilities command Grzegorz Kolodziejczyk
2018-01-23 13:48   ` Szymon Janc
2018-01-23 15:06     ` Grzegorz Kołodziejczyk
2018-01-19 16:41 ` [PATCH BlueZ 4/8] tools/btpclient: Restore default settings on reset Grzegorz Kolodziejczyk
2018-01-23 13:48   ` Szymon Janc
2018-01-19 16:41 ` [PATCH BlueZ 5/8] tools/btpclient: Cleanup advertising data " Grzegorz Kolodziejczyk
2018-01-19 16:41 ` [PATCH BlueZ 6/8] tools/btpclient: Add pair, unpair commands Grzegorz Kolodziejczyk
2018-01-23 13:53   ` Szymon Janc
2018-01-23 15:08     ` Grzegorz Kołodziejczyk
2018-01-19 16:41 ` [PATCH BlueZ 7/8] tools/btpclient: Add passkey entry cmd and passkey display event Grzegorz Kolodziejczyk
2018-01-19 16:41 ` [PATCH BlueZ 8/8] tools/btpclient: Add passkey confirm ev and passkey confirm rsp cmd Grzegorz Kolodziejczyk
2018-01-23 14:03   ` Szymon Janc
2018-01-23 15:09     ` Grzegorz Kołodziejczyk
2018-01-23 13:44 ` [PATCH BlueZ 1/8] tools/btpclient: Fix start adv commend comment Szymon Janc

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.