* [RFC 1/7] shared/ad: Add support for arbritary type
@ 2018-04-18 11:04 Luiz Augusto von Dentz
2018-04-18 11:04 ` [RFC 2/7] doc/device-api: Add AdvertisingData property Luiz Augusto von Dentz
` (5 more replies)
0 siblings, 6 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2018-04-18 11:04 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This adds APIs to include data of any type.
---
src/shared/ad.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/shared/ad.h | 16 ++++++
2 files changed, 172 insertions(+)
diff --git a/src/shared/ad.c b/src/shared/ad.c
index 255794dc4..c80caf869 100644
--- a/src/shared/ad.c
+++ b/src/shared/ad.c
@@ -37,6 +37,7 @@ struct bt_ad {
struct queue *manufacturer_data;
struct queue *solicit_uuids;
struct queue *service_data;
+ struct queue *data;
};
struct bt_ad *bt_ad_new(void)
@@ -48,6 +49,7 @@ struct bt_ad *bt_ad_new(void)
ad->manufacturer_data = queue_new();
ad->solicit_uuids = queue_new();
ad->service_data = queue_new();
+ ad->data = queue_new();
ad->appearance = UINT16_MAX;
return bt_ad_ref(ad);
@@ -94,6 +96,14 @@ static bool manuf_match(const void *data, const void *elem)
return manuf->manufacturer_id == manuf_id;
}
+static void data_destroy(void *data)
+{
+ struct bt_ad_data *ad = data;
+
+ free(ad->data);
+ free(ad);
+}
+
void bt_ad_unref(struct bt_ad *ad)
{
if (!ad)
@@ -110,6 +120,8 @@ void bt_ad_unref(struct bt_ad *ad)
queue_destroy(ad->service_data, uuid_destroy);
+ queue_destroy(ad->data, data_destroy);
+
free(ad->name);
free(ad);
@@ -203,6 +215,24 @@ static size_t name_length(const char *name, size_t *pos)
return len;
}
+static size_t data_length(struct queue *queue)
+{
+ size_t length = 0;
+ const struct queue_entry *entry;
+
+ entry = queue_get_entries(queue);
+
+ while (entry) {
+ struct bt_ad_data *data = entry->data;
+
+ length += 1 + 1 + data->len;
+
+ entry = entry->next;
+ }
+
+ return length;
+}
+
static size_t calculate_length(struct bt_ad *ad)
{
size_t length = 0;
@@ -219,6 +249,8 @@ static size_t calculate_length(struct bt_ad *ad)
length += ad->appearance != UINT16_MAX ? 4 : 0;
+ length += data_length(ad->data);
+
return length;
}
@@ -370,6 +402,24 @@ static void serialize_appearance(uint16_t value, uint8_t *buf, uint8_t *pos)
*pos += 2;
}
+static void serialize_data(struct queue *queue, uint8_t *buf, uint8_t *pos)
+{
+ const struct queue_entry *entry = queue_get_entries(queue);
+
+ while (entry) {
+ struct bt_ad_data *data = entry->data;
+
+ buf[(*pos)++] = data->len + 1;
+ buf[(*pos)++] = data->type;
+
+ memcpy(buf + *pos, data->data, data->len);
+
+ *pos += data->len;
+
+ entry = entry->next;
+ }
+}
+
uint8_t *bt_ad_generate(struct bt_ad *ad, size_t *length)
{
uint8_t *adv_data;
@@ -399,6 +449,8 @@ uint8_t *bt_ad_generate(struct bt_ad *ad, size_t *length)
serialize_appearance(ad->appearance, adv_data, &pos);
+ serialize_data(ad->data, adv_data, &pos);
+
return adv_data;
}
@@ -756,3 +808,107 @@ void bt_ad_clear_appearance(struct bt_ad *ad)
ad->appearance = UINT16_MAX;
}
+
+static bool data_type_match(const void *data, const void *user_data)
+{
+ const struct bt_ad_data *a = data;
+ const uint8_t type = PTR_TO_UINT(user_data);
+
+ return a->type == type;
+}
+
+bool bt_ad_add_data(struct bt_ad *ad, uint8_t type, void *data, size_t len)
+{
+ struct bt_ad_data *new_data;
+
+ if (!ad)
+ return false;
+
+ if (len > (MAX_ADV_DATA_LEN - 2))
+ return false;
+
+ new_data = queue_find(ad->data, data_type_match, UINT_TO_PTR(type));
+ if (new_data) {
+ if (new_data->len == len && !memcmp(new_data->data, data, len))
+ return false;
+ new_data->data = realloc(new_data->data, len);
+ memcpy(new_data->data, data, len);
+ new_data->len = len;
+ return true;
+ }
+
+ new_data = new0(struct bt_ad_data, 1);
+ new_data->type = type;
+ new_data->data = malloc(len);
+ if (!new_data->data) {
+ free(new_data);
+ return false;
+ }
+
+ memcpy(new_data->data, data, len);
+ new_data->len = len;
+
+ if (queue_push_tail(ad->data, new_data))
+ return true;
+
+ data_destroy(new_data);
+
+ return false;
+}
+
+static bool data_match(const void *data, const void *user_data)
+{
+ const struct bt_ad_data *d1 = data;
+ const struct bt_ad_data *d2 = user_data;
+
+ if (d1->type != d2->type)
+ return false;
+
+ if (d1->len != d2->len)
+ return false;
+
+ return !memcmp(d1->data, d2->data, d1->len);
+}
+
+bool bt_ad_has_data(struct bt_ad *ad, const struct bt_ad_data *data)
+{
+ if (!ad)
+ return false;
+
+ if (!data)
+ return !queue_isempty(ad->data);
+
+ return queue_find(ad->data, data_match, data);
+}
+
+void bt_ad_foreach_data(struct bt_ad *ad, bt_ad_func_t func, void *user_data)
+{
+ if (!ad)
+ return;
+
+ queue_foreach(ad->data, func, user_data);
+}
+
+bool bt_ad_remove_data(struct bt_ad *ad, uint8_t type)
+{
+ struct bt_ad_data *data;
+
+ if (!ad)
+ return false;
+
+ data = queue_remove_if(ad->data, data_type_match, UINT_TO_PTR(type));
+ if (!data)
+ return false;
+
+ data_destroy(data);
+
+ return true;
+}
+
+void bt_ad_clear_data(struct bt_ad *ad)
+{
+ if (!ad)
+ return;
+
+ queue_remove_all(ad->data, NULL, NULL, data_destroy);
+}
diff --git a/src/shared/ad.h b/src/shared/ad.h
index f0e3b8127..2ce7e3fb2 100644
--- a/src/shared/ad.h
+++ b/src/shared/ad.h
@@ -39,6 +39,12 @@ struct bt_ad_manufacturer_data {
struct bt_ad_service_data {
bt_uuid_t uuid;
+ size_t len;
+ void *data;
+};
+
+struct bt_ad_data {
+ uint8_t type;
uint8_t *data;
size_t len;
};
@@ -96,3 +102,13 @@ void bt_ad_clear_name(struct bt_ad *ad);
bool bt_ad_add_appearance(struct bt_ad *ad, uint16_t appearance);
void bt_ad_clear_appearance(struct bt_ad *ad);
+
+bool bt_ad_add_data(struct bt_ad *ad, uint8_t type, void *data, size_t len);
+
+bool bt_ad_has_data(struct bt_ad *ad, const struct bt_ad_data *data);
+
+void bt_ad_foreach_data(struct bt_ad *ad, bt_ad_func_t func, void *user_data);
+
+bool bt_ad_remove_data(struct bt_ad *ad, uint8_t type);
+
+void bt_ad_clear_data(struct bt_ad *ad);
--
2.14.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC 2/7] doc/device-api: Add AdvertisingData property
2018-04-18 11:04 [RFC 1/7] shared/ad: Add support for arbritary type Luiz Augusto von Dentz
@ 2018-04-18 11:04 ` Luiz Augusto von Dentz
2018-04-18 14:19 ` Marcel Holtmann
2018-04-18 11:04 ` [RFC 3/7] device: Add implementation of AdvertisingData Luiz Augusto von Dentz
` (4 subsequent siblings)
5 siblings, 1 reply; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2018-04-18 11:04 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This adds AdvertisingData which exposes data being advertised which is
may be useful for profiles not handled by bluetoothd.
---
doc/device-api.txt | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/doc/device-api.txt b/doc/device-api.txt
index 1b448eef1..f2f8464bc 100644
--- a/doc/device-api.txt
+++ b/doc/device-api.txt
@@ -251,3 +251,8 @@ Properties string Address [readonly]
array{byte} AdvertisingFlags [readonly, experimental]
The Advertising Data Flags of the remote device.
+
+ dict AdvertisingData [readonly, experimental]
+
+ The Advertising Data of the remote device. Keys are
+ are 8 bits AD Type followed by data as byte array.
--
2.14.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC 3/7] device: Add implementation of AdvertisingData
2018-04-18 11:04 [RFC 1/7] shared/ad: Add support for arbritary type Luiz Augusto von Dentz
2018-04-18 11:04 ` [RFC 2/7] doc/device-api: Add AdvertisingData property Luiz Augusto von Dentz
@ 2018-04-18 11:04 ` Luiz Augusto von Dentz
2018-04-18 11:04 ` [RFC 4/7] doc/advertising-api: Add Data property Luiz Augusto von Dentz
` (3 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2018-04-18 11:04 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This adds the implementation of AdvertisingData property.
---
src/adapter.c | 3 +++
src/device.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
src/device.h | 2 ++
src/eir.c | 26 +++++++++++++++++++++++
src/eir.h | 8 +++++++
5 files changed, 105 insertions(+), 1 deletion(-)
diff --git a/src/adapter.c b/src/adapter.c
index f91b04173..705c8ad7d 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -6093,6 +6093,9 @@ static void update_found_devices(struct btd_adapter *adapter,
if (eir_data.sd_list)
device_set_service_data(dev, eir_data.sd_list, duplicate);
+ if (eir_data.data_list)
+ device_set_data(dev, eir_data.data_list, duplicate);
+
if (bdaddr_type != BDADDR_BREDR)
device_set_flags(dev, eir_data.flags);
diff --git a/src/device.c b/src/device.c
index f693b7023..474479340 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1276,6 +1276,46 @@ dev_property_service_data_exist(const GDBusPropertyTable *property,
return bt_ad_has_service_data(device->ad, NULL);
}
+static void append_advertising_data(void *data, void *user_data)
+{
+ struct bt_ad_data *ad = data;
+ DBusMessageIter *dict = user_data;
+
+ g_dbus_dict_append_basic_array(dict,
+ DBUS_TYPE_BYTE, &ad->type,
+ DBUS_TYPE_BYTE, &ad->data, ad->len);
+}
+
+static gboolean
+dev_property_get_advertising_data(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_device *device = data;
+ DBusMessageIter dict;
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+ &dict);
+
+ bt_ad_foreach_data(device->ad, append_advertising_data, &dict);
+
+ dbus_message_iter_close_container(iter, &dict);
+
+ return TRUE;
+}
+
+static gboolean
+dev_property_advertising_data_exist(const GDBusPropertyTable *property,
+ void *data)
+{
+ struct btd_device *device = data;
+
+ return bt_ad_has_data(device->ad, NULL);
+}
+
static gboolean disconnect_all(gpointer user_data)
{
struct btd_device *device = user_data;
@@ -1681,6 +1721,29 @@ void device_set_service_data(struct btd_device *dev, GSList *list,
g_slist_foreach(list, add_service_data, dev);
}
+static void add_data(void *data, void *user_data)
+{
+ struct eir_ad *ad = data;
+ struct btd_device *dev = user_data;
+
+ if (!bt_ad_add_data(dev->ad, ad->type, ad->data, ad->len))
+ return;
+
+ if (ad->type == EIR_TRANSPORT_DISCOVERY)
+ g_dbus_emit_property_changed(dbus_conn, dev->path,
+ DEVICE_INTERFACE,
+ "TransportData");
+}
+
+void device_set_data(struct btd_device *dev, GSList *list,
+ bool duplicate)
+{
+ if (duplicate)
+ bt_ad_clear_data(dev->ad);
+
+ g_slist_foreach(list, add_data, dev);
+}
+
static struct btd_service *find_connectable_service(struct btd_device *dev,
const char *uuid)
{
@@ -2673,7 +2736,9 @@ static const GDBusPropertyTable device_properties[] = {
{ "AdvertisingFlags", "ay", dev_property_get_flags, NULL,
dev_property_flags_exist,
G_DBUS_PROPERTY_FLAG_EXPERIMENTAL},
-
+ { "AdvertisingData", "a{sv}", dev_property_get_advertising_data,
+ NULL, dev_property_advertising_data_exist,
+ G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
{ }
};
diff --git a/src/device.h b/src/device.h
index b90f9273a..06b100499 100644
--- a/src/device.h
+++ b/src/device.h
@@ -83,6 +83,8 @@ void device_set_manufacturer_data(struct btd_device *dev, GSList *list,
bool duplicate);
void device_set_service_data(struct btd_device *dev, GSList *list,
bool duplicate);
+void device_set_data(struct btd_device *dev, GSList *list,
+ bool duplicate);
void device_probe_profile(gpointer a, gpointer b);
void device_remove_profile(gpointer a, gpointer b);
struct btd_adapter *device_get_adapter(struct btd_device *device);
diff --git a/src/eir.c b/src/eir.c
index c984fa5a7..4d09d637c 100644
--- a/src/eir.c
+++ b/src/eir.c
@@ -51,6 +51,14 @@ static void sd_free(void *data)
g_free(sd);
}
+static void data_free(void *data)
+{
+ struct eir_ad *ad = data;
+
+ g_free(ad->data);
+ g_free(ad);
+}
+
void eir_data_free(struct eir_data *eir)
{
g_slist_free_full(eir->services, free);
@@ -65,6 +73,8 @@ void eir_data_free(struct eir_data *eir)
eir->msd_list = NULL;
g_slist_free_full(eir->sd_list, sd_free);
eir->sd_list = NULL;
+ g_slist_free_full(eir->data_list, data_free);
+ eir->data_list = NULL;
}
static void eir_parse_uuid16(struct eir_data *eir, const void *data,
@@ -226,6 +236,19 @@ static void eir_parse_uuid128_data(struct eir_data *eir, const uint8_t *data,
eir_parse_sd(eir, &service, data + 16, len - 16);
}
+static void eir_parse_data(struct eir_data *eir, uint8_t type,
+ const uint8_t *data, uint8_t len)
+{
+ struct eir_ad *ad;
+
+ ad = g_malloc(sizeof(*ad));
+ ad->len = len;
+ ad->data = g_malloc(len);
+ memcpy(ad->data, data, len);
+
+ eir->data_list = g_slist_append(eir->data_list, ad);
+}
+
void eir_parse(struct eir_data *eir, const uint8_t *eir_data, uint8_t eir_len)
{
uint16_t len = 0;
@@ -346,6 +369,9 @@ void eir_parse(struct eir_data *eir, const uint8_t *eir_data, uint8_t eir_len)
eir_parse_msd(eir, data, data_len);
break;
+ default:
+ eir_parse_data(eir, eir_data[1], data, data_len);
+ break;
}
eir_data += field_len + 1;
diff --git a/src/eir.h b/src/eir.h
index 219ee794b..c868177a6 100644
--- a/src/eir.h
+++ b/src/eir.h
@@ -49,6 +49,7 @@
#define EIR_SOLICIT32 0x1F /* LE: Solicit UUIDs, 32-bit */
#define EIR_SVC_DATA32 0x20 /* LE: Service data, 32-bit UUID */
#define EIR_SVC_DATA128 0x21 /* LE: Service data, 128-bit UUID */
+#define EIR_TRANSPORT_DISCOVERY 0x26 /* Transport Discovery Service */
#define EIR_MANUFACTURER_DATA 0xFF /* Manufacturer Specific Data */
/* Flags Descriptions */
@@ -75,6 +76,12 @@ struct eir_sd {
uint8_t data_len;
};
+struct eir_ad {
+ uint8_t type;
+ uint8_t len;
+ void *data;
+};
+
struct eir_data {
GSList *services;
unsigned int flags;
@@ -92,6 +99,7 @@ struct eir_data {
uint16_t did_source;
GSList *msd_list;
GSList *sd_list;
+ GSList *data_list;
};
void eir_data_free(struct eir_data *eir);
--
2.14.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC 4/7] doc/advertising-api: Add Data property
2018-04-18 11:04 [RFC 1/7] shared/ad: Add support for arbritary type Luiz Augusto von Dentz
2018-04-18 11:04 ` [RFC 2/7] doc/device-api: Add AdvertisingData property Luiz Augusto von Dentz
2018-04-18 11:04 ` [RFC 3/7] device: Add implementation of AdvertisingData Luiz Augusto von Dentz
@ 2018-04-18 11:04 ` Luiz Augusto von Dentz
2018-04-18 11:05 ` [RFC 5/7] advertising: Add Data implementation Luiz Augusto von Dentz
` (2 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2018-04-18 11:04 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Data property can be used to add advertising data with arbitrary/profile
specific type.
---
doc/advertising-api.txt | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/doc/advertising-api.txt b/doc/advertising-api.txt
index 15e64d38a..758c4e687 100644
--- a/doc/advertising-api.txt
+++ b/doc/advertising-api.txt
@@ -61,6 +61,12 @@ Properties string Type
Service Data elements to include. The keys are the
UUID to associate with the data.
+ dict Data [Experimental]
+
+ Advertising Type to include in the Advertising
+ Data. Key is the advertising type and value is the
+ data as byte array.
+
array{string} Includes
List of features to be included in the advertising
--
2.14.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC 5/7] advertising: Add Data implementation
2018-04-18 11:04 [RFC 1/7] shared/ad: Add support for arbritary type Luiz Augusto von Dentz
` (2 preceding siblings ...)
2018-04-18 11:04 ` [RFC 4/7] doc/advertising-api: Add Data property Luiz Augusto von Dentz
@ 2018-04-18 11:05 ` Luiz Augusto von Dentz
2018-04-18 11:05 ` [RFC 6/7] monitor: Add support for Transport Discovery AD Luiz Augusto von Dentz
2018-04-18 11:05 ` [RFC 7/7] client: Add support for setting advertising Data property Luiz Augusto von Dentz
5 siblings, 0 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2018-04-18 11:05 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This adds the support for Data property.
---
src/advertising.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 59 insertions(+)
diff --git a/src/advertising.c b/src/advertising.c
index b976562c4..400c21b5e 100644
--- a/src/advertising.c
+++ b/src/advertising.c
@@ -583,6 +583,64 @@ static bool parse_timeout(DBusMessageIter *iter,
return true;
}
+static bool parse_data(DBusMessageIter *iter, struct btd_adv_client *client)
+{
+ DBusMessageIter entries;
+
+ if (!iter) {
+ bt_ad_clear_data(client->data);
+ return true;
+ }
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
+ return false;
+
+ dbus_message_iter_recurse(iter, &entries);
+
+ bt_ad_clear_data(client->data);
+
+ while (dbus_message_iter_get_arg_type(&entries)
+ == DBUS_TYPE_DICT_ENTRY) {
+ DBusMessageIter value, entry, array;
+ uint8_t type;
+ uint8_t *data;
+ int len;
+
+ dbus_message_iter_recurse(&entries, &entry);
+ dbus_message_iter_get_basic(&entry, &type);
+
+ dbus_message_iter_next(&entry);
+
+ if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
+ goto fail;
+
+ dbus_message_iter_recurse(&entry, &value);
+
+ if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_ARRAY)
+ goto fail;
+
+ dbus_message_iter_recurse(&value, &array);
+
+ if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_BYTE)
+ goto fail;
+
+ dbus_message_iter_get_fixed_array(&array, &data, &len);
+
+ DBG("Adding Data for type 0x%02x len %u", type, len);
+
+ if (!bt_ad_add_data(client->data, type, data, len))
+ goto fail;
+
+ dbus_message_iter_next(&entries);
+ }
+
+ return true;
+
+fail:
+ bt_ad_clear_data(client->data);
+ return false;
+}
+
static struct adv_parser {
const char *name;
bool (*func)(DBusMessageIter *iter, struct btd_adv_client *client);
@@ -597,6 +655,7 @@ static struct adv_parser {
{ "Appearance", parse_appearance },
{ "Duration", parse_duration },
{ "Timeout", parse_timeout },
+ { "Data", parse_data },
{ },
};
--
2.14.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC 6/7] monitor: Add support for Transport Discovery AD
2018-04-18 11:04 [RFC 1/7] shared/ad: Add support for arbritary type Luiz Augusto von Dentz
` (3 preceding siblings ...)
2018-04-18 11:05 ` [RFC 5/7] advertising: Add Data implementation Luiz Augusto von Dentz
@ 2018-04-18 11:05 ` Luiz Augusto von Dentz
2018-04-18 11:05 ` [RFC 7/7] client: Add support for setting advertising Data property Luiz Augusto von Dentz
5 siblings, 0 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2018-04-18 11:05 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This adds support for decoding Transport Discovery Data:
@ MGMT Command: Add Advertising (0x003e) plen 16
Instance: 1
Flags: 0x00000001
Switch into Connectable mode
Duration: 0
Timeout: 0
Advertising data length: 5
Transport Discovery Data
Organization: Bluetooth SIG (0x01)
Flags: 0x01
Role: 0x01
Seeker Only
Transport Data Incomplete: False (0x00)
Transport State: 0x00
Off
Length: 0
Data:
Scan response length: 0
---
monitor/packet.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 55 insertions(+)
diff --git a/monitor/packet.c b/monitor/packet.c
index b800a2d75..c00e9efa4 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -3545,6 +3545,57 @@ static void print_mesh_data(const uint8_t *data, uint8_t len)
packet_hexdump(data + 1, len - 1);
}
+static void print_transport_data(const uint8_t *data, uint8_t len)
+{
+ print_field("Transport Discovery Data");
+
+ if (len < 3)
+ return;
+
+ print_field(" Organization: %s (0x%02x)",
+ data[0] == 0x01 ? "Bluetooth SIG" : "RFU", data[0]);
+ print_field(" Flags: 0x%2.2x", data[1]);
+ print_field(" Role: 0x%2.2x", data[1] & 0x03);
+
+ switch (data[1] & 0x03) {
+ case 0x00:
+ print_field(" Not Specified");
+ break;
+ case 0x01:
+ print_field(" Seeker Only");
+ break;
+ case 0x02:
+ print_field(" Provider Only");
+ break;
+ case 0x03:
+ print_field(" Both Seeker an Provider");
+ break;
+ }
+
+ print_field(" Transport Data Incomplete: %s (0x%2.2x)",
+ data[1] & 0x04 ? "True" : "False", data[1] & 0x04);
+
+ print_field(" Transport State: 0x%2.2x", data[1] & 0x18);
+
+ switch (data[1] & 0x18) {
+ case 0x00:
+ print_field(" Off");
+ break;
+ case 0x08:
+ print_field(" On");
+ break;
+ case 0x10:
+ print_field(" Temporary Unavailable");
+ break;
+ case 0x18:
+ print_field(" RFU");
+ break;
+ }
+
+ print_field(" Length: %u", data[2]);
+ print_hex_field(" Data", data + 3, len - 3);
+}
+
static void print_eir(const uint8_t *eir, uint8_t eir_len, bool le)
{
uint16_t len = 0;
@@ -3744,6 +3795,10 @@ static void print_eir(const uint8_t *eir, uint8_t eir_len, bool le)
print_randomizer_p256(data);
break;
+ case BT_EIR_TRANSPORT_DISCOVERY:
+ print_transport_data(data, data_len);
+ break;
+
case BT_EIR_3D_INFO_DATA:
print_hex_field("3D Information Data", data, data_len);
if (data_len < 2)
--
2.14.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC 7/7] client: Add support for setting advertising Data property
2018-04-18 11:04 [RFC 1/7] shared/ad: Add support for arbritary type Luiz Augusto von Dentz
` (4 preceding siblings ...)
2018-04-18 11:05 ` [RFC 6/7] monitor: Add support for Transport Discovery AD Luiz Augusto von Dentz
@ 2018-04-18 11:05 ` Luiz Augusto von Dentz
5 siblings, 0 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2018-04-18 11:05 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This adds data command to advertise menu which can be used to set
an arbitrary/profile specific advertising type and data:
[bluetooth]# data 0x26 0x01 0x01 0x00
---
client/advertising.c | 158 +++++++++++++++++++++++++++++++++++++--------------
client/advertising.h | 2 +
client/main.c | 13 +++++
3 files changed, 130 insertions(+), 43 deletions(-)
diff --git a/client/advertising.c b/client/advertising.c
index 152a22a56..045133aa3 100644
--- a/client/advertising.c
+++ b/client/advertising.c
@@ -54,6 +54,11 @@ struct manufacturer_data {
struct ad_data data;
};
+struct data {
+ uint8_t type;
+ struct ad_data data;
+};
+
static struct ad {
bool registered;
char *type;
@@ -65,6 +70,7 @@ static struct ad {
size_t uuids_len;
struct service_data service;
struct manufacturer_data manufacturer;
+ struct data data;
bool tx_power;
bool name;
bool appearance;
@@ -373,12 +379,35 @@ static gboolean get_timeout(const GDBusPropertyTable *property,
return TRUE;
}
+static gboolean data_exists(const GDBusPropertyTable *property, void *data)
+{
+ return ad.data.type != 0;
+}
+
+static gboolean get_data(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *user_data)
+{
+ DBusMessageIter dict;
+ struct ad_data *data = &ad.data.data;
+ uint8_t *val = data->data;
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{yv}", &dict);
+
+ g_dbus_dict_append_basic_array(&dict, DBUS_TYPE_BYTE, &ad.data.type,
+ DBUS_TYPE_BYTE, &val, data->len);
+
+ dbus_message_iter_close_container(iter, &dict);
+
+ return TRUE;
+}
+
static const GDBusPropertyTable ad_props[] = {
{ "Type", "s", get_type },
{ "ServiceUUIDs", "as", get_uuids, NULL, uuids_exists },
{ "ServiceData", "a{sv}", get_service_data, NULL, service_data_exists },
{ "ManufacturerData", "a{qv}", get_manufacturer_data, NULL,
manufacturer_data_exists },
+ { "Data", "a{yv}", get_data, NULL, data_exists },
{ "Includes", "as", get_includes, NULL, includes_exists },
{ "LocalName", "s", get_local_name, NULL, local_name_exits },
{ "Appearance", "q", get_appearance, NULL, appearance_exits },
@@ -508,46 +537,55 @@ static void ad_clear_service(void)
return bt_shell_noninteractive_quit(EXIT_SUCCESS);
}
-void ad_advertise_service(DBusConnection *conn, int argc, char *argv[])
+static bool ad_add_data(struct ad_data *data, int argc, char *argv[])
{
unsigned int i;
- struct ad_data *data;
- if (argc < 2 || !strlen(argv[1])) {
- if (ad.service.uuid) {
- print_uuid(ad.service.uuid);
- bt_shell_hexdump(ad.service.data.data,
- ad.service.data.len);
- }
- return bt_shell_noninteractive_quit(EXIT_SUCCESS);
- }
+ memset(data, 0, sizeof(*data));
- ad_clear_service();
-
- ad.service.uuid = g_strdup(argv[1]);
- data = &ad.service.data;
-
- for (i = 2; i < (unsigned int) argc; i++) {
+ for (i = 0; i < (unsigned int) argc; i++) {
long int val;
char *endptr = NULL;
if (i >= G_N_ELEMENTS(data->data)) {
bt_shell_printf("Too much data\n");
- ad_clear_service();
- return;
+ return false;
}
val = strtol(argv[i], &endptr, 0);
if (!endptr || *endptr != '\0' || val > UINT8_MAX) {
bt_shell_printf("Invalid value at index %d\n", i);
- ad_clear_service();
- return;
+ return false;
}
data->data[data->len] = val;
data->len++;
}
+ return true;
+}
+
+void ad_advertise_service(DBusConnection *conn, int argc, char *argv[])
+{
+ struct ad_data data;
+
+ if (argc < 2 || !strlen(argv[1])) {
+ if (ad.service.uuid) {
+ print_uuid(ad.service.uuid);
+ bt_shell_hexdump(ad.service.data.data,
+ ad.service.data.len);
+ }
+ return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+ }
+
+ if (!ad_add_data(&data, argc - 2, argv + 2))
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+
+ ad_clear_service();
+
+ ad.service.uuid = g_strdup(argv[1]);
+ ad.service.data = data;
+
g_dbus_emit_property_changed(conn, AD_PATH, AD_IFACE, "ServiceData");
return bt_shell_noninteractive_quit(EXIT_SUCCESS);
@@ -573,10 +611,9 @@ static void ad_clear_manufacturer(void)
void ad_advertise_manufacturer(DBusConnection *conn, int argc, char *argv[])
{
- unsigned int i;
char *endptr = NULL;
long int val;
- struct ad_data *data;
+ struct ad_data data;
if (argc < 2 || !strlen(argv[1])) {
if (ad.manufacturer.data.len) {
@@ -589,34 +626,18 @@ void ad_advertise_manufacturer(DBusConnection *conn, int argc, char *argv[])
return bt_shell_noninteractive_quit(EXIT_SUCCESS);
}
- ad_clear_manufacturer();
-
val = strtol(argv[1], &endptr, 0);
if (!endptr || *endptr != '\0' || val > UINT16_MAX) {
bt_shell_printf("Invalid manufacture id\n");
return bt_shell_noninteractive_quit(EXIT_FAILURE);
}
- ad.manufacturer.id = val;
- data = &ad.manufacturer.data;
-
- for (i = 2; i < (unsigned int) argc; i++) {
- if (i >= G_N_ELEMENTS(data->data)) {
- bt_shell_printf("Too much data\n");
- ad_clear_manufacturer();
- return bt_shell_noninteractive_quit(EXIT_FAILURE);
- }
-
- val = strtol(argv[i], &endptr, 0);
- if (!endptr || *endptr != '\0' || val > UINT8_MAX) {
- bt_shell_printf("Invalid value at index %d\n", i);
- ad_clear_manufacturer();
- return bt_shell_noninteractive_quit(EXIT_FAILURE);
- }
+ if (!ad_add_data(&data, argc - 2, argv + 2))
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
- data->data[data->len] = val;
- data->len++;
- }
+ ad_clear_manufacturer();
+ ad.manufacturer.id = val;
+ ad.manufacturer.data = data;
g_dbus_emit_property_changed(conn, AD_PATH, AD_IFACE,
"ManufacturerData");
@@ -636,6 +657,57 @@ void ad_disable_manufacturer(DBusConnection *conn)
return bt_shell_noninteractive_quit(EXIT_SUCCESS);
}
+static void ad_clear_data(void)
+{
+ memset(&ad.manufacturer, 0, sizeof(ad.manufacturer));
+
+ return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+void ad_advertise_data(DBusConnection *conn, int argc, char *argv[])
+{
+ char *endptr = NULL;
+ long int val;
+ struct ad_data data;
+
+ if (argc < 2 || !strlen(argv[1])) {
+ if (ad.manufacturer.data.len) {
+ bt_shell_printf("Type: 0x%02x\n", ad.data.type);
+ bt_shell_hexdump(ad.data.data.data, ad.data.data.len);
+ }
+
+ return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+ }
+
+ val = strtol(argv[1], &endptr, 0);
+ if (!endptr || *endptr != '\0' || val > UINT8_MAX) {
+ bt_shell_printf("Invalid type\n");
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+
+ if (!ad_add_data(&data, argc - 2, argv + 2))
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+
+ ad_clear_data();
+ ad.data.type = val;
+ ad.data.data = data;
+
+ g_dbus_emit_property_changed(conn, AD_PATH, AD_IFACE, "Data");
+
+ return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+void ad_disable_data(DBusConnection *conn)
+{
+ if (!ad.data.type && !ad.data.data.len)
+ return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+
+ ad_clear_data();
+ g_dbus_emit_property_changed(conn, AD_PATH, AD_IFACE, "Data");
+
+ return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
void ad_advertise_tx_power(DBusConnection *conn, dbus_bool_t *value)
{
if (!value) {
diff --git a/client/advertising.h b/client/advertising.h
index b73d33b13..12b4d69c1 100644
--- a/client/advertising.h
+++ b/client/advertising.h
@@ -37,3 +37,5 @@ void ad_advertise_local_name(DBusConnection *conn, const char *name);
void ad_advertise_local_appearance(DBusConnection *conn, long int *value);
void ad_advertise_duration(DBusConnection *conn, long int *value);
void ad_advertise_timeout(DBusConnection *conn, long int *value);
+void ad_advertise_data(DBusConnection *conn, int argc, char *argv[]);
+void ad_disable_data(DBusConnection *conn);
diff --git a/client/main.c b/client/main.c
index b96278d45..d0d7f2a8f 100644
--- a/client/main.c
+++ b/client/main.c
@@ -2185,6 +2185,11 @@ static void cmd_advertise_manufacturer(int argc, char *argv[])
ad_advertise_manufacturer(dbus_conn, argc, argv);
}
+static void cmd_advertise_data(int argc, char *argv[])
+{
+ ad_advertise_data(dbus_conn, argc, argv);
+}
+
static void cmd_advertise_tx_power(int argc, char *argv[])
{
dbus_bool_t powered;
@@ -2302,6 +2307,11 @@ static void ad_clear_manufacturer(void)
ad_disable_manufacturer(dbus_conn);
}
+static void ad_clear_data(void)
+{
+ ad_disable_data(dbus_conn);
+}
+
static void ad_clear_tx_power(void)
{
dbus_bool_t powered = false;
@@ -2337,6 +2347,7 @@ static const struct clear_entry ad_clear[] = {
{ "uuids", ad_clear_uuids },
{ "service", ad_clear_service },
{ "manufacturer", ad_clear_manufacturer },
+ { "data", ad_clear_data },
{ "tx-power", ad_clear_tx_power },
{ "name", ad_clear_name },
{ "appearance", ad_clear_appearance },
@@ -2367,6 +2378,8 @@ static const struct bt_shell_menu advertise_menu = {
{ "manufacturer", "[id] [data=xx xx ...]",
cmd_advertise_manufacturer,
"Set/Get advertise manufacturer data" },
+ { "data", "[type] [data=xx xx ...]", cmd_advertise_data,
+ "Set/Get advertise data" },
{ "tx-power", "[on/off]", cmd_advertise_tx_power,
"Show/Enable/Disable TX power to be advertised",
NULL },
--
2.14.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [RFC 2/7] doc/device-api: Add AdvertisingData property
2018-04-18 11:04 ` [RFC 2/7] doc/device-api: Add AdvertisingData property Luiz Augusto von Dentz
@ 2018-04-18 14:19 ` Marcel Holtmann
2018-04-18 14:44 ` Luiz Augusto von Dentz
0 siblings, 1 reply; 10+ messages in thread
From: Marcel Holtmann @ 2018-04-18 14:19 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
Hi Luiz,
> This adds AdvertisingData which exposes data being advertised which is
> may be useful for profiles not handled by bluetoothd.
> ---
> doc/device-api.txt | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/doc/device-api.txt b/doc/device-api.txt
> index 1b448eef1..f2f8464bc 100644
> --- a/doc/device-api.txt
> +++ b/doc/device-api.txt
> @@ -251,3 +251,8 @@ Properties string Address [readonly]
> array{byte} AdvertisingFlags [readonly, experimental]
>
> The Advertising Data Flags of the remote device.
> +
> + dict AdvertisingData [readonly, experimental]
> +
> + The Advertising Data of the remote device. Keys are
> + are 8 bits AD Type followed by data as byte array.
this somehow needs to be explained on how a dict like that would look like. And also which AD types are _not_ valid here. Or at least not valid in conjunction with using other properties.
Regards
Marcel
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC 2/7] doc/device-api: Add AdvertisingData property
2018-04-18 14:19 ` Marcel Holtmann
@ 2018-04-18 14:44 ` Luiz Augusto von Dentz
2018-04-18 14:54 ` Marcel Holtmann
0 siblings, 1 reply; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2018-04-18 14:44 UTC (permalink / raw)
To: Marcel Holtmann; +Cc: linux-bluetooth@vger.kernel.org
Hi Marcel,
On Wed, Apr 18, 2018 at 5:19 PM, Marcel Holtmann <marcel@holtmann.org> wrote:
> Hi Luiz,
>
>> This adds AdvertisingData which exposes data being advertised which is
>> may be useful for profiles not handled by bluetoothd.
>> ---
>> doc/device-api.txt | 5 +++++
>> 1 file changed, 5 insertions(+)
>>
>> diff --git a/doc/device-api.txt b/doc/device-api.txt
>> index 1b448eef1..f2f8464bc 100644
>> --- a/doc/device-api.txt
>> +++ b/doc/device-api.txt
>> @@ -251,3 +251,8 @@ Properties string Address [readonly]
>> array{byte} AdvertisingFlags [readonly, experimental]
>>
>> The Advertising Data Flags of the remote device.
>> +
>> + dict AdvertisingData [readonly, experimental]
>> +
>> + The Advertising Data of the remote device. Keys are
>> + are 8 bits AD Type followed by data as byte array.
>
> this somehow needs to be explained on how a dict like that would look like. And also which AD types are _not_ valid here. Or at least not valid in conjunction with using other properties.
Sure, I can add a couple of examples for the existing profiles like
Transport Discovery Data. For the peripheral we could limit the
available type to just AD types available in the assigned number, like
a whitelist, or blacklist the types that either kernel or bluetooothd
are managing, I guess either way would work but maintaining the first
option might be more troublesome since there are new profile being
adopted all the time which was the reason why I haven't bother adding
profile specific properties since we would end up with too many. There
is also the option to use Advertising1 interface instead of Device1
that way central and peripheral APIs would be symmetric.
Btw, I don't know what went wrong with Service Data type, afaik that
was meant for the profile to use instead of each creating its own AD
type, now types can be profile specific without the use of the UUIDs
which makes it hard to correlate with the actual profile.
> Regards
>
> Marcel
>
--
Luiz Augusto von Dentz
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC 2/7] doc/device-api: Add AdvertisingData property
2018-04-18 14:44 ` Luiz Augusto von Dentz
@ 2018-04-18 14:54 ` Marcel Holtmann
0 siblings, 0 replies; 10+ messages in thread
From: Marcel Holtmann @ 2018-04-18 14:54 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth@vger.kernel.org
Hi Luiz,
>>> This adds AdvertisingData which exposes data being advertised which is
>>> may be useful for profiles not handled by bluetoothd.
>>> ---
>>> doc/device-api.txt | 5 +++++
>>> 1 file changed, 5 insertions(+)
>>>
>>> diff --git a/doc/device-api.txt b/doc/device-api.txt
>>> index 1b448eef1..f2f8464bc 100644
>>> --- a/doc/device-api.txt
>>> +++ b/doc/device-api.txt
>>> @@ -251,3 +251,8 @@ Properties string Address [readonly]
>>> array{byte} AdvertisingFlags [readonly, experimental]
>>>
>>> The Advertising Data Flags of the remote device.
>>> +
>>> + dict AdvertisingData [readonly, experimental]
>>> +
>>> + The Advertising Data of the remote device. Keys are
>>> + are 8 bits AD Type followed by data as byte array.
>>
>> this somehow needs to be explained on how a dict like that would look like. And also which AD types are _not_ valid here. Or at least not valid in conjunction with using other properties.
>
> Sure, I can add a couple of examples for the existing profiles like
> Transport Discovery Data. For the peripheral we could limit the
> available type to just AD types available in the assigned number, like
> a whitelist, or blacklist the types that either kernel or bluetooothd
> are managing, I guess either way would work but maintaining the first
> option might be more troublesome since there are new profile being
> adopted all the time which was the reason why I haven't bother adding
> profile specific properties since we would end up with too many. There
> is also the option to use Advertising1 interface instead of Device1
> that way central and peripheral APIs would be symmetric.
actually I am fine with allowing any AD type, but not allowing conflicting AD type here with other properties. So if you want all freeform, then do it and only use AdvertisingData, but if you want a combination, then certain AD types are not allowed.
Now I just saw that this is Device API, so all AD fields that are not covered by the exposed properties are fair game. My comment about not conflicting data is for the Advertising API.
> Btw, I don't know what went wrong with Service Data type, afaik that
> was meant for the profile to use instead of each creating its own AD
> type, now types can be profile specific without the use of the UUIDs
> which makes it hard to correlate with the actual profile.
Most likely size or some how stupid things that it is not a real service. This reminds me, I would actually also blacklist the Mesh AD Types since they should not be processed via D-Bus. So lets just say which ones are blacklisted.
Regards
Marcel
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2018-04-18 14:54 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-04-18 11:04 [RFC 1/7] shared/ad: Add support for arbritary type Luiz Augusto von Dentz
2018-04-18 11:04 ` [RFC 2/7] doc/device-api: Add AdvertisingData property Luiz Augusto von Dentz
2018-04-18 14:19 ` Marcel Holtmann
2018-04-18 14:44 ` Luiz Augusto von Dentz
2018-04-18 14:54 ` Marcel Holtmann
2018-04-18 11:04 ` [RFC 3/7] device: Add implementation of AdvertisingData Luiz Augusto von Dentz
2018-04-18 11:04 ` [RFC 4/7] doc/advertising-api: Add Data property Luiz Augusto von Dentz
2018-04-18 11:05 ` [RFC 5/7] advertising: Add Data implementation Luiz Augusto von Dentz
2018-04-18 11:05 ` [RFC 6/7] monitor: Add support for Transport Discovery AD Luiz Augusto von Dentz
2018-04-18 11:05 ` [RFC 7/7] client: Add support for setting advertising Data property Luiz Augusto von Dentz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).