[PATCH BlueZ 1/2] advertising: Allow changes to properties

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx>

This enables the application to change the advertising object instead of
having it unregistered and registered once again.
---
 src/advertising.c | 156 +++++++++++++++++++++++++++++-------------------------
 1 file changed, 85 insertions(+), 71 deletions(-)

diff --git a/src/advertising.c b/src/advertising.c
index 9eb22b9fd..f125ca5c8 100644
--- a/src/advertising.c
+++ b/src/advertising.c
@@ -21,6 +21,7 @@
 
 #include <stdint.h>
 #include <stdbool.h>
+#include <errno.h>
 
 #include <dbus/dbus.h>
 #include <gdbus/gdbus.h>
@@ -468,6 +469,7 @@ static bool parse_local_name(DBusMessageIter *iter,
 
 	dbus_message_iter_get_basic(iter, &name);
 
+	free(client->name);
 	client->name = strdup(name);
 
 	return true;
@@ -504,58 +506,6 @@ static struct adv_parser {
 	{ },
 };
 
-static void add_client_complete(struct btd_adv_client *client, uint8_t status)
-{
-	DBusMessage *reply;
-
-	if (status) {
-		error("Failed to add advertisement: %s (0x%02x)",
-						mgmt_errstr(status), status);
-		reply = btd_error_failed(client->reg,
-					"Failed to register advertisement");
-		queue_remove(client->manager->clients, client);
-		g_idle_add(client_free_idle_cb, client);
-
-	} else
-		reply = dbus_message_new_method_return(client->reg);
-
-	g_dbus_send_message(btd_get_dbus_connection(), reply);
-	dbus_message_unref(client->reg);
-	client->reg = NULL;
-}
-
-static void add_adv_callback(uint8_t status, uint16_t length,
-					  const void *param, void *user_data)
-{
-	struct btd_adv_client *client = user_data;
-	const struct mgmt_rp_add_advertising *rp = param;
-
-	if (status)
-		goto done;
-
-	if (!param || length < sizeof(*rp)) {
-		status = MGMT_STATUS_FAILED;
-		goto done;
-	}
-
-	client->instance = rp->instance;
-
-	g_dbus_client_set_disconnect_watch(client->client, client_disconnect_cb,
-									client);
-	DBG("Advertisement registered: %s", client->path);
-
-	g_dbus_emit_property_changed(btd_get_dbus_connection(),
-				adapter_get_path(client->manager->adapter),
-				LE_ADVERTISING_MGR_IFACE, "SupportedInstances");
-
-	g_dbus_emit_property_changed(btd_get_dbus_connection(),
-				adapter_get_path(client->manager->adapter),
-				LE_ADVERTISING_MGR_IFACE, "ActiveInstances");
-
-done:
-	add_client_complete(client, status);
-}
-
 static size_t calc_max_adv_len(struct btd_adv_client *client, uint32_t flags)
 {
 	size_t max = client->manager->max_adv_len;
@@ -619,7 +569,7 @@ static uint8_t *generate_scan_rsp(struct btd_adv_client *client,
 	return bt_ad_generate(client->scan, len);
 }
 
-static DBusMessage *refresh_advertisement(struct btd_adv_client *client)
+static int refresh_adv(struct btd_adv_client *client, mgmt_request_func_t func)
 {
 	struct mgmt_cp_add_advertising *cp;
 	uint8_t param_len;
@@ -639,33 +589,24 @@ static DBusMessage *refresh_advertisement(struct btd_adv_client *client)
 	adv_data = generate_adv_data(client, &flags, &adv_data_len);
 	if (!adv_data || (adv_data_len > calc_max_adv_len(client, flags))) {
 		error("Advertising data too long or couldn't be generated.");
-
-		return g_dbus_create_error(client->reg, ERROR_INTERFACE
-						".InvalidLength",
-						"Advertising data too long.");
+		return -EINVAL;
 	}
 
 	scan_rsp = generate_scan_rsp(client, &flags, &scan_rsp_len);
 	if (!scan_rsp && scan_rsp_len) {
 		error("Scan data couldn't be generated.");
-
-		return g_dbus_create_error(client->reg, ERROR_INTERFACE
-						".InvalidLength",
-						"Advertising data too long.");
+		return -EINVAL;
 	}
 
 	param_len = sizeof(struct mgmt_cp_add_advertising) + adv_data_len +
 							scan_rsp_len;
 
 	cp = malloc0(param_len);
-
 	if (!cp) {
 		error("Couldn't allocate for MGMT!");
-
 		free(adv_data);
 		free(scan_rsp);
-
-		return btd_error_failed(client->reg, "Failed");
+		return -ENOMEM;
 	}
 
 	cp->flags = htobl(flags);
@@ -680,22 +621,93 @@ static DBusMessage *refresh_advertisement(struct btd_adv_client *client)
 
 	if (!mgmt_send(client->manager->mgmt, MGMT_OP_ADD_ADVERTISING,
 				client->manager->mgmt_index, param_len, cp,
-				add_adv_callback, client, NULL)) {
+				func, client, NULL)) {
 		error("Failed to add Advertising Data");
-
 		free(cp);
-
-		return btd_error_failed(client->reg, "Failed");
+		return -EINVAL;
 	}
 
 	free(cp);
 
-	return NULL;
+	return 0;
+}
+
+static void properties_changed(GDBusProxy *proxy, const char *name,
+					DBusMessageIter *iter, void *user_data)
+{
+	struct btd_adv_client *client = user_data;
+	struct adv_parser *parser;
+
+	for (parser = parsers; parser && parser->name; parser++) {
+		if (strcmp(parser->name, name))
+			continue;
+
+		if (parser->func(iter, client)) {
+			refresh_adv(client, NULL);
+			break;
+		}
+	}
+}
+
+static void add_client_complete(struct btd_adv_client *client, uint8_t status)
+{
+	DBusMessage *reply;
+
+	if (status) {
+		error("Failed to add advertisement: %s (0x%02x)",
+						mgmt_errstr(status), status);
+		reply = btd_error_failed(client->reg,
+					"Failed to register advertisement");
+		queue_remove(client->manager->clients, client);
+		g_idle_add(client_free_idle_cb, client);
+
+	} else
+		reply = dbus_message_new_method_return(client->reg);
+
+	g_dbus_send_message(btd_get_dbus_connection(), reply);
+	dbus_message_unref(client->reg);
+	client->reg = NULL;
+}
+
+static void add_adv_callback(uint8_t status, uint16_t length,
+					  const void *param, void *user_data)
+{
+	struct btd_adv_client *client = user_data;
+	const struct mgmt_rp_add_advertising *rp = param;
+
+	if (status)
+		goto done;
+
+	if (!param || length < sizeof(*rp)) {
+		status = MGMT_STATUS_FAILED;
+		goto done;
+	}
+
+	client->instance = rp->instance;
+
+	g_dbus_client_set_disconnect_watch(client->client, client_disconnect_cb,
+									client);
+	DBG("Advertisement registered: %s", client->path);
+
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+				adapter_get_path(client->manager->adapter),
+				LE_ADVERTISING_MGR_IFACE, "SupportedInstances");
+
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+				adapter_get_path(client->manager->adapter),
+				LE_ADVERTISING_MGR_IFACE, "ActiveInstances");
+
+	g_dbus_proxy_set_property_watch(client->proxy, properties_changed,
+								client);
+
+done:
+	add_client_complete(client, status);
 }
 
 static DBusMessage *parse_advertisement(struct btd_adv_client *client)
 {
 	struct adv_parser *parser;
+	int err;
 
 	for (parser = parsers; parser && parser->name; parser++) {
 		DBusMessageIter iter;
@@ -710,7 +722,9 @@ static DBusMessage *parse_advertisement(struct btd_adv_client *client)
 		}
 	}
 
-	return refresh_advertisement(client);
+	err = refresh_adv(client, add_adv_callback);
+	if (!err)
+		return NULL;
 
 fail:
 	return btd_error_failed(client->reg, "Failed to parse advertisement.");
-- 
2.13.4

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux