advertising: Add Includes property

This enables using the all the supporting includes.

Note: IncludeTxPower has been moved under Includes as well since it was
still experimental.
This commit is contained in:
Luiz Augusto von Dentz 2017-08-09 11:29:01 +03:00
parent 91f9eb1310
commit 9fb1f9ff69
2 changed files with 104 additions and 100 deletions

View File

@ -61,11 +61,13 @@ Properties string Type
Service Data elements to include. The keys are the
UUID to associate with the data.
bool IncludeTxPower
array{string} Includes
Includes the Tx Power in the advertising packet.
If missing, the Tx Power is not included.
List of features to be included in the advertising
packet.
Possible values: as found on
LEAdvertisingManager.SupportedIncludes
LE Advertising Manager hierarchy
================================

View File

@ -63,7 +63,7 @@ struct btd_adv_client {
GDBusProxy *proxy;
DBusMessage *reg;
uint8_t type; /* Advertising type */
bool include_tx_power;
uint32_t flags;
struct bt_ad *data;
uint8_t instance;
};
@ -194,45 +194,39 @@ static void client_disconnect_cb(DBusConnection *conn, void *user_data)
client_remove(user_data);
}
static bool parse_type(GDBusProxy *proxy, uint8_t *type)
static bool parse_type(DBusMessageIter *iter, struct btd_adv_client *client)
{
DBusMessageIter iter;
const char *msg_type;
if (!g_dbus_proxy_get_property(proxy, "Type", &iter))
if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING)
return false;
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
return false;
dbus_message_iter_get_basic(&iter, &msg_type);
dbus_message_iter_get_basic(iter, &msg_type);
if (!g_strcmp0(msg_type, "broadcast")) {
*type = AD_TYPE_BROADCAST;
client->type = AD_TYPE_BROADCAST;
return true;
}
if (!g_strcmp0(msg_type, "peripheral")) {
*type = AD_TYPE_PERIPHERAL;
client->type = AD_TYPE_PERIPHERAL;
return true;
}
return false;
}
static bool parse_service_uuids(GDBusProxy *proxy, struct bt_ad *data)
static bool parse_service_uuids(DBusMessageIter *iter,
struct btd_adv_client *client)
{
DBusMessageIter iter, ariter;
DBusMessageIter ariter;
if (!g_dbus_proxy_get_property(proxy, "ServiceUUIDs", &iter))
return true;
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
return false;
dbus_message_iter_recurse(&iter, &ariter);
dbus_message_iter_recurse(iter, &ariter);
bt_ad_clear_service_uuid(data);
bt_ad_clear_service_uuid(client->data);
while (dbus_message_iter_get_arg_type(&ariter) == DBUS_TYPE_STRING) {
const char *uuid_str;
@ -245,7 +239,7 @@ static bool parse_service_uuids(GDBusProxy *proxy, struct bt_ad *data)
if (bt_string_to_uuid(&uuid, uuid_str) < 0)
goto fail;
if (!bt_ad_add_service_uuid(data, &uuid))
if (!bt_ad_add_service_uuid(client->data, &uuid))
goto fail;
dbus_message_iter_next(&ariter);
@ -254,23 +248,21 @@ static bool parse_service_uuids(GDBusProxy *proxy, struct bt_ad *data)
return true;
fail:
bt_ad_clear_service_uuid(data);
bt_ad_clear_service_uuid(client->data);
return false;
}
static bool parse_solicit_uuids(GDBusProxy *proxy, struct bt_ad *data)
static bool parse_solicit_uuids(DBusMessageIter *iter,
struct btd_adv_client *client)
{
DBusMessageIter iter, ariter;
DBusMessageIter ariter;
if (!g_dbus_proxy_get_property(proxy, "SolicitUUIDs", &iter))
return true;
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
return false;
dbus_message_iter_recurse(&iter, &ariter);
dbus_message_iter_recurse(iter, &ariter);
bt_ad_clear_solicit_uuid(data);
bt_ad_clear_solicit_uuid(client->data);
while (dbus_message_iter_get_arg_type(&ariter) == DBUS_TYPE_STRING) {
const char *uuid_str;
@ -283,7 +275,7 @@ static bool parse_solicit_uuids(GDBusProxy *proxy, struct bt_ad *data)
if (bt_string_to_uuid(&uuid, uuid_str) < 0)
goto fail;
if (!bt_ad_add_solicit_uuid(data, &uuid))
if (!bt_ad_add_solicit_uuid(client->data, &uuid))
goto fail;
dbus_message_iter_next(&ariter);
@ -292,23 +284,21 @@ static bool parse_solicit_uuids(GDBusProxy *proxy, struct bt_ad *data)
return true;
fail:
bt_ad_clear_solicit_uuid(data);
bt_ad_clear_solicit_uuid(client->data);
return false;
}
static bool parse_manufacturer_data(GDBusProxy *proxy, struct bt_ad *data)
static bool parse_manufacturer_data(DBusMessageIter *iter,
struct btd_adv_client *client)
{
DBusMessageIter iter, entries;
DBusMessageIter entries;
if (!g_dbus_proxy_get_property(proxy, "ManufacturerData", &iter))
return true;
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
return false;
dbus_message_iter_recurse(&iter, &entries);
dbus_message_iter_recurse(iter, &entries);
bt_ad_clear_manufacturer_data(data);
bt_ad_clear_manufacturer_data(client->data);
while (dbus_message_iter_get_arg_type(&entries)
== DBUS_TYPE_DICT_ENTRY) {
@ -339,8 +329,8 @@ static bool parse_manufacturer_data(GDBusProxy *proxy, struct bt_ad *data)
DBG("Adding ManufacturerData for %04x", manuf_id);
if (!bt_ad_add_manufacturer_data(data, manuf_id, manuf_data,
len))
if (!bt_ad_add_manufacturer_data(client->data, manuf_id,
manuf_data, len))
goto fail;
dbus_message_iter_next(&entries);
@ -349,23 +339,21 @@ static bool parse_manufacturer_data(GDBusProxy *proxy, struct bt_ad *data)
return true;
fail:
bt_ad_clear_manufacturer_data(data);
bt_ad_clear_manufacturer_data(client->data);
return false;
}
static bool parse_service_data(GDBusProxy *proxy, struct bt_ad *data)
static bool parse_service_data(DBusMessageIter *iter,
struct btd_adv_client *client)
{
DBusMessageIter iter, entries;
DBusMessageIter entries;
if (!g_dbus_proxy_get_property(proxy, "ServiceData", &iter))
return true;
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
return false;
dbus_message_iter_recurse(&iter, &entries);
dbus_message_iter_recurse(iter, &entries);
bt_ad_clear_service_data(data);
bt_ad_clear_service_data(client->data);
while (dbus_message_iter_get_arg_type(&entries)
== DBUS_TYPE_DICT_ENTRY) {
@ -400,7 +388,8 @@ static bool parse_service_data(GDBusProxy *proxy, struct bt_ad *data)
DBG("Adding ServiceData for %s", uuid_str);
if (!bt_ad_add_service_data(data, &uuid, service_data, len))
if (!bt_ad_add_service_data(client->data, &uuid, service_data,
len))
goto fail;
dbus_message_iter_next(&entries);
@ -409,28 +398,67 @@ static bool parse_service_data(GDBusProxy *proxy, struct bt_ad *data)
return true;
fail:
bt_ad_clear_service_data(data);
bt_ad_clear_service_data(client->data);
return false;
}
static bool parse_include_tx_power(GDBusProxy *proxy, bool *included)
static struct adv_include {
uint8_t flag;
const char *name;
} includes[] = {
{ MGMT_ADV_FLAG_TX_POWER, "tx-power" },
{ MGMT_ADV_FLAG_APPEARANCE, "appearance" },
{ MGMT_ADV_FLAG_LOCAL_NAME, "local-name" },
{ },
};
static bool parse_includes(DBusMessageIter *iter,
struct btd_adv_client *client)
{
DBusMessageIter iter;
dbus_bool_t b;
DBusMessageIter entries;
if (!g_dbus_proxy_get_property(proxy, "IncludeTxPower", &iter))
return true;
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
return false;
dbus_message_iter_get_basic(&iter, &b);
dbus_message_iter_recurse(iter, &entries);
*included = b;
while (dbus_message_iter_get_arg_type(&entries) == DBUS_TYPE_STRING) {
const char *str;
struct adv_include *inc;
dbus_message_iter_get_basic(&entries, &str);
for (inc = includes; inc && inc->name; inc++) {
if (strcmp(str, inc->name))
continue;
if (!(client->manager->supported_flags & inc->flag))
continue;
DBG("Including Feature: %s", str);
client->flags |= inc->flag;
}
dbus_message_iter_next(&entries);
}
return true;
}
static struct adv_parser {
const char *name;
bool (*func)(DBusMessageIter *iter, struct btd_adv_client *client);
} parsers[] = {
{ "Type", parse_type },
{ "UUIDs", parse_service_uuids },
{ "SolicitUUIDs", parse_solicit_uuids },
{ "ManufacturerData", parse_manufacturer_data },
{ "ServiceData", parse_service_data },
{ "Includes", parse_includes },
{ },
};
static void add_client_complete(struct btd_adv_client *client, uint8_t status)
{
DBusMessage *reply;
@ -517,8 +545,7 @@ static DBusMessage *refresh_advertisement(struct btd_adv_client *client)
if (client->type == AD_TYPE_PERIPHERAL)
flags = MGMT_ADV_FLAG_CONNECTABLE | MGMT_ADV_FLAG_DISCOV;
if (client->include_tx_power)
flags |= MGMT_ADV_FLAG_TX_POWER;
flags |= client->flags;
adv_data = bt_ad_generate(client->data, &adv_data_len);
@ -566,34 +593,19 @@ static DBusMessage *refresh_advertisement(struct btd_adv_client *client)
static DBusMessage *parse_advertisement(struct btd_adv_client *client)
{
if (!parse_type(client->proxy, &client->type)) {
error("Failed to read \"Type\" property of advertisement");
goto fail;
}
struct adv_parser *parser;
if (!parse_service_uuids(client->proxy, client->data)) {
error("Property \"ServiceUUIDs\" failed to parse");
goto fail;
}
for (parser = parsers; parser && parser->name; parser++) {
DBusMessageIter iter;
if (!parse_solicit_uuids(client->proxy, client->data)) {
error("Property \"SolicitUUIDs\" failed to parse");
goto fail;
}
if (!g_dbus_proxy_get_property(client->proxy, parser->name,
&iter))
continue;
if (!parse_manufacturer_data(client->proxy, client->data)) {
error("Property \"ManufacturerData\" failed to parse");
goto fail;
}
if (!parse_service_data(client->proxy, client->data)) {
error("Property \"ServiceData\" failed to parse");
goto fail;
}
if (!parse_include_tx_power(client->proxy, &client->include_tx_power)) {
error("Property \"IncludeTxPower\" failed to parse");
goto fail;
if (!parser->func(&iter, client)) {
error("Error parsing %s property", parser->name);
goto fail;
}
}
return refresh_advertisement(client);
@ -774,16 +786,6 @@ static gboolean get_active_instances(const GDBusPropertyTable *property,
return TRUE;
}
static struct adv_include {
uint8_t flag;
const char *name;
} includes[] = {
{ MGMT_ADV_FLAG_TX_POWER, "tx-power" },
{ MGMT_ADV_FLAG_APPEARANCE, "appearance" },
{ MGMT_ADV_FLAG_LOCAL_NAME, "local-name" },
{ },
};
static void append_include(struct btd_adv_manager *manager,
DBusMessageIter *iter)
{