summaryrefslogtreecommitdiff
path: root/src/advertising.c
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2017-08-14 16:22:09 +0300
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2017-08-16 13:59:00 +0300
commitb12b7e76556dc2bd037ee89604b759f3de60c695 (patch)
treef8fff7ec5a88767298b028685c7b759a1754be22 /src/advertising.c
parent0c663ff5e06f1635c3def93e3f00b5dd291a72f0 (diff)
downloadbluez-b12b7e76556dc2bd037ee89604b759f3de60c695.tar.gz
advertising: Allow changes to properties
This enables the application to change the advertising object instead of having it unregistered and registered once again.
Diffstat (limited to 'src/advertising.c')
-rw-r--r--src/advertising.c156
1 files 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.");