2011-03-04 16:20:36

by Elvis Pfutzenreuter

[permalink] [raw]
Subject: [PATCH 1/5] Add new UUID utility functions

From: Claudio Takahasi <[email protected]>

New UUID functions will store the UUIDs values on host order. Byte
ordering functions are implemented somewhere else.
---
Makefile.am | 6 +-
lib/uuid.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/uuid.h | 61 +++++++++++++++++++++++++++
3 files changed, 198 insertions(+), 3 deletions(-)
create mode 100644 lib/uuid.c
create mode 100644 lib/uuid.h

diff --git a/Makefile.am b/Makefile.am
index ec1ca97..8eb1e56 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -43,8 +43,8 @@ plugin_LTLIBRARIES =


lib_headers = lib/bluetooth.h lib/hci.h lib/hci_lib.h lib/mgmt.h \
- lib/sco.h lib/l2cap.h lib/sdp.h lib/sdp_lib.h \
- lib/rfcomm.h lib/bnep.h lib/cmtp.h lib/hidp.h
+ lib/sco.h lib/l2cap.h lib/sdp.h lib/sdp_lib.h lib/uuid.h \
+ lib/rfcomm.h lib/bnep.h lib/cmtp.h lib/hidp.h
local_headers = $(foreach file,$(lib_headers), lib/bluetooth/$(notdir $(file)))

include_HEADERS += $(lib_headers)
@@ -52,7 +52,7 @@ include_HEADERS += $(lib_headers)
lib_LTLIBRARIES += lib/libbluetooth.la

lib_libbluetooth_la_SOURCES = $(lib_headers) \
- lib/bluetooth.c lib/hci.c lib/sdp.c
+ lib/bluetooth.c lib/hci.c lib/sdp.c lib/uuid.c
lib_libbluetooth_la_LDFLAGS = -version-info 13:5:10
lib_libbluetooth_la_DEPENDENCIES = $(local_headers)

diff --git a/lib/uuid.c b/lib/uuid.c
new file mode 100644
index 0000000..6bdff12
--- /dev/null
+++ b/lib/uuid.c
@@ -0,0 +1,134 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ * Copyright (C) 2011 Marcel Holtmann <[email protected]>
+ *
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include "uuid.h"
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+static uint128_t bluetooth_base_uuid = {
+ .data = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB }
+};
+
+#define BASE_UUID16_OFFSET 2
+#define BASE_UUID32_OFFSET 0
+
+#else
+static uint128_t bluetooth_base_uuid = {
+ .data = { 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+#define BASE_UUID16_OFFSET 12
+#define BASE_UUID32_OFFSET BASE_UUID16_OFFSET
+
+#endif
+
+static void bt_uuid16_to_uuid128(const bt_uuid_t *uuid16, bt_uuid_t *uuid128)
+{
+ uint16_t data;
+
+ uuid128->value.u128 = bluetooth_base_uuid;
+ uuid128->type = BT_UUID128;
+
+ memcpy(&data, &bluetooth_base_uuid.data[BASE_UUID16_OFFSET], 2);
+ data += uuid16->value.u16;
+
+ memcpy(&uuid128->value.u128.data[BASE_UUID16_OFFSET], &data, 2);
+}
+
+static void bt_uuid32_to_uuid128(const bt_uuid_t *uuid32, bt_uuid_t *uuid128)
+{
+ uint32_t data;
+
+ uuid128->value.u128 = bluetooth_base_uuid;
+ uuid128->type = BT_UUID128;
+
+ memcpy(&data, &bluetooth_base_uuid.data[BASE_UUID32_OFFSET], 4);
+ data += uuid32->value.u32;
+
+ memcpy(&uuid128->value.u128.data[BASE_UUID32_OFFSET], &data, 4);
+}
+
+static void bt_uuid2uuid128(const bt_uuid_t *uuid, bt_uuid_t *uuid128)
+{
+ switch (uuid->type) {
+ case BT_UUID128:
+ memcpy(uuid128, uuid, sizeof(bt_uuid_t));
+ break;
+ case BT_UUID32:
+ bt_uuid32_to_uuid128(uuid, uuid128);
+ break;
+ case BT_UUID16:
+ bt_uuid16_to_uuid128(uuid, uuid128);
+ break;
+ }
+}
+
+static int bt_uuid128_cmp(const bt_uuid_t *u1, const bt_uuid_t *u2)
+{
+ return memcmp(&u1->value.u128, &u2->value.u128, sizeof(uint128_t));
+}
+
+int bt_uuid16_create(bt_uuid_t *btuuid, uint16_t value)
+{
+ memset(btuuid, 0, sizeof(bt_uuid_t));
+ btuuid->type = BT_UUID16;
+ btuuid->value.u16 = value;
+
+ return 0;
+}
+
+int bt_uuid32_create(bt_uuid_t *btuuid, uint32_t value)
+{
+ memset(btuuid, 0, sizeof(bt_uuid_t));
+ btuuid->type = BT_UUID32;
+ btuuid->value.u32 = value;
+
+ return 0;
+}
+
+int bt_uuid128_create(bt_uuid_t *btuuid, uint128_t value)
+{
+ memset(btuuid, 0, sizeof(bt_uuid_t));
+ btuuid->type = BT_UUID128;
+ btuuid->value.u128 = value;
+
+ return 0;
+}
+
+int bt_uuid_cmp(const bt_uuid_t *uuid1, const bt_uuid_t *uuid2)
+{
+ bt_uuid_t u1, u2;
+
+ bt_uuid2uuid128(uuid1, &u1);
+ bt_uuid2uuid128(uuid2, &u2);
+
+ return bt_uuid128_cmp(&u1, &u2);
+}
diff --git a/lib/uuid.h b/lib/uuid.h
new file mode 100644
index 0000000..bc9ca31
--- /dev/null
+++ b/lib/uuid.h
@@ -0,0 +1,61 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ * Copyright (C) 2011 Marcel Holtmann <[email protected]>
+ *
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __BLUETOOTH_UUID_H
+#define __BLUETOOTH_UUID_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+typedef struct {
+ uint8_t data[16];
+} uint128_t;
+
+typedef struct {
+ enum {
+ BT_UUID16 = 16,
+ BT_UUID32 = 32,
+ BT_UUID128 = 128,
+ } type;
+ union {
+ uint16_t u16;
+ uint32_t u32;
+ uint128_t u128;
+ } value;
+} bt_uuid_t;
+
+int bt_uuid16_create(bt_uuid_t *btuuid, uint16_t value);
+int bt_uuid32_create(bt_uuid_t *btuuid, uint32_t value);
+int bt_uuid128_create(bt_uuid_t *btuuid, uint128_t value);
+
+int bt_uuid_cmp(const bt_uuid_t *uuid1, const bt_uuid_t *uuid2);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BLUETOOTH_UUID_H */
--
1.7.1



2011-03-04 19:54:03

by Brian Gix

[permalink] [raw]
Subject: Re: [PATCH 1/5] Add new UUID utility functions

Hi Lizardo,

On 11-03-04 11:17 AM, Anderson Lizardo wrote:
> Hi Brian,
>
> On Fri, Mar 4, 2011 at 2:57 PM, Brian Gix<[email protected]> wrote:
>> On 11-03-04 10:32 AM, Elvis Pf?tzenreuter wrote:
>>>> I don't believe this line to be always portable between platforms. This
>>>> line makes the assumption that a uint16_t is two native units (not always
>>>> true) and can therefore be directly memcopy'd into into an array of uint8_t
>>>> array members. This is not always true. memcpy should never be used in
>>>> portable code when packing data for network datagram usage models (anything
>>>> that treats data as an octet stream).
>>>
>>> If we had used "unsigned char" and "unsigned short int", I'd agree, but
>>> uint8_t and uint16_t are *explicitly* 8-bit and 16-bit types, and thus there
>>> is a guaranteed 2:1 size relationship.
>>>
>>
>> Unfortunately, this is only part true. There are already CPU architectures
>> in the marketplace which define the smallest addressable unit as being 16
>> bits, which means that even if you have defined a uint8_t that has a valid
>> range of only 0-255, the sizeof(uint8_t) will == 1, and the sizeof(uint16_t)
>> will also == 1, and so a uint16_t of 0x1234 memcpy'd into a uint8_t array
>> will not appear as {0x12, 0x34} but rather as {0x34, 0x00} regardless of
>> your endian-ness (the Most Sig 8 bits hidden by the allowed range). Memcpy
>> is only portability-safe when used to copy between two identical data types.
>> It is also the reason you see things like sizeof(uint16_t) being passed as
>> arguments to the mem* functions.
>>
>> That axiom is also true when copying data between unions and/or stucts with
>> different underlying definitions. The layout of raw bits can never be
>> assumed.
>
> While your explanation looks really interesting (I always thought that
> sizeof() returned the number of bytes), keep in mind that there are
> tons of memcpy() calls beween different datatypes, at least on BlueZ
> and on Linux kernel. I'm not arguing that we should keep it as is, but
> I suppose there will be a lot of changes to be done even before BlueZ
> (or even the kernel) can run on these CPUs.
>
> If I understand your explanation, even memcpy(..., ...,
> sizeof(uint16_t)) would not work on these CPUs, as it copies the
> specified number of *bytes*.
>
> Simply grep for "memcpy" on BlueZ sources to get an idea.
>
> My two cents,


I suppose you are correct that for Linux and BlueZ, the damage is
already done as far as mem* function usage, and that therefore all of my
other objections are moot, and withdraw my fundamental memcpy objection.


However:
You are also correct that sizeof() returns the number of bytes, but
bytes are not in fact the same thing as octets. An octet is used in
networking, and other inter-architecture communication, and is defined
as being exactly eight bits of data.

A byte on the other hand is architecturally defined and is neither
limited to, nor gaurenteed to be at least, 8 bits. It is rather "the
smallest addressable unit" of the target architecture. That is why if
you read networking documents, you are more likely to hear the
underlying data referred to as "octets" instead of bytes. Octets are
precise, and bytes are imprecise.

byte != octet

So memcpy(a1, a2, sizeof(uint16_t)) would work as expected, assuming a1
and a2 were both pointers to objects with underlying 16 bit definitions.

--
Brian Gix
[email protected]
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

2011-03-04 19:17:15

by Anderson Lizardo

[permalink] [raw]
Subject: Re: [PATCH 1/5] Add new UUID utility functions

Hi Brian,

On Fri, Mar 4, 2011 at 2:57 PM, Brian Gix <[email protected]> wrote:
> On 11-03-04 10:32 AM, Elvis Pf?tzenreuter wrote:
>>> I don't believe this line to be always portable between platforms. This
>>> line makes the assumption that a uint16_t is two native units (not always
>>> true) and can therefore be directly memcopy'd into into an array of uint8_t
>>> array members. This is not always true. memcpy should never be used in
>>> portable code when packing data for network datagram usage models (anything
>>> that treats data as an octet stream).
>>
>> If we had used "unsigned char" and "unsigned short int", I'd agree, but
>> uint8_t and uint16_t are *explicitly* 8-bit and 16-bit types, and thus there
>> is a guaranteed 2:1 size relationship.
>>
>
> Unfortunately, this is only part true. There are already CPU architectures
> in the marketplace which define the smallest addressable unit as being 16
> bits, which means that even if you have defined a uint8_t that has a valid
> range of only 0-255, the sizeof(uint8_t) will == 1, and the sizeof(uint16_t)
> will also == 1, and so a uint16_t of 0x1234 memcpy'd into a uint8_t array
> will not appear as {0x12, 0x34} but rather as {0x34, 0x00} regardless of
> your endian-ness (the Most Sig 8 bits hidden by the allowed range). Memcpy
> is only portability-safe when used to copy between two identical data types.
> It is also the reason you see things like sizeof(uint16_t) being passed as
> arguments to the mem* functions.
>
> That axiom is also true when copying data between unions and/or stucts with
> different underlying definitions. The layout of raw bits can never be
> assumed.

While your explanation looks really interesting (I always thought that
sizeof() returned the number of bytes), keep in mind that there are
tons of memcpy() calls beween different datatypes, at least on BlueZ
and on Linux kernel. I'm not arguing that we should keep it as is, but
I suppose there will be a lot of changes to be done even before BlueZ
(or even the kernel) can run on these CPUs.

If I understand your explanation, even memcpy(..., ...,
sizeof(uint16_t)) would not work on these CPUs, as it copies the
specified number of *bytes*.

Simply grep for "memcpy" on BlueZ sources to get an idea.

My two cents,
--
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil

2011-03-04 18:57:34

by Brian Gix

[permalink] [raw]
Subject: Re: [PATCH 1/5] Add new UUID utility functions

Hi Elvis,

On 11-03-04 10:32 AM, Elvis Pf?tzenreuter wrote:
> Hi Brian,
>
> On 4 Mar 2011, at 15:06 , Brian Gix wrote:
>
>> Hi Elvis,
>>
>> I'm trying to understand the problem being addressed by these patches. I am guessing that there is a difference in behaviour between little endian and big endian architectures, but I still question some of the changes.
>>
>> One example below.
>>
>> On 11-03-04 08:20 AM, Elvis Pf?tzenreuter wrote:
>> [...]
>>> +
>>> + memcpy(&uuid128->value.u128.data[BASE_UUID16_OFFSET],&data, 2);
>>
>> I don't believe this line to be always portable between platforms. This line makes the assumption that a uint16_t is two native units (not always true) and can therefore be directly memcopy'd into into an array of uint8_t array members. This is not always true. memcpy should never be used in portable code when packing data for network datagram usage models (anything that treats data as an octet stream).
>
> If we had used "unsigned char" and "unsigned short int", I'd agree, but uint8_t and uint16_t are *explicitly* 8-bit and 16-bit types, and thus there is a guaranteed 2:1 size relationship.
>

Unfortunately, this is only part true. There are already CPU
architectures in the marketplace which define the smallest addressable
unit as being 16 bits, which means that even if you have defined a
uint8_t that has a valid range of only 0-255, the sizeof(uint8_t) will
== 1, and the sizeof(uint16_t) will also == 1, and so a uint16_t of
0x1234 memcpy'd into a uint8_t array will not appear as {0x12, 0x34} but
rather as {0x34, 0x00} regardless of your endian-ness (the Most Sig 8
bits hidden by the allowed range). Memcpy is only portability-safe when
used to copy between two identical data types. It is also the reason you
see things like sizeof(uint16_t) being passed as arguments to the mem*
functions.

That axiom is also true when copying data between unions and/or stucts
with different underlying definitions. The layout of raw bits can never
be assumed.

>>
>> I am not saying I agree with the need to store UUIDs in anything but network order, however if I were to write a portable function that will always work in this instance, I would eliminate all usage of memcpy here and do something like:
>>
>> uuid128->value.u128.data[SHORT_UUID_LE_0] = (uint8_t) data;
>> uuid128->value.u128.data[SHORT_UUID_LE_1] = (uint8_t) (data>> 8);
>>
>> And likewise for uuid32 to uui128:
>> uuid128->value.u128.data[SHORT_UUID_LE_2] = (uint8_t) (data>> 16);
>> uuid128->value.u128.data[SHORT_UUID_LE_3] = (uint8_t) (data>> 24);
>
> I don't feel it's any better. This is Claudio's style, I'd prefer something like
>
> *((uint16_t* )&uuid128->value.u128.data[BASE_UUID16_OFFSET]) = data;

I personally think this slightly preferable to memcpy, but still not
100% portable unless targeted only for 8-bit addressable CPUs.


--
Brian Gix
[email protected]
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

2011-03-04 18:32:00

by Elvis Pfutzenreuter

[permalink] [raw]
Subject: Re: [PATCH 1/5] Add new UUID utility functions

Hi Brian,

On 4 Mar 2011, at 15:06 , Brian Gix wrote:

> Hi Elvis,
>
> I'm trying to understand the problem being addressed by these patches. I am guessing that there is a difference in behaviour between little endian and big endian architectures, but I still question some of the changes.
>
> One example below.
>
> On 11-03-04 08:20 AM, Elvis Pf?tzenreuter wrote:
> [...]
>> +
>> +#if __BYTE_ORDER == __BIG_ENDIAN
>> +static uint128_t bluetooth_base_uuid = {
>> + .data = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
>> + 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB }
>> +};
>> +
>> +#define BASE_UUID16_OFFSET 2
>> +#define BASE_UUID32_OFFSET 0
>> +
>> +#else
>> +static uint128_t bluetooth_base_uuid = {
>> + .data = { 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
>> + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
>> +};
>> +
>> +#define BASE_UUID16_OFFSET 12
>> +#define BASE_UUID32_OFFSET BASE_UUID16_OFFSET
>> +
>> +#endif
>> +
>> +static void bt_uuid16_to_uuid128(const bt_uuid_t *uuid16, bt_uuid_t *uuid128)
>> +{
>> + uint16_t data;
>> +
>> + uuid128->value.u128 = bluetooth_base_uuid;
>> + uuid128->type = BT_UUID128;
>> +
>> + memcpy(&data,&bluetooth_base_uuid.data[BASE_UUID16_OFFSET], 2);
>
> This line should always be copying Zero, and so more directly should be data = 0; These appear to be bluetooth specific, so the 4 MSBs of the base are Zero by definition.
>
>> + data += uuid16->value.u16;
>
> Given the above line, this would become "data = uuid16->value.16", and the other eliminated.

Perhaps we were a bit precious here :)

>
>> +
>> + memcpy(&uuid128->value.u128.data[BASE_UUID16_OFFSET],&data, 2);
>
> I don't believe this line to be always portable between platforms. This line makes the assumption that a uint16_t is two native units (not always true) and can therefore be directly memcopy'd into into an array of uint8_t array members. This is not always true. memcpy should never be used in portable code when packing data for network datagram usage models (anything that treats data as an octet stream).

If we had used "unsigned char" and "unsigned short int", I'd agree, but uint8_t and uint16_t are *explicitly* 8-bit and 16-bit types, and thus there is a guaranteed 2:1 size relationship.

>
> I am not saying I agree with the need to store UUIDs in anything but network order, however if I were to write a portable function that will always work in this instance, I would eliminate all usage of memcpy here and do something like:
>
> uuid128->value.u128.data[SHORT_UUID_LE_0] = (uint8_t) data;
> uuid128->value.u128.data[SHORT_UUID_LE_1] = (uint8_t) (data >> 8);
>
> And likewise for uuid32 to uui128:
> uuid128->value.u128.data[SHORT_UUID_LE_2] = (uint8_t) (data >> 16);
> uuid128->value.u128.data[SHORT_UUID_LE_3] = (uint8_t) (data >> 24);

I don't feel it's any better. This is Claudio's style, I'd prefer something like

*((uint16_t* ) &uuid128->value.u128.data[BASE_UUID16_OFFSET]) = data;

>
>
> Where depending on the endian, SHORT_UUID_LE_0 thru SHORT_UUID_LE_3 would be defined as 3 thru 0 for Big Endian storage, and 12 thru 15 for Little Endian storage.
>
> This is guaranteed to put the desired octet into it's correct position within the uuid128's data array, while it could not be guaranteed across platforms with memcpy.
>
>> +}
>
>
> Regards,
>
> --
> Brian Gix
> [email protected]
> Employee of Qualcomm Innovation Center, Inc.
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum


2011-03-04 18:06:53

by Brian Gix

[permalink] [raw]
Subject: Re: [PATCH 1/5] Add new UUID utility functions

Hi Elvis,

I'm trying to understand the problem being addressed by these patches. I
am guessing that there is a difference in behaviour between little
endian and big endian architectures, but I still question some of the
changes.

One example below.

On 11-03-04 08:20 AM, Elvis Pf?tzenreuter wrote:
[...]
> +
> +#if __BYTE_ORDER == __BIG_ENDIAN
> +static uint128_t bluetooth_base_uuid = {
> + .data = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
> + 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB }
> +};
> +
> +#define BASE_UUID16_OFFSET 2
> +#define BASE_UUID32_OFFSET 0
> +
> +#else
> +static uint128_t bluetooth_base_uuid = {
> + .data = { 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
> + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
> +};
> +
> +#define BASE_UUID16_OFFSET 12
> +#define BASE_UUID32_OFFSET BASE_UUID16_OFFSET
> +
> +#endif
> +
> +static void bt_uuid16_to_uuid128(const bt_uuid_t *uuid16, bt_uuid_t *uuid128)
> +{
> + uint16_t data;
> +
> + uuid128->value.u128 = bluetooth_base_uuid;
> + uuid128->type = BT_UUID128;
> +
> + memcpy(&data,&bluetooth_base_uuid.data[BASE_UUID16_OFFSET], 2);

This line should always be copying Zero, and so more directly should be
data = 0; These appear to be bluetooth specific, so the 4 MSBs of the
base are Zero by definition.

> + data += uuid16->value.u16;

Given the above line, this would become "data = uuid16->value.16", and
the other eliminated.

> +
> + memcpy(&uuid128->value.u128.data[BASE_UUID16_OFFSET],&data, 2);

I don't believe this line to be always portable between platforms. This
line makes the assumption that a uint16_t is two native units (not
always true) and can therefore be directly memcopy'd into into an array
of uint8_t array members. This is not always true. memcpy should never
be used in portable code when packing data for network datagram usage
models (anything that treats data as an octet stream).

I am not saying I agree with the need to store UUIDs in anything but
network order, however if I were to write a portable function that will
always work in this instance, I would eliminate all usage of memcpy here
and do something like:

uuid128->value.u128.data[SHORT_UUID_LE_0] = (uint8_t) data;
uuid128->value.u128.data[SHORT_UUID_LE_1] = (uint8_t) (data >> 8);

And likewise for uuid32 to uui128:
uuid128->value.u128.data[SHORT_UUID_LE_2] = (uint8_t) (data >> 16);
uuid128->value.u128.data[SHORT_UUID_LE_3] = (uint8_t) (data >> 24);


Where depending on the endian, SHORT_UUID_LE_0 thru SHORT_UUID_LE_3
would be defined as 3 thru 0 for Big Endian storage, and 12 thru 15 for
Little Endian storage.

This is guaranteed to put the desired octet into it's correct position
within the uuid128's data array, while it could not be guaranteed across
platforms with memcpy.

> +}


Regards,

--
Brian Gix
[email protected]
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

2011-03-04 16:20:40

by Elvis Pfutzenreuter

[permalink] [raw]
Subject: [PATCH 5/5] Use new UUID functions in example GATT server

---
attrib/example.c | 92 ++++++++++++++++++++++++++++--------------------------
1 files changed, 48 insertions(+), 44 deletions(-)

diff --git a/attrib/example.c b/attrib/example.c
index 395650a..fae288c 100644
--- a/attrib/example.c
+++ b/attrib/example.c
@@ -29,8 +29,7 @@

#include <arpa/inet.h>

-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
+#include <bluetooth/uuid.h>

#include <glib.h>

@@ -70,36 +69,41 @@ static int register_attributes(void)
const char *manufacturer_name2 = "ACME Weighing Scales";
const char *serial1 = "237495-3282-A";
const char *serial2 = "11267-2327A00239";
- const unsigned char char_weight_uuid[] = { 0x80, 0x88, 0xF2, 0x18, 0x90,
- 0x2C, 0x45, 0x0B, 0xB6, 0xC4, 0x62, 0x89, 0x1E, 0x8C, 0x25,
- 0xE9 };
- const unsigned char prim_weight_uuid[] = { 0x4F, 0x0A, 0xC0, 0x96, 0x35,
- 0xD4, 0x49, 0x11, 0x96, 0x31, 0xDE, 0xA8, 0xDC, 0x74, 0xEE,
- 0xFE };
+
+ const uint128_t char_weight_uuid_btorder = {
+ .data = { 0x80, 0x88, 0xF2, 0x18, 0x90, 0x2C, 0x45, 0x0B,
+ 0xB6, 0xC4, 0x62, 0x89, 0x1E, 0x8C, 0x25, 0xE9 } };
+ const uint128_t prim_weight_uuid_btorder = {
+ .data = { 0x4F, 0x0A, 0xC0, 0x96, 0x35, 0xD4, 0x49, 0x11,
+ 0x96, 0x31, 0xDE, 0xA8, 0xDC, 0x74, 0xEE, 0xFE } };
+
+ uint128_t char_weight_uuid;
uint8_t atval[256];
uint32_t handle;
- uuid_t uuid;
+ bt_uuid_t uuid;
int len;

+ btoh128(&char_weight_uuid_btorder, &char_weight_uuid);
+
/* Battery state service: primary service definition */
- sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
+ bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
att_put_u16(BATTERY_STATE_SVC_UUID, &atval[0]);
attrib_db_add(0x0100, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);

/* Battery: battery state characteristic */
- sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
+ bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0110, &atval[1]);
att_put_u16(BATTERY_STATE_UUID, &atval[3]);
attrib_db_add(0x0106, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);

/* Battery: battery state attribute */
- sdp_uuid16_create(&uuid, BATTERY_STATE_UUID);
+ bt_uuid16_create(&uuid, BATTERY_STATE_UUID);
atval[0] = 0x04;
attrib_db_add(0x0110, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 1);

/* Battery: Client Characteristic Configuration */
- sdp_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
+ bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
atval[0] = 0x00;
atval[1] = 0x00;
attrib_db_add(0x0111, &uuid, ATT_NONE, ATT_AUTHENTICATION, atval, 2);
@@ -110,12 +114,12 @@ static int register_attributes(void)
sdp_handles = g_slist_prepend(sdp_handles, GUINT_TO_POINTER(handle));

/* Thermometer: primary service definition */
- sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
+ bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
att_put_u16(THERM_HUMIDITY_SVC_UUID, &atval[0]);
attrib_db_add(0x0200, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);

/* Thermometer: Include */
- sdp_uuid16_create(&uuid, GATT_INCLUDE_UUID);
+ bt_uuid16_create(&uuid, GATT_INCLUDE_UUID);
att_put_u16(0x0500, &atval[0]);
att_put_u16(0x0504, &atval[2]);
att_put_u16(MANUFACTURER_SVC_UUID, &atval[4]);
@@ -128,20 +132,20 @@ static int register_attributes(void)
attrib_db_add(0x0202, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);

/* Thermometer: temperature characteristic */
- sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
+ bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0204, &atval[1]);
att_put_u16(TEMPERATURE_UUID, &atval[3]);
attrib_db_add(0x0203, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);

/* Thermometer: temperature characteristic value */
- sdp_uuid16_create(&uuid, TEMPERATURE_UUID);
+ bt_uuid16_create(&uuid, TEMPERATURE_UUID);
atval[0] = 0x8A;
atval[1] = 0x02;
attrib_db_add(0x0204, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);

/* Thermometer: temperature characteristic format */
- sdp_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
+ bt_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
atval[0] = 0x0E;
atval[1] = 0xFE;
att_put_u16(FMT_CELSIUS_UUID, &atval[2]);
@@ -150,25 +154,25 @@ static int register_attributes(void)
attrib_db_add(0x0205, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 7);

/* Thermometer: characteristic user description */
- sdp_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
+ bt_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
len = strlen(desc_out_temp);
strncpy((char *) atval, desc_out_temp, len);
attrib_db_add(0x0206, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);

/* Thermometer: relative humidity characteristic */
- sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
+ bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0212, &atval[1]);
att_put_u16(RELATIVE_HUMIDITY_UUID, &atval[3]);
attrib_db_add(0x0210, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);

/* Thermometer: relative humidity value */
- sdp_uuid16_create(&uuid, RELATIVE_HUMIDITY_UUID);
+ bt_uuid16_create(&uuid, RELATIVE_HUMIDITY_UUID);
atval[0] = 0x27;
attrib_db_add(0x0212, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 1);

/* Thermometer: relative humidity characteristic format */
- sdp_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
+ bt_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
atval[0] = 0x04;
atval[1] = 0x00;
att_put_u16(FMT_PERCENT_UUID, &atval[2]);
@@ -177,7 +181,7 @@ static int register_attributes(void)
attrib_db_add(0x0213, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 8);

/* Thermometer: characteristic user description */
- sdp_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
+ bt_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
len = strlen(desc_out_hum);
strncpy((char *) atval, desc_out_hum, len);
attrib_db_add(0x0214, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
@@ -188,62 +192,62 @@ static int register_attributes(void)
sdp_handles = g_slist_prepend(sdp_handles, GUINT_TO_POINTER(handle));

/* Secondary Service: Manufacturer Service */
- sdp_uuid16_create(&uuid, GATT_SND_SVC_UUID);
+ bt_uuid16_create(&uuid, GATT_SND_SVC_UUID);
att_put_u16(MANUFACTURER_SVC_UUID, &atval[0]);
attrib_db_add(0x0500, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);

/* Manufacturer name characteristic definition */
- sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
+ bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0502, &atval[1]);
att_put_u16(MANUFACTURER_NAME_UUID, &atval[3]);
attrib_db_add(0x0501, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);

/* Manufacturer name characteristic value */
- sdp_uuid16_create(&uuid, MANUFACTURER_NAME_UUID);
+ bt_uuid16_create(&uuid, MANUFACTURER_NAME_UUID);
len = strlen(manufacturer_name1);
strncpy((char *) atval, manufacturer_name1, len);
attrib_db_add(0x0502, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);

/* Manufacturer serial number characteristic */
- sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
+ bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0504, &atval[1]);
att_put_u16(MANUFACTURER_SERIAL_UUID, &atval[3]);
attrib_db_add(0x0503, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);

/* Manufacturer serial number characteristic value */
- sdp_uuid16_create(&uuid, MANUFACTURER_SERIAL_UUID);
+ bt_uuid16_create(&uuid, MANUFACTURER_SERIAL_UUID);
len = strlen(serial1);
strncpy((char *) atval, serial1, len);
attrib_db_add(0x0504, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);

/* Secondary Service: Manufacturer Service */
- sdp_uuid16_create(&uuid, GATT_SND_SVC_UUID);
+ bt_uuid16_create(&uuid, GATT_SND_SVC_UUID);
att_put_u16(MANUFACTURER_SVC_UUID, &atval[0]);
attrib_db_add(0x0505, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);

/* Manufacturer name characteristic definition */
- sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
+ bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0507, &atval[1]);
att_put_u16(MANUFACTURER_NAME_UUID, &atval[3]);
attrib_db_add(0x0506, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);

/* Secondary Service: Vendor Specific Service */
- sdp_uuid16_create(&uuid, GATT_SND_SVC_UUID);
+ bt_uuid16_create(&uuid, GATT_SND_SVC_UUID);
att_put_u16(VENDOR_SPECIFIC_SVC_UUID, &atval[0]);
attrib_db_add(0x0550, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);

/* Vendor Specific Type characteristic definition */
- sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
+ bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0568, &atval[1]);
att_put_u16(VENDOR_SPECIFIC_TYPE_UUID, &atval[3]);
attrib_db_add(0x0560, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);

/* Vendor Specific Type characteristic value */
- sdp_uuid16_create(&uuid, VENDOR_SPECIFIC_TYPE_UUID);
+ bt_uuid16_create(&uuid, VENDOR_SPECIFIC_TYPE_UUID);
atval[0] = 0x56;
atval[1] = 0x65;
atval[2] = 0x6E;
@@ -253,45 +257,45 @@ static int register_attributes(void)
attrib_db_add(0x0568, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);

/* Manufacturer name attribute */
- sdp_uuid16_create(&uuid, MANUFACTURER_NAME_UUID);
+ bt_uuid16_create(&uuid, MANUFACTURER_NAME_UUID);
len = strlen(manufacturer_name2);
strncpy((char *) atval, manufacturer_name2, len);
attrib_db_add(0x0507, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);

/* Characteristic: serial number */
- sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
+ bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0509, &atval[1]);
att_put_u16(MANUFACTURER_SERIAL_UUID, &atval[3]);
attrib_db_add(0x0508, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);

/* Serial number characteristic value */
- sdp_uuid16_create(&uuid, MANUFACTURER_SERIAL_UUID);
+ bt_uuid16_create(&uuid, MANUFACTURER_SERIAL_UUID);
len = strlen(serial2);
strncpy((char *) atval, serial2, len);
attrib_db_add(0x0509, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);

/* Weight service: primary service definition */
- sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
- memcpy(atval, prim_weight_uuid, 16);
+ bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
+ memcpy(atval, &prim_weight_uuid_btorder, 16);
attrib_db_add(0x0680, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 16);

/* Weight: include */
- sdp_uuid16_create(&uuid, GATT_INCLUDE_UUID);
+ bt_uuid16_create(&uuid, GATT_INCLUDE_UUID);
att_put_u16(0x0505, &atval[0]);
att_put_u16(0x0509, &atval[2]);
att_put_u16(MANUFACTURER_SVC_UUID, &atval[4]);
attrib_db_add(0x0681, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);

/* Weight: characteristic */
- sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
+ bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0683, &atval[1]);
- memcpy(&atval[3], char_weight_uuid, 16);
+ memcpy(&atval[3], &char_weight_uuid_btorder, 16);
attrib_db_add(0x0682, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 19);

/* Weight: characteristic value */
- sdp_uuid128_create(&uuid, char_weight_uuid);
+ bt_uuid128_create(&uuid, char_weight_uuid);
atval[0] = 0x82;
atval[1] = 0x55;
atval[2] = 0x00;
@@ -299,7 +303,7 @@ static int register_attributes(void)
attrib_db_add(0x0683, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 4);

/* Weight: characteristic format */
- sdp_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
+ bt_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
atval[0] = 0x08;
atval[1] = 0xFD;
att_put_u16(FMT_KILOGRAM_UUID, &atval[2]);
@@ -308,7 +312,7 @@ static int register_attributes(void)
attrib_db_add(0x0684, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 8);

/* Weight: characteristic user description */
- sdp_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
+ bt_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
len = strlen(desc_weight);
strncpy((char *) atval, desc_weight, len);
attrib_db_add(0x0685, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
--
1.7.1


2011-03-04 16:20:39

by Elvis Pfutzenreuter

[permalink] [raw]
Subject: [PATCH 4/5] Use new UUID functions in GATT

This patch puts the new UUID functions into use for GATT-related
code, and adds some convenience functions to ATT API (att.h).
---
attrib/att.c | 47 +++++++++++--------------
attrib/att.h | 69 +++++++++++++++++++++++++++++++++----
attrib/client.c | 26 ++++++--------
attrib/gatt.c | 71 ++++++++++++++++++++------------------
attrib/gatt.h | 4 +-
attrib/gattrib.c | 3 +-
attrib/gatttool.c | 18 ++++-----
attrib/interactive.c | 22 +++++------
attrib/utils.c | 1 +
src/adapter.c | 1 +
src/attrib-server.c | 93 +++++++++++++++++++++++++------------------------
src/attrib-server.h | 4 +-
src/device.c | 1 +
src/main.c | 1 +
14 files changed, 204 insertions(+), 157 deletions(-)

diff --git a/attrib/att.c b/attrib/att.c
index b96b97d..08000e0 100644
--- a/attrib/att.c
+++ b/attrib/att.c
@@ -27,8 +27,7 @@
#include <stdlib.h>

#include <bluetooth/bluetooth.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
+#include <bluetooth/uuid.h>

#include <glib.h>

@@ -110,7 +109,7 @@ struct att_data_list *att_data_list_alloc(uint16_t num, uint16_t len)
return list;
}

-uint16_t enc_read_by_grp_req(uint16_t start, uint16_t end, uuid_t *uuid,
+uint16_t enc_read_by_grp_req(uint16_t start, uint16_t end, bt_uuid_t *uuid,
uint8_t *pdu, int len)
{
const uint16_t min_len = sizeof(pdu[0]) + sizeof(start) + sizeof(end);
@@ -119,9 +118,9 @@ uint16_t enc_read_by_grp_req(uint16_t start, uint16_t end, uuid_t *uuid,
if (!uuid)
return 0;

- if (uuid->type == SDP_UUID16)
+ if (uuid->type == BT_UUID16)
length = 2;
- else if (uuid->type == SDP_UUID128)
+ else if (uuid->type == BT_UUID128)
length = 16;
else
return 0;
@@ -133,16 +132,13 @@ uint16_t enc_read_by_grp_req(uint16_t start, uint16_t end, uuid_t *uuid,
att_put_u16(start, &pdu[1]);
att_put_u16(end, &pdu[3]);

- if (uuid->type == SDP_UUID16)
- att_put_u16(uuid->value.uuid16, &pdu[5]);
- else
- memcpy(&pdu[5], &uuid->value.uuid128, length);
+ att_put_uuid(*uuid, &pdu[5]);

return min_len + length;
}

uint16_t dec_read_by_grp_req(const uint8_t *pdu, int len, uint16_t *start,
- uint16_t *end, uuid_t *uuid)
+ uint16_t *end, bt_uuid_t *uuid)
{
const uint16_t min_len = sizeof(pdu[0]) + sizeof(*start) + sizeof(*end);

@@ -161,9 +157,9 @@ uint16_t dec_read_by_grp_req(const uint8_t *pdu, int len, uint16_t *start,
*start = att_get_u16(&pdu[1]);
*end = att_get_u16(&pdu[3]);
if (len == min_len + 2)
- sdp_uuid16_create(uuid, att_get_u16(&pdu[5]));
+ *uuid = att_get_uuid16(&pdu[5]);
else
- sdp_uuid128_create(uuid, &pdu[5]);
+ *uuid = att_get_uuid128(&pdu[5]);

return len;
}
@@ -219,7 +215,7 @@ struct att_data_list *dec_read_by_grp_resp(const uint8_t *pdu, int len)
return list;
}

-uint16_t enc_find_by_type_req(uint16_t start, uint16_t end, uuid_t *uuid,
+uint16_t enc_find_by_type_req(uint16_t start, uint16_t end, bt_uuid_t *uuid,
const uint8_t *value, int vlen, uint8_t *pdu, int len)
{
uint16_t min_len = sizeof(pdu[0]) + sizeof(start) + sizeof(end) +
@@ -231,7 +227,7 @@ uint16_t enc_find_by_type_req(uint16_t start, uint16_t end, uuid_t *uuid,
if (!uuid)
return 0;

- if (uuid->type != SDP_UUID16)
+ if (uuid->type != BT_UUID16)
return 0;

if (len < min_len)
@@ -243,7 +239,7 @@ uint16_t enc_find_by_type_req(uint16_t start, uint16_t end, uuid_t *uuid,
pdu[0] = ATT_OP_FIND_BY_TYPE_REQ;
att_put_u16(start, &pdu[1]);
att_put_u16(end, &pdu[3]);
- att_put_u16(uuid->value.uuid16, &pdu[5]);
+ att_put_uuid16(*uuid, &pdu[5]);

if (vlen > 0) {
memcpy(&pdu[7], value, vlen);
@@ -254,7 +250,7 @@ uint16_t enc_find_by_type_req(uint16_t start, uint16_t end, uuid_t *uuid,
}

uint16_t dec_find_by_type_req(const uint8_t *pdu, int len, uint16_t *start,
- uint16_t *end, uuid_t *uuid, uint8_t *value, int *vlen)
+ uint16_t *end, bt_uuid_t *uuid, uint8_t *value, int *vlen)
{
int valuelen;
uint16_t min_len = sizeof(pdu[0]) + sizeof(*start) +
@@ -279,7 +275,7 @@ uint16_t dec_find_by_type_req(const uint8_t *pdu, int len, uint16_t *start,

/* Always UUID16 */
if (uuid)
- sdp_uuid16_create(uuid, att_get_u16(&pdu[5]));
+ *uuid = att_get_uuid16(&pdu[5]);

valuelen = len - min_len;

@@ -337,7 +333,7 @@ GSList *dec_find_by_type_resp(const uint8_t *pdu, int len)
return matches;
}

-uint16_t enc_read_by_type_req(uint16_t start, uint16_t end, uuid_t *uuid,
+uint16_t enc_read_by_type_req(uint16_t start, uint16_t end, bt_uuid_t *uuid,
uint8_t *pdu, int len)
{
const uint16_t min_len = sizeof(pdu[0]) + sizeof(start) + sizeof(end);
@@ -346,9 +342,9 @@ uint16_t enc_read_by_type_req(uint16_t start, uint16_t end, uuid_t *uuid,
if (!uuid)
return 0;

- if (uuid->type == SDP_UUID16)
+ if (uuid->type == BT_UUID16)
length = 2;
- else if (uuid->type == SDP_UUID128)
+ else if (uuid->type == BT_UUID128)
length = 16;
else
return 0;
@@ -360,16 +356,13 @@ uint16_t enc_read_by_type_req(uint16_t start, uint16_t end, uuid_t *uuid,
att_put_u16(start, &pdu[1]);
att_put_u16(end, &pdu[3]);

- if (uuid->type == SDP_UUID16)
- att_put_u16(uuid->value.uuid16, &pdu[5]);
- else
- memcpy(&pdu[5], &uuid->value.uuid128, length);
+ att_put_uuid(*uuid, &pdu[5]);

return min_len + length;
}

uint16_t dec_read_by_type_req(const uint8_t *pdu, int len, uint16_t *start,
- uint16_t *end, uuid_t *uuid)
+ uint16_t *end, bt_uuid_t *uuid)
{
const uint16_t min_len = sizeof(pdu[0]) + sizeof(*start) + sizeof(*end);

@@ -389,9 +382,9 @@ uint16_t dec_read_by_type_req(const uint8_t *pdu, int len, uint16_t *start,
*end = att_get_u16(&pdu[3]);

if (len == min_len + 2)
- sdp_uuid16_create(uuid, att_get_u16(&pdu[5]));
+ *uuid = att_get_uuid16(&pdu[5]);
else
- sdp_uuid128_create(uuid, &pdu[5]);
+ *uuid = att_get_uuid128(&pdu[5]);

return len;
}
diff --git a/attrib/att.h b/attrib/att.h
index b62f254..7a83bfa 100644
--- a/attrib/att.h
+++ b/attrib/att.h
@@ -120,7 +120,7 @@ enum {

struct attribute {
uint16_t handle;
- uuid_t uuid;
+ bt_uuid_t uuid;
int read_reqs;
int write_reqs;
uint8_t (*read_cb)(struct attribute *a, gpointer user_data);
@@ -173,6 +173,16 @@ static inline uint32_t att_get_u32(const void *ptr)
return btohl(bt_get_unaligned(u32_ptr));
}

+static inline uint128_t att_get_u128(const void *ptr)
+{
+ const uint128_t *u128_ptr = ptr;
+ uint128_t dst;
+
+ btoh128(u128_ptr, &dst);
+
+ return dst;
+}
+
static inline void att_put_u8(uint8_t src, void *dst)
{
bt_put_unaligned(src, (uint8_t *) dst);
@@ -188,26 +198,71 @@ static inline void att_put_u32(uint32_t src, void *dst)
bt_put_unaligned(htobl(src), (uint32_t *) dst);
}

+static inline void att_put_u128(uint128_t src, void *dst)
+{
+ uint128_t *d128 = dst;
+
+ htob128(&src, d128);
+}
+
+static inline void att_put_uuid16(bt_uuid_t src, void *dst)
+{
+ att_put_u16(src.value.u16, dst);
+}
+
+static inline void att_put_uuid128(bt_uuid_t src, void *dst)
+{
+ att_put_u128(src.value.u128, dst);
+}
+
+static inline void att_put_uuid(bt_uuid_t src, void *dst)
+{
+ if (src.type == BT_UUID16)
+ att_put_uuid16(src, dst);
+ else
+ att_put_uuid128(src, dst);
+}
+
+static inline bt_uuid_t att_get_uuid16(const void *ptr)
+{
+ bt_uuid_t uuid;
+
+ bt_uuid16_create(&uuid, att_get_u16(ptr));
+
+ return uuid;
+}
+
+static inline bt_uuid_t att_get_uuid128(const void *ptr)
+{
+ bt_uuid_t uuid;
+ uint128_t value;
+
+ value = att_get_u128(ptr);
+ bt_uuid128_create(&uuid, value);
+
+ return uuid;
+}
+
struct att_data_list *att_data_list_alloc(uint16_t num, uint16_t len);
void att_data_list_free(struct att_data_list *list);

const char *att_ecode2str(uint8_t status);
-uint16_t enc_read_by_grp_req(uint16_t start, uint16_t end, uuid_t *uuid,
+uint16_t enc_read_by_grp_req(uint16_t start, uint16_t end, bt_uuid_t *uuid,
uint8_t *pdu, int len);
uint16_t dec_read_by_grp_req(const uint8_t *pdu, int len, uint16_t *start,
- uint16_t *end, uuid_t *uuid);
+ uint16_t *end, bt_uuid_t *uuid);
uint16_t enc_read_by_grp_resp(struct att_data_list *list, uint8_t *pdu, int len);
-uint16_t enc_find_by_type_req(uint16_t start, uint16_t end, uuid_t *uuid,
+uint16_t enc_find_by_type_req(uint16_t start, uint16_t end, bt_uuid_t *uuid,
const uint8_t *value, int vlen, uint8_t *pdu, int len);
uint16_t dec_find_by_type_req(const uint8_t *pdu, int len, uint16_t *start,
- uint16_t *end, uuid_t *uuid, uint8_t *value, int *vlen);
+ uint16_t *end, bt_uuid_t *uuid, uint8_t *value, int *vlen);
uint16_t enc_find_by_type_resp(GSList *ranges, uint8_t *pdu, int len);
GSList *dec_find_by_type_resp(const uint8_t *pdu, int len);
struct att_data_list *dec_read_by_grp_resp(const uint8_t *pdu, int len);
-uint16_t enc_read_by_type_req(uint16_t start, uint16_t end, uuid_t *uuid,
+uint16_t enc_read_by_type_req(uint16_t start, uint16_t end, bt_uuid_t *uuid,
uint8_t *pdu, int len);
uint16_t dec_read_by_type_req(const uint8_t *pdu, int len, uint16_t *start,
- uint16_t *end, uuid_t *uuid);
+ uint16_t *end, bt_uuid_t *uuid);
uint16_t enc_read_by_type_resp(struct att_data_list *list, uint8_t *pdu,
int len);
uint16_t enc_write_cmd(uint16_t handle, const uint8_t *value, int vlen,
diff --git a/attrib/client.c b/attrib/client.c
index 97b1156..5088b27 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -32,15 +32,13 @@
#include <glib.h>

#include <bluetooth/bluetooth.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
+#include <bluetooth/uuid.h>

#include "adapter.h"
#include "device.h"
#include "log.h"
#include "gdbus.h"
#include "error.h"
-#include "glib-helper.h"
#include "dbus-common.h"
#include "btio.h"
#include "storage.h"
@@ -665,16 +663,14 @@ static void load_characteristics(gpointer data, gpointer user_data)
static void store_attribute(struct gatt_service *gatt, uint16_t handle,
uint16_t type, uint8_t *value, gsize len)
{
- uuid_t uuid;
- char *str, *uuidstr, *tmp;
+ bt_uuid_t uuid;
+ char *str, *tmp;
guint i;

str = g_malloc0(MAX_LEN_UUID_STR + len * 2 + 1);

- sdp_uuid16_create(&uuid, type);
- uuidstr = bt_uuid2string(&uuid);
- strcpy(str, uuidstr);
- g_free(uuidstr);
+ bt_uuid16_create(&uuid, type);
+ bt_uuid_to_string(&uuid, str, MAX_LEN_UUID_STR);

str[MAX_LEN_UUID_STR - 1] = '#';

@@ -770,13 +766,13 @@ static void update_char_value(guint8 status, const guint8 *pdu,
g_free(current);
}

-static int uuid_desc16_cmp(uuid_t *uuid, guint16 desc)
+static int uuid_desc16_cmp(bt_uuid_t *uuid, guint16 desc)
{
- uuid_t u16;
+ bt_uuid_t u16;

- sdp_uuid16_create(&u16, desc);
+ bt_uuid16_create(&u16, desc);

- return sdp_uuid_cmp(uuid, &u16);
+ return bt_uuid_cmp(uuid, &u16);
}

static void descriptor_cb(guint8 status, const guint8 *pdu, guint16 plen,
@@ -799,14 +795,14 @@ static void descriptor_cb(guint8 status, const guint8 *pdu, guint16 plen,

for (i = 0; i < list->num; i++) {
guint16 handle;
- uuid_t uuid;
+ bt_uuid_t uuid;
uint8_t *info = list->data[i];
struct query_data *qfmt;

handle = att_get_u16(info);

if (format == 0x01) {
- sdp_uuid16_create(&uuid, att_get_u16(&info[2]));
+ uuid = att_get_uuid16(&info[2]);
} else {
/* Currently, only "user description" and "presentation
* format" descriptors are used, and both have 16-bit
diff --git a/attrib/gatt.c b/attrib/gatt.c
index 20bb96f..4574ac4 100644
--- a/attrib/gatt.c
+++ b/attrib/gatt.c
@@ -24,8 +24,7 @@

#include <stdint.h>
#include <glib.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
+#include <bluetooth/uuid.h>

#include "att.h"
#include "gattrib.h"
@@ -33,7 +32,7 @@

struct discover_primary {
GAttrib *attrib;
- uuid_t uuid;
+ bt_uuid_t uuid;
GSList *primaries;
gatt_cb_t cb;
void *user_data;
@@ -41,7 +40,7 @@ struct discover_primary {

struct discover_char {
GAttrib *attrib;
- uuid_t uuid;
+ bt_uuid_t uuid;
uint16_t end;
GSList *characteristics;
gatt_cb_t cb;
@@ -64,31 +63,35 @@ static void discover_char_free(struct discover_char *dc)
}

static guint16 encode_discover_primary(uint16_t start, uint16_t end,
- uuid_t *uuid, uint8_t *pdu, size_t len)
+ bt_uuid_t *uuid, uint8_t *pdu, size_t len)
{
- uuid_t prim;
+ bt_uuid_t prim;
guint16 plen;
uint8_t op;

- sdp_uuid16_create(&prim, GATT_PRIM_SVC_UUID);
+ bt_uuid16_create(&prim, GATT_PRIM_SVC_UUID);

if (uuid == NULL) {
/* Discover all primary services */
op = ATT_OP_READ_BY_GROUP_REQ;
plen = enc_read_by_grp_req(start, end, &prim, pdu, len);
} else {
+ uint16_t u16;
+ uint128_t u128;
const void *value;
int vlen;

/* Discover primary service by service UUID */
op = ATT_OP_FIND_BY_TYPE_REQ;

- if (uuid->type == SDP_UUID16) {
- value = &uuid->value.uuid16;
- vlen = sizeof(uuid->value.uuid16);
+ if (uuid->type == BT_UUID16) {
+ u16 = htobs(uuid->value.u16);
+ value = &u16;
+ vlen = sizeof(u16);
} else {
- value = &uuid->value.uuid128;
- vlen = sizeof(uuid->value.uuid128);
+ htob128(&uuid->value.u128, &u128);
+ value = &u128;
+ vlen = sizeof(u128);
}

plen = enc_find_by_type_req(start, end, &prim, value, vlen,
@@ -163,21 +166,20 @@ static void primary_all_cb(guint8 status, const guint8 *ipdu, guint16 iplen,
for (i = 0, end = 0; i < list->num; i++) {
const uint8_t *data = list->data[i];
struct att_primary *primary;
- uuid_t u128, u16;
+ bt_uuid_t uuid;

start = att_get_u16(&data[0]);
end = att_get_u16(&data[2]);

if (list->len == 6) {
- sdp_uuid16_create(&u16,
- att_get_u16(&data[4]));
- sdp_uuid16_to_uuid128(&u128, &u16);
-
- } else if (list->len == 20)
- sdp_uuid128_create(&u128, &data[4]);
- else
+ uuid = att_get_uuid16(&data[4]);
+ bt_uuid_to_uuid128(&uuid);
+ } else if (list->len == 20) {
+ uuid = att_get_uuid128(&data[4]);
+ } else {
/* Skipping invalid data */
continue;
+ }

primary = g_try_new0(struct att_primary, 1);
if (!primary) {
@@ -186,7 +188,7 @@ static void primary_all_cb(guint8 status, const guint8 *ipdu, guint16 iplen,
}
primary->start = start;
primary->end = end;
- sdp_uuid2strn(&u128, primary->uuid, sizeof(primary->uuid));
+ bt_uuid_to_string(&uuid, primary->uuid, sizeof(primary->uuid));
dp->primaries = g_slist_append(dp->primaries, primary);
}

@@ -209,7 +211,7 @@ done:
discover_primary_free(dp);
}

-guint gatt_discover_primary(GAttrib *attrib, uuid_t *uuid, gatt_cb_t func,
+guint gatt_discover_primary(GAttrib *attrib, bt_uuid_t *uuid, gatt_cb_t func,
gpointer user_data)
{
struct discover_primary *dp;
@@ -230,7 +232,7 @@ guint gatt_discover_primary(GAttrib *attrib, uuid_t *uuid, gatt_cb_t func,
dp->user_data = user_data;

if (uuid) {
- memcpy(&dp->uuid, uuid, sizeof(uuid_t));
+ memcpy(&dp->uuid, uuid, sizeof(bt_uuid_t));
cb = primary_by_uuid_cb;
} else
cb = primary_all_cb;
@@ -246,7 +248,7 @@ static void char_discovered_cb(guint8 status, const guint8 *ipdu, guint16 iplen,
unsigned int i, err;
uint8_t opdu[ATT_DEFAULT_LE_MTU];
guint16 oplen;
- uuid_t uuid;
+ bt_uuid_t uuid;
uint16_t last = 0;

if (status) {
@@ -263,15 +265,16 @@ static void char_discovered_cb(guint8 status, const guint8 *ipdu, guint16 iplen,
for (i = 0; i < list->num; i++) {
uint8_t *value = list->data[i];
struct att_char *chars;
- uuid_t u128, u16;
+ bt_uuid_t uuid;

last = att_get_u16(value);

if (list->len == 7) {
- sdp_uuid16_create(&u16, att_get_u16(&value[5]));
- sdp_uuid16_to_uuid128(&u128, &u16);
- } else
- sdp_uuid128_create(&u128, &value[5]);
+ uuid = att_get_uuid16(&value[5]);
+ bt_uuid_to_uuid128(&uuid);
+ } else {
+ uuid = att_get_uuid128(&value[5]);
+ }

chars = g_try_new0(struct att_char, 1);
if (!chars) {
@@ -282,7 +285,7 @@ static void char_discovered_cb(guint8 status, const guint8 *ipdu, guint16 iplen,
chars->handle = last;
chars->properties = value[2];
chars->value_handle = att_get_u16(&value[3]);
- sdp_uuid2strn(&u128, chars->uuid, sizeof(chars->uuid));
+ bt_uuid_to_string(&uuid, chars->uuid, sizeof(chars->uuid));
dc->characteristics = g_slist_append(dc->characteristics,
chars);
}
@@ -291,7 +294,7 @@ static void char_discovered_cb(guint8 status, const guint8 *ipdu, guint16 iplen,
err = 0;

if (last != 0) {
- sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
+ bt_uuid16_create(&uuid, GATT_CHARAC_UUID);

oplen = enc_read_by_type_req(last + 1, dc->end, &uuid, opdu,
sizeof(opdu));
@@ -316,9 +319,9 @@ guint gatt_discover_char(GAttrib *attrib, uint16_t start, uint16_t end,
uint8_t pdu[ATT_DEFAULT_LE_MTU];
struct discover_char *dc;
guint16 plen;
- uuid_t uuid;
+ bt_uuid_t uuid;

- sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
+ bt_uuid16_create(&uuid, GATT_CHARAC_UUID);

plen = enc_read_by_type_req(start, end, &uuid, pdu, sizeof(pdu));
if (plen == 0)
@@ -338,7 +341,7 @@ guint gatt_discover_char(GAttrib *attrib, uint16_t start, uint16_t end,
}

guint gatt_read_char_by_uuid(GAttrib *attrib, uint16_t start, uint16_t end,
- uuid_t *uuid, GAttribResultFunc func,
+ bt_uuid_t *uuid, GAttribResultFunc func,
gpointer user_data)
{
uint8_t pdu[ATT_DEFAULT_LE_MTU];
diff --git a/attrib/gatt.h b/attrib/gatt.h
index 9f69646..9731f1a 100644
--- a/attrib/gatt.h
+++ b/attrib/gatt.h
@@ -26,7 +26,7 @@

typedef void (*gatt_cb_t) (GSList *l, guint8 status, gpointer user_data);

-guint gatt_discover_primary(GAttrib *attrib, uuid_t *uuid, gatt_cb_t func,
+guint gatt_discover_primary(GAttrib *attrib, bt_uuid_t *uuid, gatt_cb_t func,
gpointer user_data);

guint gatt_discover_char(GAttrib *attrib, uint16_t start, uint16_t end,
@@ -45,5 +45,5 @@ guint gatt_write_cmd(GAttrib *attrib, uint16_t handle, uint8_t *value, int vlen,
GDestroyNotify notify, gpointer user_data);

guint gatt_read_char_by_uuid(GAttrib *attrib, uint16_t start, uint16_t end,
- uuid_t *uuid, GAttribResultFunc func,
+ bt_uuid_t *uuid, GAttribResultFunc func,
gpointer user_data);
diff --git a/attrib/gattrib.c b/attrib/gattrib.c
index c4cfd95..07e56de 100644
--- a/attrib/gattrib.c
+++ b/attrib/gattrib.c
@@ -29,8 +29,7 @@
#include <stdio.h>

#include <bluetooth/bluetooth.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
+#include <bluetooth/uuid.h>

#include "att.h"
#include "btio.h"
diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index 420fc91..f7abd23 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -34,13 +34,11 @@
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
+#include <bluetooth/uuid.h>

#include "att.h"
#include "btio.h"
#include "gattrib.h"
-#include "glib-helper.h"
#include "gatt.h"
#include "gatttool.h"

@@ -48,7 +46,7 @@ static gchar *opt_src = NULL;
static gchar *opt_dst = NULL;
static gchar *opt_value = NULL;
static gchar *opt_sec_level = NULL;
-static uuid_t *opt_uuid = NULL;
+static bt_uuid_t *opt_uuid = NULL;
static int opt_start = 0x0001;
static int opt_end = 0xffff;
static int opt_handle = -1;
@@ -426,17 +424,17 @@ static void char_desc_cb(guint8 status, const guint8 *pdu, guint16 plen,
char uuidstr[MAX_LEN_UUID_STR];
uint16_t handle;
uint8_t *value;
- uuid_t uuid;
+ bt_uuid_t uuid;

value = list->data[i];
handle = att_get_u16(value);

if (format == 0x01)
- sdp_uuid16_create(&uuid, att_get_u16(&value[2]));
+ uuid = att_get_uuid16(&value[2]);
else
- sdp_uuid128_create(&uuid, &value[2]);
+ uuid = att_get_uuid128(&value[2]);

- sdp_uuid2strn(&uuid, uuidstr, MAX_LEN_UUID_STR);
+ bt_uuid_to_string(&uuid, uuidstr, MAX_LEN_UUID_STR);
g_print("handle = 0x%04x, uuid = %s\n", handle, uuidstr);
}

@@ -462,11 +460,11 @@ static gboolean parse_uuid(const char *key, const char *value,
if (!value)
return FALSE;

- opt_uuid = g_try_malloc(sizeof(uuid_t));
+ opt_uuid = g_try_malloc(sizeof(bt_uuid_t));
if (opt_uuid == NULL)
return FALSE;

- if (bt_string2uuid(opt_uuid, value) < 0)
+ if (bt_string_to_uuid(opt_uuid, value) < 0)
return FALSE;

return TRUE;
diff --git a/attrib/interactive.c b/attrib/interactive.c
index ff676b4..bc8efbc 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -26,8 +26,7 @@
#include <stdio.h>
#include <glib.h>

-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
+#include <bluetooth/uuid.h>

#include <readline/readline.h>
#include <readline/history.h>
@@ -35,7 +34,6 @@
#include "att.h"
#include "btio.h"
#include "gattrib.h"
-#include "glib-helper.h"
#include "gatt.h"
#include "gatttool.h"

@@ -54,7 +52,7 @@ struct characteristic_data {
uint16_t orig_start;
uint16_t start;
uint16_t end;
- uuid_t uuid;
+ bt_uuid_t uuid;
};

static void cmd_help(int argcp, char **argvp);
@@ -198,17 +196,17 @@ static void char_desc_cb(guint8 status, const guint8 *pdu, guint16 plen,
char uuidstr[MAX_LEN_UUID_STR];
uint16_t handle;
uint8_t *value;
- uuid_t uuid;
+ bt_uuid_t uuid;

value = list->data[i];
handle = att_get_u16(value);

if (format == 0x01)
- sdp_uuid16_create(&uuid, att_get_u16(&value[2]));
+ uuid = att_get_uuid16(&value[2]);
else
- sdp_uuid128_create(&uuid, &value[2]);
+ uuid = att_get_uuid128(&value[2]);

- sdp_uuid2strn(&uuid, uuidstr, MAX_LEN_UUID_STR);
+ bt_uuid_to_string(&uuid, uuidstr, MAX_LEN_UUID_STR);
printf("handle: 0x%04x, uuid: %s\n", handle, uuidstr);
}

@@ -339,7 +337,7 @@ static void cmd_disconnect(int argcp, char **argvp)

static void cmd_primary(int argcp, char **argvp)
{
- uuid_t uuid;
+ bt_uuid_t uuid;

if (conn_state != STATE_CONNECTED) {
printf("Command failed: disconnected\n");
@@ -351,7 +349,7 @@ static void cmd_primary(int argcp, char **argvp)
return;
}

- if (bt_string2uuid(&uuid, argvp[1]) < 0) {
+ if (bt_string_to_uuid(&uuid, argvp[1]) < 0) {
printf("Invalid UUID\n");
return;
}
@@ -458,7 +456,7 @@ static void cmd_read_uuid(int argcp, char **argvp)
struct characteristic_data *char_data;
int start = 0x0001;
int end = 0xffff;
- uuid_t uuid;
+ bt_uuid_t uuid;

if (conn_state != STATE_CONNECTED) {
printf("Command failed: disconnected\n");
@@ -470,7 +468,7 @@ static void cmd_read_uuid(int argcp, char **argvp)
return;
}

- if (bt_string2uuid(&uuid, argvp[1]) < 0) {
+ if (bt_string_to_uuid(&uuid, argvp[1]) < 0) {
printf("Invalid UUID\n");
return;
}
diff --git a/attrib/utils.c b/attrib/utils.c
index 8d1ca74..5f4444a 100644
--- a/attrib/utils.c
+++ b/attrib/utils.c
@@ -27,6 +27,7 @@
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
+#include <bluetooth/uuid.h>
#include <bluetooth/sdp.h>

#include "gattrib.h"
diff --git a/src/adapter.c b/src/adapter.c
index 2e11832..f74d3f0 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -34,6 +34,7 @@
#include <sys/ioctl.h>

#include <bluetooth/bluetooth.h>
+#include <bluetooth/uuid.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>

diff --git a/src/attrib-server.c b/src/attrib-server.c
index b980b28..b0dde52 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -33,6 +33,7 @@
#include <glib.h>

#include <bluetooth/bluetooth.h>
+#include <bluetooth/uuid.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>

@@ -80,13 +81,13 @@ static uint32_t gap_sdp_handle = 0;
static uint16_t name_handle = 0x0000;
static uint16_t appearance_handle = 0x0000;

-static uuid_t prim_uuid = {
- .type = SDP_UUID16,
- .value.uuid16 = GATT_PRIM_SVC_UUID
+static bt_uuid_t prim_uuid = {
+ .type = BT_UUID16,
+ .value.u16 = GATT_PRIM_SVC_UUID
};
-static uuid_t snd_uuid = {
- .type = SDP_UUID16,
- .value.uuid16 = GATT_SND_SVC_UUID
+static bt_uuid_t snd_uuid = {
+ .type = BT_UUID16,
+ .value.u16 = GATT_SND_SVC_UUID
};

static sdp_record_t *server_record_new(uuid_t *uuid, uint16_t start, uint16_t end)
@@ -198,12 +199,12 @@ static uint8_t client_set_notifications(struct attribute *attr,
struct attribute *last_chr_val = NULL;
uint16_t cfg_val;
uint8_t props;
- uuid_t uuid;
+ bt_uuid_t uuid;
GSList *l;

cfg_val = att_get_u16(attr->data);

- sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
+ bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
for (l = database, props = 0; l != NULL; l = l->next) {
struct attribute *a = l->data;
static uint16_t handle = 0;
@@ -211,7 +212,7 @@ static uint8_t client_set_notifications(struct attribute *attr,
if (a->handle >= attr->handle)
break;

- if (sdp_uuid_cmp(&a->uuid, &uuid) == 0) {
+ if (bt_uuid_cmp(&a->uuid, &uuid) == 0) {
props = att_get_u8(&a->data[0]);
handle = att_get_u16(&a->data[1]);
continue;
@@ -250,11 +251,11 @@ static struct attribute *client_cfg_attribute(struct gatt_channel *channel,
const uint8_t *value, int vlen)
{
guint handle = orig_attr->handle;
- uuid_t uuid;
+ bt_uuid_t uuid;
GSList *l;

- sdp_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
- if (sdp_uuid_cmp(&orig_attr->uuid, &uuid) != 0)
+ bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
+ if (bt_uuid_cmp(&orig_attr->uuid, &uuid) != 0)
return NULL;

/* Value is unchanged, not need to create a private copy yet */
@@ -284,7 +285,7 @@ static struct attribute *client_cfg_attribute(struct gatt_channel *channel,
}

static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start,
- uint16_t end, uuid_t *uuid,
+ uint16_t end, bt_uuid_t *uuid,
uint8_t *pdu, int len)
{
struct att_data_list *adl;
@@ -304,8 +305,8 @@ static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start,
* types may be used in the Read By Group Type Request.
*/

- if (sdp_uuid_cmp(uuid, &prim_uuid) != 0 &&
- sdp_uuid_cmp(uuid, &snd_uuid) != 0)
+ if (bt_uuid_cmp(uuid, &prim_uuid) != 0 &&
+ bt_uuid_cmp(uuid, &snd_uuid) != 0)
return enc_error_resp(ATT_OP_READ_BY_GROUP_REQ, 0x0000,
ATT_ECODE_UNSUPP_GRP_TYPE, pdu, len);

@@ -322,13 +323,13 @@ static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start,
break;

/* The old group ends when a new one starts */
- if (old && (sdp_uuid_cmp(&a->uuid, &prim_uuid) == 0 ||
- sdp_uuid_cmp(&a->uuid, &snd_uuid) == 0)) {
+ if (old && (bt_uuid_cmp(&a->uuid, &prim_uuid) == 0 ||
+ bt_uuid_cmp(&a->uuid, &snd_uuid) == 0)) {
old->end = last_handle;
old = NULL;
}

- if (sdp_uuid_cmp(&a->uuid, uuid) != 0) {
+ if (bt_uuid_cmp(&a->uuid, uuid) != 0) {
/* Still inside a service, update its last handle */
if (old)
last_handle = a->handle;
@@ -404,7 +405,7 @@ static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start,
}

static uint16_t read_by_type(struct gatt_channel *channel, uint16_t start,
- uint16_t end, uuid_t *uuid,
+ uint16_t end, bt_uuid_t *uuid,
uint8_t *pdu, int len)
{
struct att_data_list *adl;
@@ -429,7 +430,7 @@ static uint16_t read_by_type(struct gatt_channel *channel, uint16_t start,
if (a->handle >= end)
break;

- if (sdp_uuid_cmp(&a->uuid, uuid) != 0)
+ if (bt_uuid_cmp(&a->uuid, uuid) != 0)
continue;

status = att_check_reqs(channel, ATT_OP_READ_BY_TYPE_REQ,
@@ -494,7 +495,7 @@ static int find_info(uint16_t start, uint16_t end, uint8_t *pdu, int len)
struct attribute *a;
struct att_data_list *adl;
GSList *l, *info;
- uint8_t format, last_type = SDP_UUID_UNSPEC;
+ uint8_t format, last_type = BT_UUID_UNSPEC;
uint16_t length, num;
int i;

@@ -511,7 +512,7 @@ static int find_info(uint16_t start, uint16_t end, uint8_t *pdu, int len)
if (a->handle > end)
break;

- if (last_type == SDP_UUID_UNSPEC)
+ if (last_type == BT_UUID_UNSPEC)
last_type = a->uuid.type;

if (a->uuid.type != last_type)
@@ -527,10 +528,10 @@ static int find_info(uint16_t start, uint16_t end, uint8_t *pdu, int len)
return enc_error_resp(ATT_OP_FIND_INFO_REQ, start,
ATT_ECODE_ATTR_NOT_FOUND, pdu, len);

- if (last_type == SDP_UUID16) {
+ if (last_type == BT_UUID16) {
length = 2;
format = 0x01;
- } else if (last_type == SDP_UUID128) {
+ } else if (last_type == BT_UUID128) {
length = 16;
format = 0x02;
}
@@ -547,7 +548,7 @@ static int find_info(uint16_t start, uint16_t end, uint8_t *pdu, int len)
att_put_u16(a->handle, value);

/* Attribute Value */
- memcpy(&value[2], &a->uuid.value, length);
+ att_put_uuid(a->uuid, &value[2]);
}

length = enc_find_info_resp(format, adl, pdu, len);
@@ -558,7 +559,7 @@ static int find_info(uint16_t start, uint16_t end, uint8_t *pdu, int len)
return length;
}

-static int find_by_type(uint16_t start, uint16_t end, uuid_t *uuid,
+static int find_by_type(uint16_t start, uint16_t end, bt_uuid_t *uuid,
const uint8_t *value, int vlen, uint8_t *opdu, int mtu)
{
struct attribute *a;
@@ -581,7 +582,7 @@ static int find_by_type(uint16_t start, uint16_t end, uuid_t *uuid,
break;

/* Primary service? Attribute value matches? */
- if ((sdp_uuid_cmp(&a->uuid, uuid) == 0) && (a->len == vlen) &&
+ if ((bt_uuid_cmp(&a->uuid, uuid) == 0) && (a->len == vlen) &&
(memcmp(a->data, value, vlen) == 0)) {

range = g_new0(struct att_range, 1);
@@ -595,8 +596,8 @@ static int find_by_type(uint16_t start, uint16_t end, uuid_t *uuid,
/* Update the last found handle or reset the pointer
* to track that a new group started: Primary or
* Secondary service. */
- if (sdp_uuid_cmp(&a->uuid, &prim_uuid) == 0 ||
- sdp_uuid_cmp(&a->uuid, &snd_uuid) == 0)
+ if (bt_uuid_cmp(&a->uuid, &prim_uuid) == 0 ||
+ bt_uuid_cmp(&a->uuid, &snd_uuid) == 0)
range = NULL;
else
range->end = a->handle;
@@ -631,7 +632,7 @@ static struct attribute *find_primary_range(uint16_t start, uint16_t *end)

attrib = l->data;

- if (sdp_uuid_cmp(&attrib->uuid, &prim_uuid) != 0)
+ if (bt_uuid_cmp(&attrib->uuid, &prim_uuid) != 0)
return NULL;

*end = start;
@@ -639,8 +640,8 @@ static struct attribute *find_primary_range(uint16_t start, uint16_t *end)
for (l = l->next; l; l = l->next) {
struct attribute *a = l->data;

- if (sdp_uuid_cmp(&a->uuid, &prim_uuid) == 0 ||
- sdp_uuid_cmp(&a->uuid, &snd_uuid) == 0)
+ if (bt_uuid_cmp(&a->uuid, &prim_uuid) == 0 ||
+ bt_uuid_cmp(&a->uuid, &snd_uuid) == 0)
break;

*end = a->handle;
@@ -785,7 +786,7 @@ static void channel_handler(const uint8_t *ipdu, uint16_t len,
struct gatt_channel *channel = user_data;
uint8_t opdu[ATT_MAX_MTU], value[ATT_MAX_MTU];
uint16_t length, start, end, mtu, offset;
- uuid_t uuid;
+ bt_uuid_t uuid;
uint8_t status = 0;
int vlen;

@@ -978,37 +979,37 @@ static void attrib_notify_clients(struct attribute *attr)
static gboolean register_core_services(void)
{
uint8_t atval[256];
- uuid_t uuid;
+ bt_uuid_t uuid;
uint16_t appearance = 0x0000;

/* GAP service: primary service definition */
- sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
+ bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
att_put_u16(GENERIC_ACCESS_PROFILE_ID, &atval[0]);
attrib_db_add(0x0001, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);

/* GAP service: device name characteristic */
name_handle = 0x0006;
- sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
+ bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(name_handle, &atval[1]);
att_put_u16(GATT_CHARAC_DEVICE_NAME, &atval[3]);
attrib_db_add(0x0004, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);

/* GAP service: device name attribute */
- sdp_uuid16_create(&uuid, GATT_CHARAC_DEVICE_NAME);
+ bt_uuid16_create(&uuid, GATT_CHARAC_DEVICE_NAME);
attrib_db_add(name_handle, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
NULL, 0);

/* GAP service: device appearance characteristic */
appearance_handle = 0x0008;
- sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
+ bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(appearance_handle, &atval[1]);
att_put_u16(GATT_CHARAC_APPEARANCE, &atval[3]);
attrib_db_add(0x0007, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);

/* GAP service: device appearance attribute */
- sdp_uuid16_create(&uuid, GATT_CHARAC_APPEARANCE);
+ bt_uuid16_create(&uuid, GATT_CHARAC_APPEARANCE);
att_put_u16(appearance, &atval[0]);
attrib_db_add(appearance_handle, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
atval, 2);
@@ -1020,7 +1021,7 @@ static gboolean register_core_services(void)
}

/* GATT service: primary service definition */
- sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
+ bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
att_put_u16(GENERIC_ATTRIB_PROFILE_ID, &atval[0]);
attrib_db_add(0x0010, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);

@@ -1177,7 +1178,7 @@ void attrib_free_sdp(uint32_t sdp_handle)
remove_record_from_server(sdp_handle);
}

-struct attribute *attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs,
+struct attribute *attrib_db_add(uint16_t handle, bt_uuid_t *uuid, int read_reqs,
int write_reqs, const uint8_t *value, int len)
{
struct attribute *a;
@@ -1186,7 +1187,7 @@ struct attribute *attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs,

a = g_malloc0(sizeof(struct attribute) + len);
a->handle = handle;
- memcpy(&a->uuid, uuid, sizeof(uuid_t));
+ memcpy(&a->uuid, uuid, sizeof(bt_uuid_t));
a->read_reqs = read_reqs;
a->write_reqs = write_reqs;
a->len = len;
@@ -1197,7 +1198,7 @@ struct attribute *attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs,
return a;
}

-int attrib_db_update(uint16_t handle, uuid_t *uuid, const uint8_t *value,
+int attrib_db_update(uint16_t handle, bt_uuid_t *uuid, const uint8_t *value,
int len)
{
struct attribute *a;
@@ -1215,7 +1216,7 @@ int attrib_db_update(uint16_t handle, uuid_t *uuid, const uint8_t *value,
l->data = a;
a->handle = handle;
if (uuid != &a->uuid)
- memcpy(&a->uuid, uuid, sizeof(uuid_t));
+ memcpy(&a->uuid, uuid, sizeof(bt_uuid_t));
a->len = len;
memcpy(a->data, value, len);

@@ -1243,12 +1244,12 @@ int attrib_db_del(uint16_t handle)

int attrib_gap_set(uint16_t uuid, const uint8_t *value, int len)
{
- uuid_t u16;
+ bt_uuid_t u16;
uint16_t handle;

/* FIXME: Missing Privacy and Reconnection Address */

- sdp_uuid16_create(&u16, uuid);
+ bt_uuid16_create(&u16, uuid);

switch (uuid) {
case GATT_CHARAC_DEVICE_NAME:
diff --git a/src/attrib-server.h b/src/attrib-server.h
index 85f3bdb..c03d3c5 100644
--- a/src/attrib-server.h
+++ b/src/attrib-server.h
@@ -25,9 +25,9 @@
int attrib_server_init(void);
void attrib_server_exit(void);

-struct attribute *attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs,
+struct attribute *attrib_db_add(uint16_t handle, bt_uuid_t *uuid, int read_reqs,
int write_reqs, const uint8_t *value, int len);
-int attrib_db_update(uint16_t handle, uuid_t *uuid, const uint8_t *value,
+int attrib_db_update(uint16_t handle, bt_uuid_t *uuid, const uint8_t *value,
int len);
int attrib_db_del(uint16_t handle);
int attrib_gap_set(uint16_t uuid, const uint8_t *value, int len);
diff --git a/src/device.c b/src/device.c
index 529e0de..e9d9e65 100644
--- a/src/device.c
+++ b/src/device.c
@@ -35,6 +35,7 @@
#include <errno.h>

#include <bluetooth/bluetooth.h>
+#include <bluetooth/uuid.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>

diff --git a/src/main.c b/src/main.c
index 1aaa181..c454327 100644
--- a/src/main.c
+++ b/src/main.c
@@ -39,6 +39,7 @@
#include <sys/types.h>

#include <bluetooth/bluetooth.h>
+#include <bluetooth/uuid.h>

#include <glib.h>

--
1.7.1


2011-03-04 16:20:38

by Elvis Pfutzenreuter

[permalink] [raw]
Subject: [PATCH 3/5] Add "unit test" for new UUID functions

---
Makefile.tools | 6 +-
test/uuidtest.c | 296 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 301 insertions(+), 1 deletions(-)
create mode 100644 test/uuidtest.c

diff --git a/Makefile.tools b/Makefile.tools
index 9c43202..1a1f5a1 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -142,7 +142,8 @@ bin_PROGRAMS += test/l2test test/rctest
noinst_PROGRAMS += test/gaptest test/sdptest test/scotest \
test/attest test/hstest test/avtest test/ipctest \
test/lmptest test/bdaddr test/agent \
- test/btiotest test/test-textfile
+ test/btiotest test/test-textfile \
+ test/uuidtest

test_hciemu_LDADD = @GLIB_LIBS@ lib/libbluetooth.la

@@ -175,6 +176,9 @@ test_agent_LDADD = @DBUS_LIBS@
test_btiotest_SOURCES = test/btiotest.c btio/btio.h btio/btio.c
test_btiotest_LDADD = @GLIB_LIBS@ lib/libbluetooth.la

+test_uuidtest_SOURCES = test/uuidtest.c
+test_uuidtest_LDADD = lib/libbluetooth.la
+
test_test_textfile_SOURCES = test/test-textfile.c src/textfile.h src/textfile.c

dist_man_MANS += test/rctest.1 test/hciemu.1
diff --git a/test/uuidtest.c b/test/uuidtest.c
new file mode 100644
index 0000000..ee94a3f
--- /dev/null
+++ b/test/uuidtest.c
@@ -0,0 +1,296 @@
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/uuid.h>
+
+const char *base = "00000000-0000-1000-8000-00805F9B34FB";
+
+uint8_t xbase[] = {0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+ 0x10, 0x00,
+ 0x80, 0x00,
+ 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+
+uint16_t sixteen = 0x1234;
+const char *uuidsixteen128 = "00001234-0000-1000-8000-00805F9B34FB";
+const char *uuidsixteen16 = "0x1234";
+const char *uuidsixteen16a = "1234";
+
+uint8_t xuuidsixteen[] = {0x00, 0x00, 0x12, 0x34,
+ 0x00, 0x00,
+ 0x10, 0x00,
+ 0x80, 0x00,
+ 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+
+uint32_t thirtytwo = 0x12345678;
+const char *uuidthirtytwo32 = "0x12345678";
+const char *uuidthirtytwo32a = "12345678";
+const char *uuidthirtytwo128 = "12345678-0000-1000-8000-00805F9B34FB";
+
+uint8_t xuuidthirtytwo[] = {0x12, 0x34, 0x56, 0x78,
+ 0x00, 0x00,
+ 0x10, 0x00,
+ 0x80, 0x00,
+ 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+
+const char *malformed[] = {
+ "0",
+ "01",
+ "012",
+ "xxxx",
+ "xxxxx",
+ "0xxxxx",
+ "0123456",
+ "012g4567",
+ "012345678",
+ "0x234567u9",
+ "01234567890",
+ "00001234-0000-1000-8000-00805F9B34F",
+ "00001234-0000-1000-8000 00805F9B34FB",
+ "00001234-0000-1000-8000-00805F9B34FBC",
+ "00001234-0000-1000-800G-00805F9B34FB",
+ NULL };
+
+int main()
+{
+ bt_uuid_t u, u2, u3, u4, u5, ub;
+ uint128_t n;
+ uint128_t i;
+ char buf[512];
+ int s;
+
+ memcpy(&n, xbase, 16);
+ ntoh128(&n, &i);
+
+ if (bt_string_to_uuid(&u, base)) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (bt_string_to_uuid(&ub, base)) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (u.type != 128) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (ub.type != 128) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (memcmp(&u.value.u128, &i, 16) != 0) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (memcmp(&ub.value.u128, &i, 16) != 0) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (memcmp(&ub.value.u128, &u.value.u128, 16) != 0) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (bt_uuid_cmp(&u, &ub) != 0) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ bt_uuid_to_string(&u, buf, sizeof(buf));
+ /* printf("%s\n", buf); */
+
+ if (strcasecmp(buf, base) != 0) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ memcpy(&n, xuuidsixteen, 16);
+ ntoh128(&n, &i);
+
+ bt_uuid16_create(&u, sixteen);
+
+ if (bt_string_to_uuid(&u2, uuidsixteen16)) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (bt_string_to_uuid(&u3, uuidsixteen16a)) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (bt_string_to_uuid(&u4, uuidsixteen128)) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ bt_uuid128_create(&u5, i);
+
+ if (u.type != 16) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (u.value.u16 != sixteen) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (u2.type != 16) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (u3.type != 16) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (u4.type != 128) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (u5.type != 128) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (bt_uuid_cmp(&u, &u2) != 0) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (bt_uuid_cmp(&u2, &u3) != 0) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (bt_uuid_cmp(&u, &u3) != 0) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (bt_uuid_cmp(&u3, &u4) != 0) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (bt_uuid_cmp(&u4, &u5) != 0) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (bt_uuid_cmp(&u5, &u) != 0) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (bt_uuid_cmp(&u, &ub) == 0) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (bt_uuid_cmp(&u5, &ub) == 0) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ memcpy(&n, xuuidthirtytwo, 16);
+ ntoh128(&n, &i);
+
+ bt_uuid32_create(&u, thirtytwo);
+ bt_string_to_uuid(&u2, uuidthirtytwo32);
+ bt_string_to_uuid(&u3, uuidthirtytwo32a);
+ bt_string_to_uuid(&u4, uuidthirtytwo128);
+ bt_uuid128_create(&u5, i);
+
+ /*
+ bt_uuid_to_string(&u2, buf, sizeof(buf));
+ printf("%s\n", buf);
+
+ bt_uuid_to_string(&u3, buf, sizeof(buf));
+ printf("%s\n", buf);
+
+ bt_uuid_to_string(&u4, buf, sizeof(buf));
+ printf("%s\n", buf);
+ */
+
+ if (u.type != 32) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (u.value.u32 != thirtytwo) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (u2.type != 32) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (u3.type != 32) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (u4.type != 128) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (u5.type != 128) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (bt_uuid_cmp(&u, &u2) != 0) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (bt_uuid_cmp(&u2, &u3) != 0) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (bt_uuid_cmp(&u3, &u4) != 0) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (bt_uuid_cmp(&u4, &u5) != 0) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (bt_uuid_cmp(&u5, &u) != 0) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (bt_uuid_cmp(&u, &ub) == 0) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ if (bt_uuid_cmp(&u5, &ub) == 0) {
+ printf("Fail %d\n", __LINE__);
+ return 1;
+ }
+
+ for (s = 0; malformed[s]; ++s) {
+ if (bt_string_to_uuid(&u3, malformed[s]) == 0) {
+ printf("Fail %s %d\n", malformed[s], __LINE__);
+ return 1;
+ }
+ }
+
+ return 0;
+}
--
1.7.1


2011-03-04 16:20:37

by Elvis Pfutzenreuter

[permalink] [raw]
Subject: [PATCH 2/5] Add more functions for new UUID handling

This patch adds more functions that are necessary to handle
the new bt_uuid_t type, and moves basic things like
byte-swapping functions and uint128_t type to bluetooth.h.
---
health/mcap_sync.c | 15 -----
lib/bluetooth.h | 49 ++++++++++++++++
lib/sdp.c | 43 --------------
lib/sdp.h | 4 +-
lib/uuid.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/uuid.h | 12 +++-
test/hciemu.c | 16 -----
7 files changed, 218 insertions(+), 81 deletions(-)

diff --git a/health/mcap_sync.c b/health/mcap_sync.c
index 6f90344..f4b005a 100644
--- a/health/mcap_sync.c
+++ b/health/mcap_sync.c
@@ -92,21 +92,6 @@ struct sync_set_data {
gboolean role;
};

-/* Ripped from lib/sdp.c */
-
-#if __BYTE_ORDER == __BIG_ENDIAN
-#define ntoh64(x) (x)
-#else
-static inline uint64_t ntoh64(uint64_t n)
-{
- uint64_t h;
- uint64_t tmp = ntohl(n & 0x00000000ffffffff);
- h = ntohl(n >> 32);
- h |= tmp << 32;
- return h;
-}
-#endif
-
#define hton64(x) ntoh64(x)

static gboolean csp_caps_initialized = FALSE;
diff --git a/lib/bluetooth.h b/lib/bluetooth.h
index bc0921e..5b8055c 100644
--- a/lib/bluetooth.h
+++ b/lib/bluetooth.h
@@ -35,6 +35,7 @@ extern "C" {
#include <string.h>
#include <endian.h>
#include <byteswap.h>
+#include <netinet/in.h>

#ifndef AF_BLUETOOTH
#define AF_BLUETOOTH 31
@@ -158,6 +159,54 @@ void bt_free(void *ptr);
int bt_error(uint16_t code);
char *bt_compidtostr(int id);

+typedef struct {
+ uint8_t data[16];
+} uint128_t;
+
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define ntoh64(x) (x)
+static inline void ntoh128(const uint128_t *src, uint128_t *dst)
+{
+ memcpy(dst, src, sizeof(uint128_t));
+}
+
+static inline void btoh128(const uint128_t *src, uint128_t *dst)
+{
+ int i;
+ for (i = 0; i < 16; i++)
+ dst->data[15 - i] = src->data[i];
+
+}
+
+#else
+static inline uint64_t ntoh64(uint64_t n)
+{
+ uint64_t h;
+ uint64_t tmp = ntohl(n & 0x00000000ffffffff);
+ h = ntohl(n >> 32);
+ h |= tmp << 32;
+ return h;
+}
+
+static inline void ntoh128(const uint128_t *src, uint128_t *dst)
+{
+ int i;
+ for (i = 0; i < 16; i++)
+ dst->data[15 - i] = src->data[i];
+}
+
+static inline void btoh128(const uint128_t *src, uint128_t *dst)
+{
+ memcpy(dst, src, sizeof(uint128_t));
+}
+
+#endif
+
+#define hton64(x) ntoh64(x)
+#define hton128(x, y) ntoh128(x, y)
+#define htob128(x, y) btoh128(x, y)
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/sdp.c b/lib/sdp.c
index e782aec..d24d1e2 100644
--- a/lib/sdp.c
+++ b/lib/sdp.c
@@ -60,49 +60,6 @@
#define SDPDBG(fmt...)
#endif

-#if __BYTE_ORDER == __BIG_ENDIAN
-#define ntoh64(x) (x)
-static inline void ntoh128(const uint128_t *src, uint128_t *dst)
-{
- memcpy(dst, src, sizeof(uint128_t));
-}
-
-static inline void btoh128(const uint128_t *src, uint128_t *dst)
-{
- int i;
- for (i = 0; i < 16; i++)
- dst->data[15 - i] = src->data[i];
-
-}
-
-#else
-static inline uint64_t ntoh64(uint64_t n)
-{
- uint64_t h;
- uint64_t tmp = ntohl(n & 0x00000000ffffffff);
- h = ntohl(n >> 32);
- h |= tmp << 32;
- return h;
-}
-
-static inline void ntoh128(const uint128_t *src, uint128_t *dst)
-{
- int i;
- for (i = 0; i < 16; i++)
- dst->data[15 - i] = src->data[i];
-}
-
-static inline void btoh128(const uint128_t *src, uint128_t *dst)
-{
- memcpy(dst, src, sizeof(uint128_t));
-}
-
-#endif
-
-#define hton64(x) ntoh64(x)
-#define hton128(x, y) ntoh128(x, y)
-#define htob128(x, y) btoh128(x, y)
-
#define BASE_UUID "00000000-0000-1000-8000-00805F9B34FB"

static uint128_t bluetooth_base_uuid = {
diff --git a/lib/sdp.h b/lib/sdp.h
index f0758b2..8a4b49b 100644
--- a/lib/sdp.h
+++ b/lib/sdp.h
@@ -32,6 +32,7 @@ extern "C" {
#endif

#include <stdint.h>
+#include <bluetooth.h>

#define SDP_UNIX_PATH "/var/run/sdp"
#define SDP_RESPONSE_TIMEOUT 20
@@ -420,9 +421,6 @@ typedef struct {
* Common definitions for attributes in the SDP.
* Should the type of any of these change, you need only make a change here.
*/
-typedef struct {
- uint8_t data[16];
-} uint128_t;

typedef struct {
uint8_t type;
diff --git a/lib/uuid.c b/lib/uuid.c
index 6bdff12..708ad8d 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -27,6 +27,8 @@
#endif

#include <string.h>
+#include <stdlib.h>
+#include <errno.h>

#include "uuid.h"

@@ -81,6 +83,7 @@ static void bt_uuid2uuid128(const bt_uuid_t *uuid, bt_uuid_t *uuid128)
switch (uuid->type) {
case BT_UUID128:
memcpy(uuid128, uuid, sizeof(bt_uuid_t));
+ uuid128->type = BT_UUID128;
break;
case BT_UUID32:
bt_uuid32_to_uuid128(uuid, uuid128);
@@ -88,9 +91,22 @@ static void bt_uuid2uuid128(const bt_uuid_t *uuid, bt_uuid_t *uuid128)
case BT_UUID16:
bt_uuid16_to_uuid128(uuid, uuid128);
break;
+ default:
+ break;
}
}

+void bt_uuid_to_uuid128(bt_uuid_t *uuid)
+{
+ bt_uuid_t orig;
+
+ if (uuid->type == BT_UUID128)
+ return;
+
+ memcpy(&orig, uuid, sizeof(bt_uuid_t));
+ bt_uuid2uuid128(&orig, uuid);
+}
+
static int bt_uuid128_cmp(const bt_uuid_t *u1, const bt_uuid_t *u2)
{
return memcmp(&u1->value.u128, &u2->value.u128, sizeof(uint128_t));
@@ -132,3 +148,147 @@ int bt_uuid_cmp(const bt_uuid_t *uuid1, const bt_uuid_t *uuid2)

return bt_uuid128_cmp(&u1, &u2);
}
+
+/*
+ * convert the UUID to string, copying a maximum of n characters.
+ */
+int bt_uuid_to_string(const bt_uuid_t *uuid, char *str, size_t n)
+{
+ if (!uuid) {
+ snprintf(str, n, "NULL");
+ return -EINVAL;
+ }
+
+ switch (uuid->type) {
+ case BT_UUID16:
+ snprintf(str, n, "%.4x", uuid->value.u16);
+ break;
+ case BT_UUID32:
+ snprintf(str, n, "%.8x", uuid->value.u32);
+ break;
+ case BT_UUID128: {
+ unsigned int data0;
+ unsigned short data1;
+ unsigned short data2;
+ unsigned short data3;
+ unsigned int data4;
+ unsigned short data5;
+
+ uint128_t nvalue;
+ const uint8_t *data = (uint8_t *) &nvalue;
+
+ hton128(&uuid->value.u128, &nvalue);
+
+ memcpy(&data0, &data[0], 4);
+ memcpy(&data1, &data[4], 2);
+ memcpy(&data2, &data[6], 2);
+ memcpy(&data3, &data[8], 2);
+ memcpy(&data4, &data[10], 4);
+ memcpy(&data5, &data[14], 2);
+
+ snprintf(str, n, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x",
+ ntohl(data0), ntohs(data1),
+ ntohs(data2), ntohs(data3),
+ ntohl(data4), ntohs(data5));
+ }
+ break;
+ default:
+ snprintf(str, n, "Type of UUID (%x) unknown.", uuid->type);
+ return -EINVAL; /* Enum type of UUID not set */
+ }
+
+ return 0;
+}
+
+static inline int is_uuid128(const char *string)
+{
+ return (strlen(string) == 36 &&
+ string[8] == '-' &&
+ string[13] == '-' &&
+ string[18] == '-' &&
+ string[23] == '-');
+}
+
+static inline int is_uuid32(const char *string)
+{
+ return (strlen(string) == 8 || strlen(string) == 10);
+}
+
+static inline int is_uuid16(const char *string)
+{
+ return (strlen(string) == 4 || strlen(string) == 6);
+}
+
+static int bt_string_to_uuid16(bt_uuid_t *uuid, const char *string)
+{
+ uint16_t u16;
+ char *endptr = NULL;
+
+ u16 = strtol(string, &endptr, 16);
+ if (endptr && *endptr == '\0') {
+ bt_uuid16_create(uuid, u16);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int bt_string_to_uuid32(bt_uuid_t *uuid, const char *string)
+{
+ uint32_t u32;
+ char *endptr = NULL;
+
+ u32 = strtol(string, &endptr, 16);
+ if (endptr && *endptr == '\0') {
+ bt_uuid32_create(uuid, u32);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int bt_string_to_uuid128(bt_uuid_t *uuid, const char *string)
+{
+ uint32_t data0, data4;
+ uint16_t data1, data2, data3, data5;
+ uint128_t n128, u128;
+ uint8_t *val = (uint8_t *) &n128;
+
+ if (sscanf(string, "%08x-%04hx-%04hx-%04hx-%08x%04hx",
+ &data0, &data1, &data2,
+ &data3, &data4, &data5) != 6)
+ return -EINVAL;
+
+
+ data0 = htonl(data0);
+ data1 = htons(data1);
+ data2 = htons(data2);
+ data3 = htons(data3);
+ data4 = htonl(data4);
+ data5 = htons(data5);
+
+ memcpy(&val[0], &data0, 4);
+ memcpy(&val[4], &data1, 2);
+ memcpy(&val[6], &data2, 2);
+ memcpy(&val[8], &data3, 2);
+ memcpy(&val[10], &data4, 4);
+ memcpy(&val[14], &data5, 2);
+
+ ntoh128(&n128, &u128);
+
+ bt_uuid128_create(uuid, u128);
+
+ return 0;
+}
+
+int bt_string_to_uuid(bt_uuid_t *uuid, const char *string)
+{
+ if (is_uuid128(string))
+ return bt_string_to_uuid128(uuid, string);
+ else if (is_uuid32(string))
+ return bt_string_to_uuid32(uuid, string);
+ else if (is_uuid16(string))
+ return bt_string_to_uuid16(uuid, string);
+
+ return -EINVAL;
+}
diff --git a/lib/uuid.h b/lib/uuid.h
index bc9ca31..7d73625 100644
--- a/lib/uuid.h
+++ b/lib/uuid.h
@@ -30,13 +30,11 @@ extern "C" {
#endif

#include <stdint.h>
-
-typedef struct {
- uint8_t data[16];
-} uint128_t;
+#include <bluetooth.h>

typedef struct {
enum {
+ BT_UUID_UNSPEC = 0,
BT_UUID16 = 16,
BT_UUID32 = 32,
BT_UUID128 = 128,
@@ -53,6 +51,12 @@ int bt_uuid32_create(bt_uuid_t *btuuid, uint32_t value);
int bt_uuid128_create(bt_uuid_t *btuuid, uint128_t value);

int bt_uuid_cmp(const bt_uuid_t *uuid1, const bt_uuid_t *uuid2);
+void bt_uuid_to_uuid128(bt_uuid_t *uuid);
+
+#define MAX_LEN_UUID_STR 37
+
+int bt_uuid_to_string(const bt_uuid_t *uuid, char *str, size_t n);
+int bt_string_to_uuid(bt_uuid_t *uuid, const char *string);

#ifdef __cplusplus
}
diff --git a/test/hciemu.c b/test/hciemu.c
index 5227766..757a75c 100644
--- a/test/hciemu.c
+++ b/test/hciemu.c
@@ -52,22 +52,6 @@

#include <glib.h>

-#if __BYTE_ORDER == __LITTLE_ENDIAN
-static inline uint64_t ntoh64(uint64_t n)
-{
- uint64_t h;
- uint64_t tmp = ntohl(n & 0x00000000ffffffff);
- h = ntohl(n >> 32);
- h |= tmp << 32;
- return h;
-}
-#elif __BYTE_ORDER == __BIG_ENDIAN
-#define ntoh64(x) (x)
-#else
-#error "Unknown byte order"
-#endif
-#define hton64(x) ntoh64(x)
-
#define GHCI_DEV "/dev/ghci"

#define VHCI_DEV "/dev/vhci"
--
1.7.1