All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH BlueZ 1/7] shared/ad: Add support for arbritary type
@ 2018-04-19 13:46 Luiz Augusto von Dentz
  2018-04-19 13:46 ` [PATCH BlueZ 2/7] doc/device-api: Add AdvertisingData property Luiz Augusto von Dentz
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2018-04-19 13:46 UTC (permalink / raw)
  To: linux-bluetooth

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

This adds APIs to include data of arbritary type as long as it is not
of a type which blacklisted due to being handled already or it is
considered to safe to be set by an application.
---
 src/shared/ad.c | 231 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
 src/shared/ad.h |  60 +++++++++++++++
 2 files changed, 278 insertions(+), 13 deletions(-)

diff --git a/src/shared/ad.c b/src/shared/ad.c
index 255794dc4..f0e62cef1 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;
 }
 
@@ -258,21 +290,21 @@ static void serialize_uuids(struct queue *uuids, uint8_t uuid_type,
 static void serialize_service_uuids(struct queue *uuids, uint8_t *buf,
 								uint8_t *pos)
 {
-	serialize_uuids(uuids, BT_UUID16, EIR_UUID16_ALL, buf, pos);
+	serialize_uuids(uuids, BT_UUID16, BT_AD_UUID16_ALL, buf, pos);
 
-	serialize_uuids(uuids, BT_UUID32, EIR_UUID32_ALL, buf, pos);
+	serialize_uuids(uuids, BT_UUID32, BT_AD_UUID32_ALL, buf, pos);
 
-	serialize_uuids(uuids, BT_UUID128, EIR_UUID128_ALL, buf, pos);
+	serialize_uuids(uuids, BT_UUID128, BT_AD_UUID128_ALL, buf, pos);
 }
 
 static void serialize_solicit_uuids(struct queue *uuids, uint8_t *buf,
 								uint8_t *pos)
 {
-	serialize_uuids(uuids, BT_UUID16, EIR_SOLICIT16, buf, pos);
+	serialize_uuids(uuids, BT_UUID16, BT_AD_SOLICIT16, buf, pos);
 
-	serialize_uuids(uuids, BT_UUID32, EIR_SOLICIT32, buf, pos);
+	serialize_uuids(uuids, BT_UUID32, BT_AD_SOLICIT32, buf, pos);
 
-	serialize_uuids(uuids, BT_UUID128, EIR_SOLICIT128, buf, pos);
+	serialize_uuids(uuids, BT_UUID128, BT_AD_SOLICIT128, buf, pos);
 }
 
 static void serialize_manuf_data(struct queue *manuf_data, uint8_t *buf,
@@ -285,7 +317,7 @@ static void serialize_manuf_data(struct queue *manuf_data, uint8_t *buf,
 
 		buf[(*pos)++] = data->len + 2 + 1;
 
-		buf[(*pos)++] = EIR_MANUFACTURER_DATA;
+		buf[(*pos)++] = BT_AD_MANUFACTURER_DATA;
 
 		bt_put_le16(data->manufacturer_id, buf + (*pos));
 
@@ -312,13 +344,13 @@ static void serialize_service_data(struct queue *service_data, uint8_t *buf,
 
 		switch (uuid_len) {
 		case 2:
-			buf[(*pos)++] = EIR_SVC_DATA16;
+			buf[(*pos)++] = BT_AD_SERVICE_DATA16;
 			break;
 		case 4:
-			buf[(*pos)++] = EIR_SVC_DATA32;
+			buf[(*pos)++] = BT_AD_SERVICE_DATA32;
 			break;
 		case 16:
-			buf[(*pos)++] = EIR_SVC_DATA128;
+			buf[(*pos)++] = BT_AD_SERVICE_DATA128;
 			break;
 		}
 
@@ -340,14 +372,14 @@ static void serialize_service_data(struct queue *service_data, uint8_t *buf,
 static void serialize_name(const char *name, uint8_t *buf, uint8_t *pos)
 {
 	int len;
-	uint8_t type = EIR_NAME_COMPLETE;
+	uint8_t type = BT_AD_NAME_COMPLETE;
 
 	if (!name)
 		return;
 
 	len = strlen(name);
 	if (len > MAX_ADV_DATA_LEN - (*pos + 2)) {
-		type = EIR_NAME_SHORT;
+		type = BT_AD_NAME_SHORT;
 		len = MAX_ADV_DATA_LEN - (*pos + 2);
 	}
 
@@ -364,12 +396,30 @@ static void serialize_appearance(uint16_t value, uint8_t *buf, uint8_t *pos)
 		return;
 
 	buf[(*pos)++] = sizeof(value) + 1;
-	buf[(*pos)++] = EIR_GAP_APPEARANCE;
+	buf[(*pos)++] = BT_AD_GAP_APPEARANCE;
 
 	bt_put_le16(value, buf + (*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,156 @@ 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;
+}
+
+static uint8_t type_blacklist[] = {
+	BT_AD_FLAGS,
+	BT_AD_UUID16_SOME,
+	BT_AD_UUID16_ALL,
+	BT_AD_UUID32_SOME,
+	BT_AD_UUID32_ALL,
+	BT_AD_UUID128_SOME,
+	BT_AD_UUID128_ALL,
+	BT_AD_NAME_SHORT,
+	BT_AD_NAME_COMPLETE,
+	BT_AD_TX_POWER,
+	BT_AD_CLASS_OF_DEV,
+	BT_AD_SSP_HASH,
+	BT_AD_SSP_RANDOMIZER,
+	BT_AD_DEVICE_ID,
+	BT_AD_SMP_TK,
+	BT_AD_SMP_OOB_FLAGS,
+	BT_AD_SLAVE_CONN_INTERVAL,
+	BT_AD_SOLICIT16,
+	BT_AD_SOLICIT128,
+	BT_AD_SERVICE_DATA16,
+	BT_AD_PUBLIC_ADDRESS,
+	BT_AD_RANDOM_ADDRESS,
+	BT_AD_GAP_APPEARANCE,
+	BT_AD_ADVERTISING_INTERVAL,
+	BT_AD_LE_DEVICE_ADDRESS,
+	BT_AD_LE_ROLE,
+	BT_AD_SSP_HASH_P256,
+	BT_AD_SSP_RANDOMIZER_P256,
+	BT_AD_SOLICIT32,
+	BT_AD_SERVICE_DATA32,
+	BT_AD_SERVICE_DATA128,
+	BT_AD_LE_SC_CONFIRM_VALUE,
+	BT_AD_LE_SC_RANDOM_VALUE,
+	BT_AD_LE_SUPPORTED_FEATURES,
+	BT_AD_CHANNEL_MAP_UPDATE_IND,
+	BT_AD_MESH_PROV,
+	BT_AD_MESH_DATA,
+	BT_AD_MESH_BEACON,
+	BT_AD_3D_INFO_DATA,
+	BT_AD_MANUFACTURER_DATA,
+};
+
+bool bt_ad_add_data(struct bt_ad *ad, uint8_t type, void *data, size_t len)
+{
+	struct bt_ad_data *new_data;
+	size_t i;
+
+	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;
+	}
+
+	for (i = 0; i < sizeof(type_blacklist); i++) {
+		if (type == type_blacklist[i])
+			return false;
+	}
+
+	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..8d705323b 100644
--- a/src/shared/ad.h
+++ b/src/shared/ad.h
@@ -27,6 +27,50 @@
 #include "lib/bluetooth.h"
 #include "lib/uuid.h"
 
+#define BT_AD_FLAGS			0x01
+#define BT_AD_UUID16_SOME		0x02
+#define BT_AD_UUID16_ALL		0x03
+#define BT_AD_UUID32_SOME		0x04
+#define BT_AD_UUID32_ALL		0x05
+#define BT_AD_UUID128_SOME		0x06
+#define BT_AD_UUID128_ALL		0x07
+#define BT_AD_NAME_SHORT		0x08
+#define BT_AD_NAME_COMPLETE		0x09
+#define BT_AD_TX_POWER			0x0a
+#define BT_AD_CLASS_OF_DEV		0x0d
+#define BT_AD_SSP_HASH			0x0e
+#define BT_AD_SSP_RANDOMIZER		0x0f
+#define BT_AD_DEVICE_ID			0x10
+#define BT_AD_SMP_TK			0x10
+#define BT_AD_SMP_OOB_FLAGS		0x11
+#define BT_AD_SLAVE_CONN_INTERVAL	0x12
+#define BT_AD_SOLICIT16			0x14
+#define BT_AD_SOLICIT128		0x15
+#define BT_AD_SERVICE_DATA16		0x16
+#define BT_AD_PUBLIC_ADDRESS		0x17
+#define BT_AD_RANDOM_ADDRESS		0x18
+#define BT_AD_GAP_APPEARANCE		0x19
+#define BT_AD_ADVERTISING_INTERVAL	0x1a
+#define BT_AD_LE_DEVICE_ADDRESS		0x1b
+#define BT_AD_LE_ROLE			0x1c
+#define BT_AD_SSP_HASH_P256		0x1d
+#define BT_AD_SSP_RANDOMIZER_P256	0x1e
+#define BT_AD_SOLICIT32			0x1f
+#define BT_AD_SERVICE_DATA32		0x20
+#define BT_AD_SERVICE_DATA128		0x21
+#define BT_AD_LE_SC_CONFIRM_VALUE	0x22
+#define BT_AD_LE_SC_RANDOM_VALUE	0x23
+#define BT_AD_URI			0x24
+#define BT_AD_INDOOR_POSITIONING	0x25
+#define BT_AD_TRANSPORT_DISCOVERY	0x26
+#define BT_AD_LE_SUPPORTED_FEATURES	0x27
+#define BT_AD_CHANNEL_MAP_UPDATE_IND	0x28
+#define BT_AD_MESH_PROV			0x29
+#define BT_AD_MESH_DATA			0x2a
+#define BT_AD_MESH_BEACON		0x2b
+#define BT_AD_3D_INFO_DATA		0x3d
+#define BT_AD_MANUFACTURER_DATA		0xff
+
 typedef void (*bt_ad_func_t)(void *data, void *user_data);
 
 struct bt_ad;
@@ -39,6 +83,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 +146,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] 7+ messages in thread

end of thread, other threads:[~2018-04-19 13:46 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-04-19 13:46 [PATCH BlueZ 1/7] shared/ad: Add support for arbritary type Luiz Augusto von Dentz
2018-04-19 13:46 ` [PATCH BlueZ 2/7] doc/device-api: Add AdvertisingData property Luiz Augusto von Dentz
2018-04-19 13:46 ` [PATCH BlueZ 3/7] device: Add implementation of AdvertisingData Luiz Augusto von Dentz
2018-04-19 13:46 ` [PATCH BlueZ 4/7] doc/advertising-api: Add Data property Luiz Augusto von Dentz
2018-04-19 13:46 ` [PATCH BlueZ 5/7] advertising: Add Data implementation Luiz Augusto von Dentz
2018-04-19 13:46 ` [PATCH BlueZ 6/7] monitor: Add support for Transport Discovery AD Luiz Augusto von Dentz
2018-04-19 13:46 ` [PATCH BlueZ 7/7] client: Add support for setting advertising Data property Luiz Augusto von Dentz

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.