All of lore.kernel.org
 help / color / mirror / Atom feed
From: Szymon Janc <szymon.janc@tieto.com>
To: Michael Janssen <jamuraa@chromium.org>
Cc: linux-bluetooth@vger.kernel.org
Subject: Re: [BlueZ v7 01/10] shared: add bt_ad structure
Date: Wed, 01 Apr 2015 08:53:46 +0200	[thread overview]
Message-ID: <2282703.URdIsYbQhd@leonov> (raw)
In-Reply-To: <1427822644-39009-2-git-send-email-jamuraa@chromium.org>

Hi Michael,

On Tuesday 31 of March 2015 10:23:55 Michael Janssen wrote:
> The bt_ad structure provides an abstraction for easy translation of defined
> Advertisement Data fields into the resulting raw bytes needed by the
> Bluetooth HCI LE Set Advertising Data command.
> ---
>  Makefile.am     |   1 +
>  src/shared/ad.c | 346
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/shared/ad.h | 
> 60 ++++++++++
>  3 files changed, 407 insertions(+)
>  create mode 100644 src/shared/ad.c
>  create mode 100644 src/shared/ad.h
> 
> diff --git a/Makefile.am b/Makefile.am
> index 676d929..e144428 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -111,6 +111,7 @@ shared_sources = src/shared/io.h src/shared/timeout.h \
>  			src/shared/uhid.h src/shared/uhid.c \
>  			src/shared/pcap.h src/shared/pcap.c \
>  			src/shared/btsnoop.h src/shared/btsnoop.c \
> +			src/shared/ad.h src/shared/ad.c \
>  			src/shared/att-types.h \
>  			src/shared/att.h src/shared/att.c \
>  			src/shared/gatt-helpers.h src/shared/gatt-helpers.c \
> diff --git a/src/shared/ad.c b/src/shared/ad.c
> new file mode 100644
> index 0000000..8e38d26
> --- /dev/null
> +++ b/src/shared/ad.c
> @@ -0,0 +1,346 @@
> +/*
> + *
> + *  BlueZ - Bluetooth protocol stack for Linux
> + *
> + *  Copyright (C) 2015  Google Inc.
> + *
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation; either version 2 of the License, or
> + *  (at your option) any later version.
> + *
> + *  This program is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + */
> +
> +#include "src/shared/ad.h"
> +
> +#include "src/shared/queue.h"
> +#include "src/shared/util.h"
> +
> +struct bt_ad {
> +	int ref_count;
> +	struct queue *service_uuids;
> +	struct queue *manufacturer_data;
> +	struct queue *solicit_uuids;
> +	struct queue *service_data;
> +};
> +
> +struct uuid_tagged_data {
> +	bt_uuid_t uuid;
> +	uint8_t *data;
> +	size_t len;
> +};
> +
> +struct manufacturer_tagged_data {
> +	uint16_t manufacturer_id;
> +	uint8_t *data;
> +	size_t len;
> +};
> +
> +struct bt_ad *bt_ad_new(void)
> +{
> +	struct bt_ad *ad;
> +
> +	ad = new0(struct bt_ad, 1);
> +	if (!ad)
> +		return NULL;
> +
> +	ad->service_uuids = queue_new();
> +	if (!ad->service_uuids)
> +		goto fail;
> +
> +	ad->manufacturer_data = queue_new();
> +	if (!ad->manufacturer_data)
> +		goto fail;
> +
> +	ad->solicit_uuids = queue_new();
> +	if (!ad->solicit_uuids)
> +		goto fail;
> +
> +	ad->service_data = queue_new();
> +	if (!ad->service_data)
> +		goto fail;
> +
> +	return bt_ad_ref(ad);
> +
> +fail:
> +	queue_destroy(ad->service_uuids, NULL);
> +	queue_destroy(ad->manufacturer_data, NULL);
> +	queue_destroy(ad->solicit_uuids, NULL);
> +	queue_destroy(ad->service_data, NULL);
> +
> +	free(ad);
> +
> +	return NULL;
> +}
> +
> +struct bt_ad *bt_ad_ref(struct bt_ad *ad)
> +{
> +	ad->ref_count++;
> +	return ad;
> +}
> +
> +static void uuid_tagged_destroy(void *data)
> +{
> +	struct uuid_tagged_data *tagged = data;
> +
> +	free(tagged->data);
> +	free(tagged);
> +}
> +
> +static bool uuid_tagged_match(const void *data, const void *elem)
> +{
> +	const struct uuid_tagged_data *tagged = elem;
> +	const bt_uuid_t *uuid = data;
> +
> +	return !bt_uuid_cmp(&tagged->uuid, uuid);
> +}
> +
> +static void manuf_tagged_destroy(void *data)
> +{
> +	struct manufacturer_tagged_data *tagged = data;
> +
> +	free(tagged->data);
> +	free(tagged);
> +}
> +
> +static bool manuf_tagged_match(const void *data, const void *elem)
> +{
> +	const struct manufacturer_tagged_data *tagged = elem;
> +	uint16_t manuf_id = PTR_TO_UINT(elem);
> +
> +	return tagged->manufacturer_id == manuf_id;
> +}
> +
> +void bt_ad_unref(struct bt_ad *ad)
> +{
> +	if (!ad)
> +		return;
> +
> +	if (__sync_sub_and_fetch(&ad->ref_count, 1))
> +		return;
> +
> +	queue_destroy(ad->service_uuids, free);
> +
> +	queue_destroy(ad->manufacturer_data, manuf_tagged_destroy);
> +
> +	queue_destroy(ad->solicit_uuids, free);
> +
> +	queue_destroy(ad->service_data, uuid_tagged_destroy);
> +
> +	free(ad);
> +}
> +
> +uint8_t *bt_ad_generate(struct bt_ad *ad, uint8_t *length)
> +{
> +	/* TODO: implement */
> +	return NULL;
> +}
> +
> +static bool queue_add_uuid(struct queue *queue, const bt_uuid_t *uuid)
> +{
> +	bt_uuid_t *new_uuid;
> +
> +	if (!queue)
> +		return false;
> +
> +	new_uuid = new0(bt_uuid_t, 1);
> +	if (!new_uuid)
> +		return false;
> +
> +	bt_uuid_to_uuid128(uuid, new_uuid);
> +
> +	queue_push_tail(queue, new_uuid);
> +
> +	return true;
> +}
> +
> +static bool uuid_match(const void *data, const void *elem)
> +{
> +	const bt_uuid_t *match_uuid = data;
> +	const bt_uuid_t *uuid = elem;
> +
> +	return bt_uuid_cmp(match_uuid, uuid);
> +}
> +
> +static bool queue_remove_uuid(struct queue *queue, bt_uuid_t *uuid)
> +{
> +	bt_uuid_t *removed;
> +
> +	if (!queue || !uuid)
> +		return false;
> +
> +	removed = queue_remove_if(queue, uuid_match, uuid);
> +
> +	if (removed) {
> +		free(removed);
> +		return true;
> +	}
> +
> +	return false;
> +}
> +
> +bool bt_ad_add_service_uuid(struct bt_ad *ad, const bt_uuid_t *uuid)
> +{
> +	if (!ad)
> +		return false;
> +
> +	return queue_add_uuid(ad->service_uuids, uuid);
> +}
> +
> +bool bt_ad_remove_service_uuid(struct bt_ad *ad, bt_uuid_t *uuid)
> +{
> +	if (!ad)
> +		return false;
> +
> +	return queue_remove_uuid(ad->service_uuids, uuid);
> +}
> +
> +void bt_ad_clear_service_uuid(struct bt_ad *ad)
> +{
> +	queue_destroy(ad->service_uuids, free);
> +
> +	ad->service_uuids = queue_new();
> +}
> +
> +bool bt_ad_add_manufacturer_data(struct bt_ad *ad, uint16_t
> manufacturer_id, +							void *data, size_t len)
> +{
> +	struct manufacturer_tagged_data *new_data;
> +
> +	if (!ad)
> +		return false;
> +
> +	new_data = new0(struct manufacturer_tagged_data, 1);
> +	if (!new_data)
> +		return false;
> +
> +	new_data->manufacturer_id = manufacturer_id;
> +
> +	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->manufacturer_data, new_data))
> +		return true;
> +
> +	manuf_tagged_destroy(new_data);
> +
> +	return false;
> +}
> +
> +bool bt_ad_remove_manufacturer_data(struct bt_ad *ad, uint16_t
> manufacturer_id) +{
> +	struct manufacturer_tagged_data *data;
> +
> +	if (!ad)
> +		return false;
> +
> +	data = queue_remove_if(ad->manufacturer_data, manuf_tagged_match,
> +						UINT_TO_PTR(manufacturer_id));
> +
> +	if (!data)
> +		return false;
> +
> +	manuf_tagged_destroy(data);
> +
> +	return true;
> +}
> +
> +void bt_ad_clear_manufacturer_data(struct bt_ad *ad)
> +{
> +	queue_destroy(ad->manufacturer_data, manuf_tagged_destroy);
> +
> +	ad->manufacturer_data = queue_new();
> +}
> +
> +bool bt_ad_add_solicit_uuid(struct bt_ad *ad, const bt_uuid_t *uuid)
> +{
> +	if (!ad)
> +		return false;
> +
> +	return queue_add_uuid(ad->solicit_uuids, uuid);
> +}
> +
> +bool bt_ad_remove_solicit_uuid(struct bt_ad *ad,
> +							bt_uuid_t *uuid)
> +{
> +	if (!ad)
> +		return false;
> +
> +	return queue_remove_uuid(ad->solicit_uuids, uuid);
> +}
> +
> +void bt_ad_clear_solicit_uuid(struct bt_ad *ad)
> +{
> +	queue_destroy(ad->solicit_uuids, free);
> +
> +	ad->solicit_uuids = queue_new();
> +}
> +
> +bool bt_ad_add_service_data(struct bt_ad *ad, const bt_uuid_t *uuid, void
> *data, +								size_t len)
> +{
> +	struct uuid_tagged_data *new_data;
> +
> +	if (!ad)
> +		return false;
> +
> +	new_data = new0(struct uuid_tagged_data, 1);
> +	if (!new_data)
> +		return false;
> +
> +	bt_uuid_to_uuid128(uuid, &new_data->uuid);
> +
> +	new_data->data = malloc(len);
> +	if (!new_data) {

Should be if (!new_data->data)

> +		free(new_data);
> +		return false;
> +	}
> +
> +	memcpy(new_data->data, data, len);
> +
> +	new_data->len = len;
> +
> +	if (queue_push_tail(ad->service_data, new_data))
> +		return true;
> +
> +	uuid_tagged_destroy(new_data);
> +
> +	return false;
> +}
> +
> +bool bt_ad_remove_service_data(struct bt_ad *ad, bt_uuid_t *uuid)
> +{
> +	struct uuid_tagged_data *data;
> +
> +	if (!ad)
> +		return false;
> +
> +	data = queue_remove_if(ad->service_data, uuid_tagged_match, uuid);
> +
> +	if (!data)
> +		return false;
> +
> +	uuid_tagged_destroy(data);
> +
> +	return true;
> +}
> +
> +void bt_ad_clear_service_data(struct bt_ad *ad)
> +{
> +	queue_destroy(ad->service_data, uuid_tagged_destroy);
> +
> +	ad->service_data = queue_new();
> +}
> diff --git a/src/shared/ad.h b/src/shared/ad.h
> new file mode 100644
> index 0000000..0e41da0
> --- /dev/null
> +++ b/src/shared/ad.h
> @@ -0,0 +1,60 @@
> +/*
> + *
> + *  BlueZ - Bluetooth protocol stack for Linux
> + *
> + *  Copyright (C) 2015  Google Inc.
> + *
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation; either version 2 of the License, or
> + *  (at your option) any later version.
> + *
> + *  This program is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + */
> +
> +#include <inttypes.h>
> +#include <stdbool.h>
> +
> +#include "lib/bluetooth.h"
> +#include "lib/uuid.h"
> +
> +struct bt_ad;
> +
> +struct bt_ad *bt_ad_new(void);
> +
> +struct bt_ad *bt_ad_ref(struct bt_ad *ad);
> +
> +void bt_ad_unref(struct bt_ad *ad);
> +
> +uint8_t *bt_ad_generate(struct bt_ad *ad, uint8_t *length);
> +
> +bool bt_ad_add_service_uuid(struct bt_ad *ad, const bt_uuid_t *uuid);
> +
> +bool bt_ad_remove_service_uuid(struct bt_ad *ad, bt_uuid_t *uuid);
> +
> +void bt_ad_clear_service_uuid(struct bt_ad *ad);
> +
> +bool bt_ad_add_manufacturer_data(struct bt_ad *ad, uint16_t
> manufacturer_data, +						void *data, size_t len);
> +
> +bool bt_ad_remove_manufacturer_data(struct bt_ad *ad, uint16_t
> manufacturer_id); +
> +void bt_ad_clear_manufacturer_data(struct bt_ad *ad);
> +
> +bool bt_ad_add_solicit_uuid(struct bt_ad *ad, const bt_uuid_t *uuid);
> +
> +bool bt_ad_remove_solicit_uuid(struct bt_ad *ad, bt_uuid_t *uuid);
> +
> +void bt_ad_clear_solicit_uuid(struct bt_ad *ad);
> +
> +bool bt_ad_add_service_data(struct bt_ad *ad, const bt_uuid_t *uuid, void
> *data, +								size_t len);
> +
> +bool bt_ad_remove_service_data(struct bt_ad *ad, bt_uuid_t *uuid);
> +
> +void bt_ad_clear_service_data(struct bt_ad *ad);


And more general note: most of the queue_* (ie. push and new) functions can 
fail so that should probably be checked and it seems to be missing in multiple 
places.

Eventually we might go with just aborting if small allocation fails but for 
now those should be checked against.

-- 
BR
Szymon Janc

  reply	other threads:[~2015-04-01  6:53 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-03-31 17:23 [BlueZ v7 00/10] Implement LE Advertisement D-Bus API Michael Janssen
2015-03-31 17:23 ` [BlueZ v7 01/10] shared: add bt_ad structure Michael Janssen
2015-04-01  6:53   ` Szymon Janc [this message]
2015-04-01  7:40   ` Luiz Augusto von Dentz
2015-03-31 17:23 ` [BlueZ v7 02/10] core/advertising: use bt_ad Michael Janssen
2015-03-31 17:23 ` [BlueZ v7 03/10] core/advertising: Parse ServiceUUIDs Michael Janssen
2015-03-31 17:23 ` [BlueZ v7 04/10] core/advertising: Parse SolicitUUIDs Michael Janssen
2015-03-31 17:23 ` [BlueZ v7 05/10] core/advertising: Parse ManufacturerSpecificData Michael Janssen
2015-03-31 17:24 ` [BlueZ v7 06/10] core/advertising: Parse ServiceData Michael Janssen
2015-03-31 17:24 ` [BlueZ v7 07/10] Update TODO for LE Advertising Michael Janssen
2015-03-31 17:24 ` [BlueZ v7 08/10] shared/ad: implement bt_ad_generate Michael Janssen
2015-03-31 22:28   ` Arman Uguray
2015-03-31 17:24 ` [BlueZ v7 09/10] core/advertising: Add and Remove AD using MGMT Michael Janssen
2015-03-31 17:24 ` [BlueZ v7 10/10] test: improvements to advertising-example Michael Janssen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2282703.URdIsYbQhd@leonov \
    --to=szymon.janc@tieto.com \
    --cc=jamuraa@chromium.org \
    --cc=linux-bluetooth@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.