Linux bluetooth development
 help / color / mirror / Atom feed
* Re: [bluetooth-next 04/15] Bluetooth: Add support for using the crypto subsystem
From: Vinicius Costa Gomes @ 2011-03-03 17:45 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <20110228172801.GB2165@joana>

Hi Marcel,

On 14:28 Mon 28 Feb, Gustavo F. Padovan wrote:
> Hi Vinicius,
> 
> * Vinicius Gomes <vinicius.gomes@openbossa.org> [2011-02-27 21:49:39 -0300]:
> 
> > Hi Gustavo,
> > 
> > On Sun, Feb 27, 2011 at 5:20 PM, Gustavo F. Padovan
> > <padovan@profusion.mobi> wrote:
> > > Hi Vinicius,
> > >
> > > * Vinicius Costa Gomes <vinicius.gomes@openbossa.org> [2011-02-21 14:23:51 -0300]:
> > >
> > >> This will allow using the crypto subsystem for encrypting data. As SMP
> > >> (Security Manager Protocol) is implemented almost entirely on the host
> > >> side and the crypto module already implements the needed methods
> > >> (AES-128), it makes sense to use it.
> > >>
> > >> This patch also adds a new Kconfig option to toggle the SMP support.
> > >>
> > >> Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
> > >> Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org>
> > >> ---
> > >>  include/net/bluetooth/hci_core.h |    2 ++
> > >>  net/bluetooth/Kconfig            |    6 ++++++
> > >>  net/bluetooth/hci_core.c         |   22 ++++++++++++++++++++++
> > >>  net/bluetooth/smp.c              |   17 +++++++++++++++--
> > >>  4 files changed, 45 insertions(+), 2 deletions(-)
> > >>
> > >> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> > >> index d5d8454..e8dbde8 100644
> > >> --- a/include/net/bluetooth/hci_core.h
> > >> +++ b/include/net/bluetooth/hci_core.h
> > >> @@ -161,6 +161,8 @@ struct hci_dev {
> > >>
> > >>       __u16                   init_last_cmd;
> > >>
> > >> +     struct crypto_blkcipher *tfm;
> > >> +
> > >>       struct inquiry_cache    inq_cache;
> > >>       struct hci_conn_hash    conn_hash;
> > >>       struct list_head        blacklist;
> > >> diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
> > >> index c6f9c2f..e9f40af 100644
> > >> --- a/net/bluetooth/Kconfig
> > >> +++ b/net/bluetooth/Kconfig
> > >> @@ -22,6 +22,7 @@ menuconfig BT
> > >>            BNEP Module (Bluetooth Network Encapsulation Protocol)
> > >>            CMTP Module (CAPI Message Transport Protocol)
> > >>            HIDP Module (Human Interface Device Protocol)
> > >> +          SMP Module (Security Manager Protocol)
> > >>
> > >>         Say Y here to compile Bluetooth support into the kernel or say M to
> > >>         compile it as module (bluetooth).
> > >> @@ -35,11 +36,16 @@ config BT_L2CAP
> > >>       bool "L2CAP protocol support"
> > >>       depends on BT
> > >>       select CRC16
> > >> +     select CRYPTO_BLKCIPHER
> > >> +     select CRYPTO_AES
> > >>       help
> > >>         L2CAP (Logical Link Control and Adaptation Protocol) provides
> > >>         connection oriented and connection-less data transport.  L2CAP
> > >>         support is required for most Bluetooth applications.
> > >>
> > >> +       Also included is support for SMP (Security Manager Protocol) which
> > >> +       is the security layer on top of LE (Low Energy) links.
> > >> +
> > >>  config BT_SCO
> > >>       bool "SCO links support"
> > >>       depends on BT
> > >> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> > >> index b372fb8..ff67843 100644
> > >> --- a/net/bluetooth/hci_core.c
> > >> +++ b/net/bluetooth/hci_core.c
> > >> @@ -42,6 +42,7 @@
> > >>  #include <linux/notifier.h>
> > >>  #include <linux/rfkill.h>
> > >>  #include <linux/timer.h>
> > >> +#include <linux/crypto.h>
> > >>  #include <net/sock.h>
> > >>
> > >>  #include <asm/system.h>
> > >> @@ -60,6 +61,8 @@ static void hci_notify(struct hci_dev *hdev, int event);
> > >>
> > >>  static DEFINE_RWLOCK(hci_task_lock);
> > >>
> > >> +static int enable_smp;
> > >> +
> > >>  /* HCI device list */
> > >>  LIST_HEAD(hci_dev_list);
> > >>  DEFINE_RWLOCK(hci_dev_list_lock);
> > >> @@ -1077,6 +1080,14 @@ static void hci_cmd_timer(unsigned long arg)
> > >>       tasklet_schedule(&hdev->cmd_task);
> > >>  }
> > >>
> > >> +static struct crypto_blkcipher *alloc_cypher(void)
> > >> +{
> > >> +     if (enable_smp)
> > >> +             return crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
> > >> +
> > >> +     return ERR_PTR(-ENOTSUPP);
> > >> +}
> > >> +
> > >>  /* Register HCI device */
> > >>  int hci_register_dev(struct hci_dev *hdev)
> > >>  {
> > >> @@ -1155,6 +1166,11 @@ int hci_register_dev(struct hci_dev *hdev)
> > >>       if (!hdev->workqueue)
> > >>               goto nomem;
> > >>
> > >> +     hdev->tfm = alloc_cypher();
> > >> +     if (IS_ERR(hdev->tfm))
> > >> +             BT_INFO("Failed to load transform for ecb(aes): %ld",
> > >> +                                                     PTR_ERR(hdev->tfm));
> > >> +
> > >>       hci_register_sysfs(hdev);
> > >>
> > >>       hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
> > >> @@ -1203,6 +1219,9 @@ int hci_unregister_dev(struct hci_dev *hdev)
> > >>                                       !test_bit(HCI_SETUP, &hdev->flags))
> > >>               mgmt_index_removed(hdev->id);
> > >>
> > >> +     if (!IS_ERR(hdev->tfm))
> > >> +             crypto_free_blkcipher(hdev->tfm);
> > >> +
> > >>       hci_notify(hdev, HCI_DEV_UNREG);
> > >>
> > >>       if (hdev->rfkill) {
> > >> @@ -2037,3 +2056,6 @@ static void hci_cmd_task(unsigned long arg)
> > >>               }
> > >>       }
> > >>  }
> > >> +
> > >> +module_param(enable_smp, bool, 0644);
> > >> +MODULE_PARM_DESC(enable_smp, "Enable SMP support (LE only)");
> > >
> > > This all should be obviously inside smp.c
> > 
> > I have a couple of points against it:
> > 
> > 1. it's only used for one purpose, it says whether to try or not to
> > allocate the block cypher, which is done during the adapter
> > registration;
> > 
> > 2. If the current way is ok, it would mean that I would need to export
> > another method from smp.c, that was something that I tried to
> > minimize;
> > 
> > 3. and my weakest argument, seems that there are other similar uses,
> > for example enable_mgmt.
> 
> A similar example here is enable_ertm inside l2cap_core.c. It's a L2CAP
> related option and should reside inside L2CAP code.
> 
> > 
> > But if you think the code will be clearer moving that to smp.c, will
> > be glad to change.
> 
> I don't see the point on have it on hci code. SMP and Block cypher has
> not much to do with HCI. I prefer it on smp.c

Gustavo and I were talking on IRC and couldn't come to a solution, so
we ask you for some input.

So, just to give a little more context, the problem is that the crypto
functions used in SMP depend on the allocation of a block cypher "transform",
this allocation must happen during user context.

The current solution is that the allocation is done in hci_core.c during the
adapter registration, but only when the enable_smp module parameter is enabled.
When the parameter is disabled the allocation method just returns an invalid 
pointer and everything happens the same as if the allocation has failed.

Gustavo has a preference for an ondemand aproach, for example, using a
workqueue for doing the allocation, and trying the allocation just when SMP is
going to be used, e.g. when we receive the first SMP message or when some 
security level is activated for that socket.

Any ideas?

> 
> -- 
> Gustavo F. Padovan
> http://profusion.mobi


Cheers,
-- 
Vinicius

^ permalink raw reply

* Re: New device driver: Nintendo Wii Remote
From: Bastien Nocera @ 2011-03-03 17:49 UTC (permalink / raw)
  To: David Herrmann; +Cc: linux-bluetooth
In-Reply-To: <AANLkTimCFW3bZkmm_B8VfViMC1A+rDjWRnE5OSB7eCCJ@mail.gmail.com>

On Thu, 2011-03-03 at 18:42 +0100, David Herrmann wrote:
> Hi
> 
> The Nintendo Wii Remote (short Wiimote) is the remote for the Nintedo
> Wii console and communicates via bluetooth. There have been many
> approaches to write linux drivers (incomplete list:
> http://wiibrew.org/wiki/Wiimote/Library), however, they all are
> written as separate libraries and not as device drivers. This has the
> disadvantage, that the application must actively connect to the
> wiimote (probably performing a bt-inquiry beforehand) instead of
> listening for incoming connections.
> The latter one can be achieved by listening on the HID l2cap channels
> (psm 0x11 and 0x13), though, the wiimote does not follow the HID
> standard. Since the bluez input-plugin listens on these ports, the
> driver needs to be integrated into the bluez-daemon or kernel to work
> properly.

You can do the pairing by hacking bluetoothd:
https://bugzilla.gnome.org/show_bug.cgi?id=603845

This is the first thing to fix to get proper Wiimote access. Marcel
would also like the pairing and PIN setting to be handled directly in
bluetoothd for this device.

Cheers


^ permalink raw reply

* Re: D-Bus for LE
From: Anderson Lizardo @ 2011-03-03 17:51 UTC (permalink / raw)
  To: Marco Sinigaglia; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <4D6FD0E9.1020602@csr.com>

Hi,

On Thu, Mar 3, 2011 at 1:33 PM, Marco Sinigaglia
<marco.sinigaglia@csr.com> wrote:
> Hi All,
>
> I am looking the D-Bus API for low energy and I cannot find a way to run a
> discover for LE devices and connect to them.
> Are these API implemented? if not, are they going to be?
>
>
> Looking the attribute-api it should be possible to do some stuff on the
> local device but, on my box, it looks like not working.
> I am sure that the blutoothd is kicking off the attribute server (sdptool is
> showing the le profiles), nevertheless the test-attrib is showing nothing:
>
>>sudo ./test-attrib  -i hci0
> [nothing]

Did you connect to the remote first using "test-device create" ? Also
make sure the remote is advertising with Flags = 0x06 (bits "BR/EDR
not supported" and "general discoverable mode") if the remove is dual
mode, otherwise it will attempt a BR/EDR connection.

In summary:

1) On the remote device enable advertising and (if a dual mode) set
flags to 0x06:

hcitool -i hciX cmd 0x08 0x0008 03 02 01 06
hciconfig hciX leadv

2) on the local side, start discovery (so the adv data is saved by
bluez) followed by test-device create:

test-discovery (wait for it to finish or at least show the device you
will connect to)
test-device create <bdaddr>

3) not the tricky part: you need to reenable advertising on the remote
side (see step #1) for test-attrib to work. This is because remote
disabled advertising after the LE connection during test-device create
was done, and IIRC test-device create does not keep connection open.
test-attrib will them open a new connection which only works with
advertising enabled on remote side.

3) you can now run test-attrib:

./test-attrib -i hciX

Note this API is ongoing some changes and most of the steps above will
be automatic. See the "TODO" file on BlueZ source for the planned
changes.

HTH,
-- 
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil

^ permalink raw reply

* Re: New device driver: Nintendo Wii Remote
From: David Herrmann @ 2011-03-03 18:06 UTC (permalink / raw)
  To: Bastien Nocera; +Cc: linux-bluetooth
In-Reply-To: <1299174593.18332.42.camel@novo.hadess.net>

On Thu, Mar 3, 2011 at 6:49 PM, Bastien Nocera <hadess@hadess.net> wrote:
> On Thu, 2011-03-03 at 18:42 +0100, David Herrmann wrote:
>> Hi
>>
>> The Nintendo Wii Remote (short Wiimote) is the remote for the Nintedo
>> Wii console and communicates via bluetooth. There have been many
>> approaches to write linux drivers (incomplete list:
>> http://wiibrew.org/wiki/Wiimote/Library), however, they all are
>> written as separate libraries and not as device drivers. This has the
>> disadvantage, that the application must actively connect to the
>> wiimote (probably performing a bt-inquiry beforehand) instead of
>> listening for incoming connections.
>> The latter one can be achieved by listening on the HID l2cap channels
>> (psm 0x11 and 0x13), though, the wiimote does not follow the HID
>> standard. Since the bluez input-plugin listens on these ports, the
>> driver needs to be integrated into the bluez-daemon or kernel to work
>> properly.
>
> You can do the pairing by hacking bluetoothd:
> https://bugzilla.gnome.org/show_bug.cgi?id=603845
>
> This is the first thing to fix to get proper Wiimote access. Marcel
> would also like the pairing and PIN setting to be handled directly in
> bluetoothd for this device.

This is not about pairing. Yes, it is true, the wiimote needs to be paired
once to get the address of the host so automatic reconnection works,
but I successfully paired the device via the dbus interface so pairing is
handled inside bluetoothd.
But once paired, no further pairing is needed if the device reconnects
to the host, everything works just fine without pairing. My issue is about
getting access to the listener sockets inside the input-plugin.

Furthermore, the PIN required by the wiimote is not always the same.
It depends whether the 1+2 buttons on the front of the wiimote are
pressed or whether the red-sync button on its back is pressed. One
time it's the bdaddr of the host, the other time its the bdaddr of the remote.

So when actively connecting to the remote (which requires pairing), the
driver needs to create its own PIN-agent for this connection which can
be done via CreatePairedDevice (dbus method on adapter API). So I guess
the PIN handling is fine, or did I misunderstood you?

Cheers
David

^ permalink raw reply

* Re: New device driver: Nintendo Wii Remote
From: David Herrmann @ 2011-03-03 18:19 UTC (permalink / raw)
  To: Bastien Nocera; +Cc: linux-bluetooth
In-Reply-To: <AANLkTinhMeLRoG8GPrU8C9cNydj2Jxvfvp7PZ-7MCqGC@mail.gmail.com>

On Thu, Mar 3, 2011 at 7:06 PM, David Herrmann
<dh.herrmann@googlemail.com> wrote:
> On Thu, Mar 3, 2011 at 6:49 PM, Bastien Nocera <hadess@hadess.net> wrote:
>> On Thu, 2011-03-03 at 18:42 +0100, David Herrmann wrote:
>>> Hi
>>>
>>> The Nintendo Wii Remote (short Wiimote) is the remote for the Nintedo
>>> Wii console and communicates via bluetooth. There have been many
>>> approaches to write linux drivers (incomplete list:
>>> http://wiibrew.org/wiki/Wiimote/Library), however, they all are
>>> written as separate libraries and not as device drivers. This has the
>>> disadvantage, that the application must actively connect to the
>>> wiimote (probably performing a bt-inquiry beforehand) instead of
>>> listening for incoming connections.
>>> The latter one can be achieved by listening on the HID l2cap channels
>>> (psm 0x11 and 0x13), though, the wiimote does not follow the HID
>>> standard. Since the bluez input-plugin listens on these ports, the
>>> driver needs to be integrated into the bluez-daemon or kernel to work
>>> properly.
>>
>> You can do the pairing by hacking bluetoothd:
>> https://bugzilla.gnome.org/show_bug.cgi?id=603845
>>
>> This is the first thing to fix to get proper Wiimote access. Marcel
>> would also like the pairing and PIN setting to be handled directly in
>> bluetoothd for this device.

Wait no, I didn't do it via dbus, you're right. This would require zero bytes to
be part of the PIN. But the suggestion from Marcel (hardcoding the PIN with
PnP identification) does not work as I explained, there are 2 PINs used and
only the driver knows which PIN to use. (Well, the user has to define which
pairing method to use and so the driver chooses the right PIN). So I think the
only way is handling the PIN-related code inside the wiimote driver.

David

^ permalink raw reply

* Re: [PATCH 0/4] Message Access Profile plugin
From: Luiz Augusto von Dentz @ 2011-03-03 19:54 UTC (permalink / raw)
  To: Slawomir Bochenski; +Cc: linux-bluetooth
In-Reply-To: <AANLkTi=nhd5rzyL+YK6MjvUDzG8bwagZ6-Vt1j=OKq2T@mail.gmail.com>

Hi,

On Thu, Mar 3, 2011 at 12:20 PM, Slawomir Bochenski <lkslawek@gmail.com> wrote:
> On Thu, Mar 3, 2011 at 4:08 PM, Luiz Augusto von Dentz
> <luiz.dentz@gmail.com> wrote:
>> Hi,
>>
>> On Thu, Mar 3, 2011 at 11:09 AM, Slawomir Bochenski <lkslawek@gmail.com> wrote:
>>> On 3/3/11, Luiz Augusto von Dentz <luiz.dentz@gmail.com> wrote:
>>>> Hi,
>>>>
>>>> On Thu, Mar 3, 2011 at 6:58 AM, Slawomir Bochenski <lkslawek@gmail.com>
>>>> wrote:
>>>>> Hi,
>>>>>
>>>>> On Wed, Mar 2, 2011 at 10:12 PM, Luiz Augusto von Dentz
>>>>> <luiz.dentz@gmail.com> wrote:
>>>>>> I guess naming the file and plugin 'map' would make more sense here,
>>>>>> we don't want to confuse people what this file is about.
>>>>>
>>>>> There are two things which makes MAP - MAS and MNS. It is not like any
>>>>> other plugin we have here. The communication goes both ways, i.e. in
>>>>> full implementation there are OBEX server and OBEX client present on
>>>>> _both_ sides. As generally architecture of obexd and obex-client
>>>>> currently allows OBEX servers to be implemented only in obexd and OBEX
>>>>> clients in obex-client, it is easy to imagine that in order to add
>>>>> full MAP client role, there would be need for another plugin in obexd
>>>>> for MNS.
>>>>
>>>> But that doesn't solve any problem since the profile as a whole need
>>>> both client and server side it make no sense to have one without the
>>>> other, we can still have different drivers for each sides but the
>>>> plugin should be the same, it is a single profile not two.
>>>>
>>>
>>> Let me rephrase this:
>>> +-------+-------------+---------------+
>>> |MAP    | obex-client | client/mns.c  |
>>> |Server |             |     / \       |
>>> |role   |             |      |        |
>>> |       +-------------|    D-Bus      |
>>> |       | obexd       |      |        |
>>> |       |             |     \ /       |
>>> |       |             | plugins/mas.c |
>>> +-------+-------------+---------------+
>>>
>>> +-------+-------------+---------------+
>>> |MAP    | obex-client | client/mas.c  |
>>> |Client |             |     / \       |
>>> |role   |             |      |        |
>>> |       +-------------|    D-Bus      |
>>> |       | obexd       |      |        |
>>> |       |             |     \ /       |
>>> |       |             | plugins/mns.c |
>>> +-------+-------------+---------------+
>>>
>>>>> So there can be mns.c and mas.c, both in obexd, both completely
>>>>> independent - each one of them having nothing in common, i.e. user can
>>>>> run mns when he wants to be MAP client, mas when he wants to be MAP
>>>>> server or mas and mns when he likes to be both.
>>>>>
>>>>> Therefore naming it "map" would confuse more those who know what is
>>>>> MAP and what they really want.
>>>>
>>>> Again if they cannot be qualified separately then it make no sense to
>>>> separate them in two plugin, the logical separation can happen on
>>>> driver level.
>>>
>>> So yes, they most definitely can be qualified separately.
>>
>> Sorry but I doubt you can, MAS and MSN are not profiles they just
>> represent services, besides it is mandatory to support both MAS and
>> MNS in MSE see Table 4-1:MAP features, so at least for obexd it
>> doesn't make much sense to have them separated in two plugins, they
>> can be separated in different files which are used by the same plugin,
>> this make it easier to enable/disable MAP as o whole.
> Please read me again. Especially take a longer look at the graphics
> with roles presented. The plugins/mns.c presented here _does not_ have
> _anything_ to do with plugins/mas.c - they are used in completely
> different roles. Once again: they are NOT part of the same thing. See
> chapter 2.1 in MAP specification. What will be qualified _together_ is
> plugin/mas.c and client/mns.c.

Yep, another design decision you took without consulting us, I believe
MSE should be completely implemented on obexd and MCE on obex-client,
why do you thing involving two processes here would make sense? There
is nothing prevent us to implement client code on obexd nor server
code on obex-client, this was a design choice you took which doesn't
mean it can't work using MSE/MCE separation.

>>>>>> Also Ive been thinking on removing this internal APIs for backend,
>>>>>> each would implemented as plugin/mimetype driver directly and we can
>>>>>> create basic drivers for pbap and map and export its callbacks on
>>>>>> pbap.h and map.h respectively as we do for pcsuite which uses ftp
>>>>>> driver callbacks.
>>>>>
>>>>> I really hope that you will keep this in "thinking stage" for now. I
>>>>> see problems coming. I'd rather prefer to use what we have now and
>>>>> what works. There might be some parts that won't fit well in this new
>>>>> philosophy. It would be better to postpone considering such changes in
>>>>> MAP to the point when it will be in repository in a more complete
>>>>> form.
>>>>
>>>> It should not cause any problem, because core only knows about the
>>>> mimetype drivers, the backend interface is a plugin specific API. In
>>>> theory one could re implement pbap plugin which would have another
>>>> backend interface. If we have the backend implementing the mimetype
>>>> driver the only thing that changes is that no API is needed between
>>>> e.g. pbap plugin and the backend.
>>>>
>>>> Note that one of the worst problems with current pbap implementation
>>>> is the backend API, because it has to handle things like asynchronous
>>>> requests and cancel requests which comes from mimetype driver it had
>>>> to change several times during the development, I don't want this to
>>>> happen with map.
>>>
>>> This already happened with MAP and it works. It is done differently than
>>> in PBAP, for example handling of application parameters and cases when
>>> body is sent and when it is not is done more cleanly. And I've already
>>> seen the problems closer to the end of the MAP implementation road. What
>>> you're proposing will make this road more bumpy.
>>
>> Sorry, but until this reach upstream you cannot assumed it has
>> happened. That why we suggest sending us patches earlier so we can
>> review and discuss architect and design aspects not only code, now
>> that we had more experience with the backend interface we could
>> actually experiment the direct approach without creating more APIs,
>> usually it is easier to add API but hard to remove them once a lot of
>> code depend on them. What you may suggest is to integrate MAP
>> implementation as it is and latter change it, but please communicate
>> before about design decisions, there is no need to develop this
>> completely before sending upstream.
> PBAP is much simpler than MAP. Thus it may be tempting to do
> assumptions about MAP using previous experiences. This may not lead to
> good conclusions.

If mimetype driver API was not able to implement the drivers for MAP
you would have to change it, I don't see any modification to
mimetype.h, so it looks exactly like pbap, mimetype driver is used to
extract the request information to pass to backend via some API.

Please if you have a use case for MAP that with mimetype driver it
cannot be implement please provide it, otherwise I would consider that
you meant the backend is much more complex, but the requests are quite
similar.


-- 
Luiz Augusto von Dentz
Computer Engineer

^ permalink raw reply

* RFC: LE Security Manager and next steps
From: Brian Gix @ 2011-03-03 19:55 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: vinicius.gomes, johan.hedberg


Hi Vinicius & All,

I am starting to move forward on the LE Security Manager for bluez.  I 
am currently using the patches submitted by Vinicius for bluetooth-next, 
and hope that they are accepted by Gustavo soon, but at some point, I 
will be forced to move forward with or without that acceptance.

My more immediate attention is therefore placed on key storage (LTK, 
IRK, CSRK), and high level APIs, in particular Passkey agents for MITM 
support.

If anyone is working these problem already, I would like to discuss 
details, so that we are not coming up with competing solutions.  The 
main reason I would like Vinicius' patches accepted sooner rather than 
later is so that I (and others) can start contributing these next pieces 
without creating a divergence headache.

To begin with, I am planning on making the key storage part of the 
existing system used by BR/EDR. I am primarily concerned with Dual Mode 
devices, and we believe that from a "big system" point of view, that 
most of the differences between remote dual-mode and remote LE-only can 
be largely abstracted and out of sight by high level apps.  The main 
differences between LE keys and BR/EDR keys of course is that there are 
multiple keys per "pairs of devices", and except for LTKs, they are used 
very differently.

Also, I understand that some people think that Write-Cmd signing (CSRK) 
and verification should be a function of GATT/ATT in User space, and 
others think it should be handled down in the SM kernel on the way out 
(and in).  I know that the crypto library is being brought into the 
kernel for STK resolution, and this would seem to point towards kernel 
based signing and verification.

Privacy is the biggest problem however.  Identity *resolution* can of 
course be done at the kernel level but if addresses change, we will need 
to come up with a plan as to how to deal with everything up to and 
including dbus object-paths that currently include an ascii 
representation of the BD Addr as part of the path.  At the highest 
(DBus) level I am thinking that a signal on the original object path 
might work when we connect/detect a new address for an existing device, 
and an object path which is then an extension of the originally paired 
device:

If Original was:
/org/bluez/3456/hci0/dev_XX_XX_XX_XX_XX_XX

The Private could be:
/org/bluez/3456/hci0/dev_XX_XX_XX_XX_XX_XX/priv_YY_YY_YY_YY_YY_YY


Anyway, we are starting work on this soon, so if there is 
competing/complimentary work being done, I would really like to hear 
from you.  There is a lot to be done here, and I'd like to have the 
architectural conversations sooner rather than later.

I would also like to hear from you if you simply have a good idea of how 
you think these LE pieces should be architected, and haven't started 
writing code.



-- 
Brian Gix
bgix@codeaurora.org
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply

* Re: RFC: LE Security Manager and next steps
From: Vinicius Costa Gomes @ 2011-03-04  1:37 UTC (permalink / raw)
  To: Brian Gix; +Cc: linux-bluetooth
In-Reply-To: <4D6FF23D.5020608@codeaurora.org>

Hi Brian,

On 11:55 Thu 03 Mar, Brian Gix wrote:
> 
> Hi Vinicius & All,
> 
> I am starting to move forward on the LE Security Manager for bluez.
> I am currently using the patches submitted by Vinicius for
> bluetooth-next, and hope that they are accepted by Gustavo soon, but
> at some point, I will be forced to move forward with or without that
> acceptance.

I hope so too. There are still some still some details to be sorted out,
but I think that the meat of those patches will stay as they are right now.

> 
> My more immediate attention is therefore placed on key storage (LTK,
> IRK, CSRK), and high level APIs, in particular Passkey agents for
> MITM support.
> 
> If anyone is working these problem already, I would like to discuss
> details, so that we are not coming up with competing solutions.  The
> main reason I would like Vinicius' patches accepted sooner rather
> than later is so that I (and others) can start contributing these
> next pieces without creating a divergence headache.
> 

I have a very simple implementation of the key distribution part, for now
it is focused on only the LTK. As I did a lot of experiments while writing
it, the code still a mess. I hope to have a cleaner version soon and will
send a RFC, so more people can take a look and test it, which was extremely
useful the last time :-)

I think that the most important fact about this implementation is that it is
dependend on the Management Interface[1]. It needs this interface for
communicating userspace about new keys and so userspace loads the stored
keys when the userspace daemon is run.

> To begin with, I am planning on making the key storage part of the
> existing system used by BR/EDR. I am primarily concerned with Dual
> Mode devices, and we believe that from a "big system" point of view,
> that most of the differences between remote dual-mode and remote
> LE-only can be largely abstracted and out of sight by high level
> apps.  The main differences between LE keys and BR/EDR keys of
> course is that there are multiple keys per "pairs of devices", and
> except for LTKs, they are used very differently.

For now I have a separate storage for LTKs. For the other kinds of
keys I am still not sure how to store/use them. Right now, your idea
holds, it is completely hidden from the apps how the pairing happened.

> 
> Also, I understand that some people think that Write-Cmd signing
> (CSRK) and verification should be a function of GATT/ATT in User
> space, and others think it should be handled down in the SM kernel
> on the way out (and in).  I know that the crypto library is being
> brought into the kernel for STK resolution, and this would seem to
> point towards kernel based signing and verification.

How/where to do signing is a very good question. I just have a small
preference about doing it in userspace (most of the ATT stuff is there).
But it is just a gut feeling.

This is something that any form of input will be awesome. 

> 
> Privacy is the biggest problem however.  Identity *resolution* can
> of course be done at the kernel level but if addresses change, we
> will need to come up with a plan as to how to deal with everything
> up to and including dbus object-paths that currently include an
> ascii representation of the BD Addr as part of the path.  At the
> highest (DBus) level I am thinking that a signal on the original
> object path might work when we connect/detect a new address for an
> existing device, and an object path which is then an extension of
> the originally paired device:
> 
> If Original was:
> /org/bluez/3456/hci0/dev_XX_XX_XX_XX_XX_XX
> 
> The Private could be:
> /org/bluez/3456/hci0/dev_XX_XX_XX_XX_XX_XX/priv_YY_YY_YY_YY_YY_YY
>

Yeah, this is the most serious problem. One thought that happened some
time ago, was that the DBus path doesn't have to have the address, it is
just a path, we could change the way we name the objects, as long as the
naming is consistent i.e. the same device will have always the same path.

But even without this restriction I guess there are few problems that 
need be solved before we can support Privacy the Right Way. In short,
any help with this will be great :-)

> 
> Anyway, we are starting work on this soon, so if there is
> competing/complimentary work being done, I would really like to hear
> from you.  There is a lot to be done here, and I'd like to have the
> architectural conversations sooner rather than later.
> 
> I would also like to hear from you if you simply have a good idea of
> how you think these LE pieces should be architected, and haven't
> started writing code.
> 
> 
> 
> -- 
> Brian Gix
> bgix@codeaurora.org
> Employee of Qualcomm Innovation Center, Inc.
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum


Cheers,
-- 
Vinicius

[1] http://www.bluez.org/the-management-interface/

^ permalink raw reply

* RE: RFC: LE Security Manager and next steps
From: Mike Tsai @ 2011-03-04  2:36 UTC (permalink / raw)
  To: Vinicius Costa Gomes, Brian Gix; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <20110304013706.GA20251@piper>

Hi,

-----Original Message-----
From: linux-bluetooth-owner@vger.kernel.org [mailto:linux-bluetooth-owner@vger.kernel.org] On Behalf Of Vinicius Costa Gomes
Sent: Thursday, March 03, 2011 5:37 PM
To: Brian Gix
Cc: linux-bluetooth@vger.kernel.org
Subject: Re: RFC: LE Security Manager and next steps

Hi Brian,

On 11:55 Thu 03 Mar, Brian Gix wrote:
> 
> Hi Vinicius & All,
> 
> I am starting to move forward on the LE Security Manager for bluez.
> I am currently using the patches submitted by Vinicius for
> bluetooth-next, and hope that they are accepted by Gustavo soon, but
> at some point, I will be forced to move forward with or without that
> acceptance.

I hope so too. There are still some still some details to be sorted out,
but I think that the meat of those patches will stay as they are right now.

> 
> My more immediate attention is therefore placed on key storage (LTK,
> IRK, CSRK), and high level APIs, in particular Passkey agents for
> MITM support.
> 
> If anyone is working these problem already, I would like to discuss
> details, so that we are not coming up with competing solutions.  The
> main reason I would like Vinicius' patches accepted sooner rather
> than later is so that I (and others) can start contributing these
> next pieces without creating a divergence headache.
> 

I have a very simple implementation of the key distribution part, for now
it is focused on only the LTK. As I did a lot of experiments while writing
it, the code still a mess. I hope to have a cleaner version soon and will
send a RFC, so more people can take a look and test it, which was extremely
useful the last time :-)

I think that the most important fact about this implementation is that it is
dependend on the Management Interface[1]. It needs this interface for
communicating userspace about new keys and so userspace loads the stored
keys when the userspace daemon is run.

> To begin with, I am planning on making the key storage part of the
> existing system used by BR/EDR. I am primarily concerned with Dual
> Mode devices, and we believe that from a "big system" point of view,
> that most of the differences between remote dual-mode and remote
> LE-only can be largely abstracted and out of sight by high level
> apps.  The main differences between LE keys and BR/EDR keys of
> course is that there are multiple keys per "pairs of devices", and
> except for LTKs, they are used very differently.

For now I have a separate storage for LTKs. For the other kinds of
keys I am still not sure how to store/use them. Right now, your idea
holds, it is completely hidden from the apps how the pairing happened.

[MT]The Keys can be stored based on the public or static address. CSRK is used
For data signing, LTK is used for encryption and IDK is used for resolving private 
Address. Could it be possible to store/retrieve these keys all from inside the SM context? 
That would save many additional work to create management interface?
> 
> Also, I understand that some people think that Write-Cmd signing
> (CSRK) and verification should be a function of GATT/ATT in User
> space, and others think it should be handled down in the SM kernel
> on the way out (and in).  I know that the crypto library is being
> brought into the kernel for STK resolution, and this would seem to
> point towards kernel based signing and verification.

How/where to do signing is a very good question. I just have a small
preference about doing it in userspace (most of the ATT stuff is there).
But it is just a gut feeling.

This is something that any form of input will be awesome. 

[MT]ATT is in user space and only it can recognize the need to either sign
The command or verify the data signing. The CMAC algorithm can be implement
On user space, however, its input parameters have to come from SM. A 
Possible solution would be allowing ATT to call SM API to sign/verify the
Data signing.

> 
> Privacy is the biggest problem however.  Identity *resolution* can
> of course be done at the kernel level but if addresses change, we
> will need to come up with a plan as to how to deal with everything
> up to and including dbus object-paths that currently include an
> ascii representation of the BD Addr as part of the path.  At the
> highest (DBus) level I am thinking that a signal on the original
> object path might work when we connect/detect a new address for an
> existing device, and an object path which is then an extension of
> the originally paired device:
> 
> If Original was:
> /org/bluez/3456/hci0/dev_XX_XX_XX_XX_XX_XX
> 
> The Private could be:
> /org/bluez/3456/hci0/dev_XX_XX_XX_XX_XX_XX/priv_YY_YY_YY_YY_YY_YY
>

Yeah, this is the most serious problem. One thought that happened some
time ago, was that the DBus path doesn't have to have the address, it is
just a path, we could change the way we name the objects, as long as the
naming is consistent i.e. the same device will have always the same path.

But even without this restriction I guess there are few problems that 
need be solved before we can support Privacy the Right Way. In short,
any help with this will be great :-)

[MTsai]One solution is not to store private address, but only the public address at user space level. Private
Address in a temporary thing (update every 15 minutes) and it can always be converted back to Public address,
Or else discarded if can't. The Appl will only base on public address for all the operations. 


> 
> Anyway, we are starting work on this soon, so if there is
> competing/complimentary work being done, I would really like to hear
> from you.  There is a lot to be done here, and I'd like to have the
> architectural conversations sooner rather than later.
> 
> I would also like to hear from you if you simply have a good idea of
> how you think these LE pieces should be architected, and haven't
> started writing code.
> 
> 
> 
> -- 
> Brian Gix
> bgix@codeaurora.org
> Employee of Qualcomm Innovation Center, Inc.
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum


Cheers,
-- 
Vinicius

Regards,

Mike


[1] http://www.bluez.org/the-management-interface/
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: re "bluetooth disabled" and "[BUG] usb problems in .38-rc3+"
From: Ville Tervo @ 2011-03-04  4:47 UTC (permalink / raw)
  To: Mikko Vinni, linux-bluetooth, Justin P. Mattock, Ed Tomlinson,
	Gustavo F. Padovan
In-Reply-To: <20110303143154.GA2342@jh-x301>

Hi,

On Thu, Mar 03, 2011 at 11:31:54AM -0300, ext Johan Hedberg wrote:
> Hi Mikko,
> 
> On Thu, Mar 03, 2011, Mikko Vinni wrote:
> > > I can't reproduce this issue with any of my Bluetooth  adapters (I tested
> > > with 6 different ones). Could you get us the hcidump of  what happens
> > > when bluetoothd tries to switch on the adapter for the very  first time?
> > > Probably you'll need to disable starting of bluetoothd when your  system
> > > boots so that you have the chance to run hcidump first. Additionally,  if
> > > possible, could you enable dynamic debug in your kernel and get the  logs
> > > from hci_core.c and hci_event.c? Typically you'd enable this  with
> > > something like:
> > > 
> > > echo 'file hci_event.c +p' >  /sys/kernel/debug/dynamic_debug/control
> > > echo 'file hci_core.c +p' >  /sys/kernel/debug/dynamic_debug/control
> > > 
> > > Hopefully those logs will give  some better idea of what's going on since
> > > the logs provided so far aren't  really helpful.
> > > 
> > 
> > - Compiled the kernel (2.6.38-rc7 now) with dynamic debug
> > - Commented out the lines to start bluetoothd from /lib/udev/rules.d/
> > - Killed bluetoothd
> > - rmmod'ed all bluetooth modules and then modprobe'd rfcomm (which pulls
> > in all the others) (this resets the situation so that the bug appears -
> > when unplugging and plugging the adapter in the working state it keeps
> > on working)
> > - enabled dynamic debug for hci_core.c, hci_event.c, and rfcomm/core.c
> > - plugged in the bluetooth adapter
> > - hcidump -w hcidump_ddebug (parsed version below)
> > - bluetoothd -d
> > - run hciconfig (without parameters) a couple of times
> > - waited some minutes
> > - run hciconfig -a (around 08:18:37 in the logs)
> > - adapter led starts blinking (and e.g. blueman-applet sees it)
> > - messages from syslog further below
> > 
> > Do these help?
> 
> They do indeed. However, the simplest short-term fix I can come up for
> this is in user space and not the kernel.
> 
> > HCI sniffer - Bluetooth packet analyzer ver 2.0
> > btsnoop version: 1 datalink type: 1002
> > 2011-03-03 08:14:38.386728 < HCI Command: Reset (0x03|0x0003) plen 0
> > 2011-03-03 08:14:38.386759 > HCI Event: Command Status (0x0f) plen 4
> >     Unknown (0x00|0x0000) status 0x00 ncmd 1
> > 2011-03-03 08:14:38.386810 < HCI Command: Read Local Supported Features 
> > (0x04|0x0003) plen 0
> > 2011-03-03 08:14:38.524768 > HCI Event: Command Complete (0x0e) plen 4
> >     Reset (0x03|0x0003) ncmd 1
> >     status 0x00
> 
> I'm not sure if this is correct. The command status for opcode 0 means
> that we can start sending commands to the controller, however since
> there's a pending reset command maybe we should be waiting for its
> command complete event before sending the features command. Or should we
> be sending the Reset command at all so early and instead wait for the
> command status before sending it?

No need to wait for NOP event. And after reset no other commands should be sent
before cmd complete.

At least according the spec. So reset should be handled in a special way.

> 
> In any case what's happening is that there's never a command complete
> for the local features. This is one of those commands that user space
> tracks to determine that the adapter is initialized so if it never comes
> the adapter remains uninitialized from a bluetoothd perspective. There
> is supposed to be some work-around code in bluetoothd for this kind of
> situations, but due to the patch you found in the kernel the code
> doesn't get triggered since the "up" flag is not set when the situation
> happens. The patch I've attached removed this check for the flag. Could
> you try and see if it helps?
> 
> Meanwhile, it'd be nice to get some input from more knowledgeable
> persons on whether the kernel is doing the right thing in not waiting
> for the command status for opcode 0 before sending the HCI_Reset.

It's doing wrong currently.

-- 
Ville

^ permalink raw reply

* Re: [PATCH 0/4] Message Access Profile plugin
From: Slawomir Bochenski @ 2011-03-04  8:50 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <AANLkTim6T15=+UFQDqjOR=VchoFAWtsqo-zKjTdft3MZ@mail.gmail.com>

Hello Luiz,

On Thu, Mar 3, 2011 at 8:54 PM, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
> Hi,
>
> On Thu, Mar 3, 2011 at 12:20 PM, Slawomir Bochenski <lkslawek@gmail.com> wrote:
>> On Thu, Mar 3, 2011 at 4:08 PM, Luiz Augusto von Dentz
>> <luiz.dentz@gmail.com> wrote:
>>> Hi,
>>>
>>> On Thu, Mar 3, 2011 at 11:09 AM, Slawomir Bochenski <lkslawek@gmail.com> wrote:
>>>> On 3/3/11, Luiz Augusto von Dentz <luiz.dentz@gmail.com> wrote:
>>>>> Hi,
>>>>>
>>>>> On Thu, Mar 3, 2011 at 6:58 AM, Slawomir Bochenski <lkslawek@gmail.com>
>>>>> wrote:
>>>>>> Hi,
>>>>>>
>>>>>> On Wed, Mar 2, 2011 at 10:12 PM, Luiz Augusto von Dentz
>>>>>> <luiz.dentz@gmail.com> wrote:
>>>>>>> I guess naming the file and plugin 'map' would make more sense here,
>>>>>>> we don't want to confuse people what this file is about.
>>>>>>
>>>>>> There are two things which makes MAP - MAS and MNS. It is not like any
>>>>>> other plugin we have here. The communication goes both ways, i.e. in
>>>>>> full implementation there are OBEX server and OBEX client present on
>>>>>> _both_ sides. As generally architecture of obexd and obex-client
>>>>>> currently allows OBEX servers to be implemented only in obexd and OBEX
>>>>>> clients in obex-client, it is easy to imagine that in order to add
>>>>>> full MAP client role, there would be need for another plugin in obexd
>>>>>> for MNS.
>>>>>
>>>>> But that doesn't solve any problem since the profile as a whole need
>>>>> both client and server side it make no sense to have one without the
>>>>> other, we can still have different drivers for each sides but the
>>>>> plugin should be the same, it is a single profile not two.
>>>>>
>>>>
>>>> Let me rephrase this:
>>>> +-------+-------------+---------------+
>>>> |MAP    | obex-client | client/mns.c  |
>>>> |Server |             |     / \       |
>>>> |role   |             |      |        |
>>>> |       +-------------|    D-Bus      |
>>>> |       | obexd       |      |        |
>>>> |       |             |     \ /       |
>>>> |       |             | plugins/mas.c |
>>>> +-------+-------------+---------------+
>>>>
>>>> +-------+-------------+---------------+
>>>> |MAP    | obex-client | client/mas.c  |
>>>> |Client |             |     / \       |
>>>> |role   |             |      |        |
>>>> |       +-------------|    D-Bus      |
>>>> |       | obexd       |      |        |
>>>> |       |             |     \ /       |
>>>> |       |             | plugins/mns.c |
>>>> +-------+-------------+---------------+
>>>>
>>>>>> So there can be mns.c and mas.c, both in obexd, both completely
>>>>>> independent - each one of them having nothing in common, i.e. user can
>>>>>> run mns when he wants to be MAP client, mas when he wants to be MAP
>>>>>> server or mas and mns when he likes to be both.
>>>>>>
>>>>>> Therefore naming it "map" would confuse more those who know what is
>>>>>> MAP and what they really want.
>>>>>
>>>>> Again if they cannot be qualified separately then it make no sense to
>>>>> separate them in two plugin, the logical separation can happen on
>>>>> driver level.
>>>>
>>>> So yes, they most definitely can be qualified separately.
>>>
>>> Sorry but I doubt you can, MAS and MSN are not profiles they just
>>> represent services, besides it is mandatory to support both MAS and
>>> MNS in MSE see Table 4-1:MAP features, so at least for obexd it
>>> doesn't make much sense to have them separated in two plugins, they
>>> can be separated in different files which are used by the same plugin,
>>> this make it easier to enable/disable MAP as o whole.
>> Please read me again. Especially take a longer look at the graphics
>> with roles presented. The plugins/mns.c presented here _does not_ have
>> _anything_ to do with plugins/mas.c - they are used in completely
>> different roles. Once again: they are NOT part of the same thing. See
>> chapter 2.1 in MAP specification. What will be qualified _together_ is
>> plugin/mas.c and client/mns.c.
> Yep, another design decision you took without consulting us, I believe
> MSE should be completely implemented on obexd and MCE on obex-client,
> why do you thing involving two processes here would make sense?

Actually, with this whole plethora of small decisions I did not feel
urge to discuss, this was a notable exception. Before I even wrote a
single line of notifications-related code I considered carefully
multiple possibilities. And then I shared my findings on #obexd @
freenode asking specifically what would be the preferred way to
implement this. Johan took part in the discussion addressing this and
we came to conclusion, that even though this needs two processes
running (which in fact was what personally make me a little bit
reluctant) this is the cleanest and simplest way to do this.

> There is nothing prevent us to implement client code on obexd nor server
> code on obex-client, this was a design choice you took

Are we still talking about obexd or is it obex-data-server (which do
have client and server functionality integrated in one daemon)? This
is far more complicated. As far as I know currently there is nothing
allowing implementing OBEX clients in obexd nor allowing implementing
OBEX servers in obex-client. Even in server role, when required OBEX
client is simple this would require adding large parts from
obex-client to obexd (SDP browsing, actual client event handlers) and
it might be not as easy as linking it with parts of obex-client.
Unless we want to achieve the same architecture that obex-data-server
has and eventually melt obex-client and obexd into one daemon which
binds them all ;), I don't think it is possible

For MSE I was thinking about manually adding parts for searching SDP,
making my own bluetooth socket and using openobex directly. This would
make the code horrible, but still, this is a possibility. I would not
want to go there, though. In case of MCE there is no requirement that
MNS server has to be present, so they can be left separated between
obex-client and obexd and do not even talk to each other, only to the
MCE client applications that would want to utilize them.

> which doesn't mean it can't work using MSE/MCE separation.

Please restate this sentence ending. Well, I just plainly do not get
it at all. Even whether you meant something negative or positive. :)

>>>>>>> Also Ive been thinking on removing this internal APIs for backend,
>>>>>>> each would implemented as plugin/mimetype driver directly and we can
>>>>>>> create basic drivers for pbap and map and export its callbacks on
>>>>>>> pbap.h and map.h respectively as we do for pcsuite which uses ftp
>>>>>>> driver callbacks.
>>>>>>
>>>>>> I really hope that you will keep this in "thinking stage" for now. I
>>>>>> see problems coming. I'd rather prefer to use what we have now and
>>>>>> what works. There might be some parts that won't fit well in this new
>>>>>> philosophy. It would be better to postpone considering such changes in
>>>>>> MAP to the point when it will be in repository in a more complete
>>>>>> form.
>>>>>
>>>>> It should not cause any problem, because core only knows about the
>>>>> mimetype drivers, the backend interface is a plugin specific API. In
>>>>> theory one could re implement pbap plugin which would have another
>>>>> backend interface. If we have the backend implementing the mimetype
>>>>> driver the only thing that changes is that no API is needed between
>>>>> e.g. pbap plugin and the backend.
>>>>>
>>>>> Note that one of the worst problems with current pbap implementation
>>>>> is the backend API, because it has to handle things like asynchronous
>>>>> requests and cancel requests which comes from mimetype driver it had
>>>>> to change several times during the development, I don't want this to
>>>>> happen with map.
>>>>
>>>> This already happened with MAP and it works. It is done differently than
>>>> in PBAP, for example handling of application parameters and cases when
>>>> body is sent and when it is not is done more cleanly. And I've already
>>>> seen the problems closer to the end of the MAP implementation road. What
>>>> you're proposing will make this road more bumpy.
>>>
>>> Sorry, but until this reach upstream you cannot assumed it has
>>> happened. That why we suggest sending us patches earlier so we can
>>> review and discuss architect and design aspects not only code, now
>>> that we had more experience with the backend interface we could
>>> actually experiment the direct approach without creating more APIs,
>>> usually it is easier to add API but hard to remove them once a lot of
>>> code depend on them. What you may suggest is to integrate MAP
>>> implementation as it is and latter change it, but please communicate
>>> before about design decisions, there is no need to develop this
>>> completely before sending upstream.
>> PBAP is much simpler than MAP. Thus it may be tempting to do
>> assumptions about MAP using previous experiences. This may not lead to
>> good conclusions.
>
> If mimetype driver API was not able to implement the drivers for MAP
> you would have to change it, I don't see any modification to
> mimetype.h, so it looks exactly like pbap, mimetype driver is used to
> extract the request information to pass to backend via some API.
>
> Please if you have a use case for MAP that with mimetype driver it
> cannot be implement please provide it, otherwise I would consider that
> you meant the backend is much more complex, but the requests are quite
> similar.

Let me bullet point some examples:

* When the notifications are active the backend can call plugin at any
time, not in line with any request currently processed. Backend does
it when it becomes aware of a new message in repository. This is done
by calling glue function, implemented in the plugin.

* Additionally, as backend has a better way of making decisions about
pending notifications (some of these may become outdated before we are
ready to send them), it also does the queuing. It starts queuing
notifications when transport plugin informs it that client wishes to
receive notifications, and this happens right when
SetNotificationRegistration is received. Queuing is needed:
- because of delay between getting SetNotificationRegistration and
making the connection back to MNS OBEX server on client's side,
- because we have to wait for client response on MNS channel to
previous notification before we can send the next one.

So plugin uses another glue functions to say that it is ready to send
next notification in line.

* About this theory regarding another PBAP plugin. I assume you meant
that one wouldn't want to implement exactly another PBAP plugin and
more likely someone would want to develop another profile needing the
access to the same data PBAP does (or parts of it).

I suppose that this is the relation between pcsuite and filesystem.c.
However PBAP or MAP is not a filesystem.c - the data sent is not raw
(or rather depending only on the underlaying accessed object). It is
formatted in some profile-specific fashion. I can see that current
implementation of PBAP makes the backend doing all the work of
formatting data, so this data is useless in case of some new profile
that needs to get phone book entries and possibly send them in it's
own format.

This is not what I've chosen for MAP. For instance message listing
object in MAP profile takes form of XML document. The backend role is
to get all the meta data it can possibly get that is useful in this
listing and it returns this data to transport plugin in struct. This
way the data is really reusable in any other scenarios. Escaping
strings and formatting XML is done in plugin. This also prevents
repetitions in code of multiple backends.

So again - implementing storage backends as mime drivers removes the
flexibility of choosing data structure appropriate for situation.

> --
> Luiz Augusto von Dentz
> Computer Engineer
>



-- 
Slawomir Bochenski

^ permalink raw reply

* Re: [PATCH] Bluetooth: Add counter for not acked HCI commands
From: Andrzej Kaczmarek @ 2011-03-04 12:37 UTC (permalink / raw)
  To: Brian Gix
  Cc: linux-bluetooth@vger.kernel.org,
	par-gunnar.p.hjalmdahl@stericsson.com,
	henrik.possung@stericsson.com
In-Reply-To: <4D6D480E.7080908@codeaurora.org>

Hi Brian,

On 01.03.2011 20:25, Brian Gix wrote:
> The problem you describe sounds like one I had to solve in the past, but
> unfortunately, I think it may be a little more difficult to solve here.
>    This particular baseband appears to have an outstanding Cmd queue of
> 2.  It also appears to consume one of them for extended periods of time
> when making requests of the remote device, and using the NOP
> Cmd-Status-Event to inform the host that the slot is now free.
>
> As you are observing, the completion of the task (triggering additional
> requests locally) overlaps with these NOP responses, giving a false
> count to the host of available cmd slots.
>
> Personally, I consider this to be a baseband bug, which could have been
> avoided by having a max outstanding queue of 1.

This particular controller uses 1 credit for each command that is being 
processed and having max outstanding queue of 1 would make some 
scenarios impossible - consider authentication with 
HCI_Authentication_Request pending and other HCI command to be sent in
parallel.

Since spec does not specify how credits should be used so I don't 
consider this a baseband bug, more like a design decision.

> Note 1:
> My biggest problem with your patch is the point marked above.  I agree
> that it would solve the problem you observed, and your overall analysis
> of the situation, but because of the way this particular baseband is
> operating, and the way I have seen other basebands operate in the past,
> I think this decision point as to when to send the next command is
> incorrect.
>
> A flaw in the HCI command handshaking paradigm is that a baseband can
> decide to take away or not take away one of these slots, and give you
> notification asynchronously. I have seen basebands with presumptively
> two slots return a cmd status with ncmd 0 when getting a remote device
> name, if no ACL connection was currently established, for example.
>
> The safest way I have seen this problem handled is to force a
> psuedo-single-threading of commands on the system by NEVER sending a
> command while another command has not yet received it's Cmd-Status or
> Cmd-Cmplt event. In other words, instead of the test for cmd_cnt>
> cmd_not_acked, I would simply make into cmd_cnt&&  !cmd_not_acked.

I never saw baseband which behaves as you described so I assumed that 
each command should take no more that 1 credit. But again, since spec is 
not very specific at this point perhaps this assumption was wrong, so 
making this psuedo-single-threading as you described sounds reasonable 
to me.

>>    			atomic_dec(&hdev->cmd_cnt);
>> +			atomic_inc(&hdev->cmd_not_ack);
> [...]
>
> Also, I am not sure this means what you may intend it to mean. I think
> that this is intended to do both of these operations "together
> atomically", but that as written, it is possible for an interruption to
> occur between the two operations.

No, I didn't mean to do both of these operations together atomically. I 
followed scheme to update cmd_cnt atomically. Honestly, I'm not sure why 
cmd_cnt is updated atomically while other counters are not, it does not 
guarantee us proper updating of this value - see hci_cmd_task for example.

Perhaps atomic functions should be stripped from cmd_cnt or code should 
be updated more thoroughly to lock access to counters properly. I'll be 
glad to hear opinion on this as well.

BR,
Andrzej

^ permalink raw reply

* [PATCH v5 0/6] Support for out of band association model
From: Szymon Janc @ 2011-03-04 15:08 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: par-gunnar.p.hjalmdahl, henrik.possung, Szymon Janc

Significant change since last version is that oob data is now fed to kernel (or
hciops) and is used while pairing if needed. No need for requesting
providers/agent while pairing. Advantage is less roundtrips and much simpler
implementation.

Whats in the patchset:
- for new kernels implementation in mgmtops
  (with kernel patches from "[PATCH v2 0/4] Support for OOB in mgmt interface")
- for compatibility with older kernels implementation in hciops (mimic mgmt)
- D-Bus plugin only exposes OOB functionality. In future we could also have
  CreateOOB[Paired]Device (or similar) which would act as
  AddRemoteOobData+CreateDevice.


As usual, comments are welcome.


BR,
Szymon Janc
on behalf of ST-Ericsson


Szymon Janc (6):
  Add initial support for Out of Band (OOB) association model
  Add support for Out of Band (OOB) association model in mgmtops
  Add support for Out of Band (OOB) association model in hciops
  Add D-Bus OOB plugin
  Update mgmt-api.txt with OOB commands
  Add oob-api.txt with documentation about OOB D-Bus methods

 Makefile.am       |    8 ++-
 acinclude.m4      |    6 ++
 doc/mgmt-api.txt  |   30 +++++++
 doc/oob-api.txt   |   38 +++++++++
 lib/mgmt.h        |   18 ++++
 plugins/dbusoob.c |  241 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 plugins/hciops.c  |  143 ++++++++++++++++++++++++++++++-
 plugins/mgmtops.c |  127 ++++++++++++++++++++++++++++
 src/adapter.c     |   18 ++++
 src/adapter.h     |   12 +++
 src/oob.c         |   43 ++++++++++
 src/oob.h         |   30 +++++++
 12 files changed, 708 insertions(+), 6 deletions(-)
 create mode 100644 doc/oob-api.txt
 create mode 100644 plugins/dbusoob.c
 create mode 100644 src/oob.c
 create mode 100644 src/oob.h


^ permalink raw reply

* [PATCH v5 1/6] Add initial support for Out of Band (OOB) association model
From: Szymon Janc @ 2011-03-04 15:08 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: par-gunnar.p.hjalmdahl, henrik.possung, Szymon Janc
In-Reply-To: <1299251315-2041-1-git-send-email-szymon.janc@tieto.com>

---
 Makefile.am       |    3 ++-
 plugins/hciops.c  |   31 +++++++++++++++++++++++++++++++
 plugins/mgmtops.c |   31 +++++++++++++++++++++++++++++++
 src/adapter.c     |   18 ++++++++++++++++++
 src/adapter.h     |   12 ++++++++++++
 src/oob.c         |   43 +++++++++++++++++++++++++++++++++++++++++++
 src/oob.h         |   30 ++++++++++++++++++++++++++++++
 7 files changed, 167 insertions(+), 1 deletions(-)
 create mode 100644 src/oob.c
 create mode 100644 src/oob.h

diff --git a/Makefile.am b/Makefile.am
index ec1ca97..573673e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -245,7 +245,8 @@ src_bluetoothd_SOURCES = $(gdbus_sources) $(builtin_sources) \
 			src/adapter.h src/adapter.c \
 			src/device.h src/device.c \
 			src/dbus-common.c src/dbus-common.h \
-			src/event.h src/event.c
+			src/event.h src/event.c \
+			src/oob.h src/oob.c
 src_bluetoothd_LDADD = lib/libbluetooth.la @GLIB_LIBS@ @DBUS_LIBS@ \
 							@CAPNG_LIBS@ -ldl -lrt
 src_bluetoothd_LDFLAGS = -Wl,--export-dynamic \
diff --git a/plugins/hciops.c b/plugins/hciops.c
index fd19ef4..74ff7d5 100644
--- a/plugins/hciops.c
+++ b/plugins/hciops.c
@@ -3558,6 +3558,34 @@ static int hciops_cancel_bonding(int index, bdaddr_t *bdaddr)
 	return 0;
 }
 
+static int hciops_read_local_oob_data (int index)
+{
+	DBG("hci%d", index);
+
+	return -ENOSYS;
+}
+
+static int hciops_add_remote_oob_data (int index, bdaddr_t *bdaddr,
+					uint8_t *hash, uint8_t *randomizer)
+{
+	char addr[18];
+
+	ba2str(bdaddr, addr);
+	DBG("hci%d bdaddr %s", index, addr);
+
+	return -ENOSYS;
+}
+
+static int hciops_remove_remote_oob_data (int index, bdaddr_t *bdaddr)
+{
+	char addr[18];
+
+	ba2str(bdaddr, addr);
+	DBG("hci%d bdaddr %s", index, addr);
+
+	return -ENOSYS;
+}
+
 static struct btd_adapter_ops hci_ops = {
 	.setup = hciops_setup,
 	.cleanup = hciops_cleanup,
@@ -3597,6 +3625,9 @@ static struct btd_adapter_ops hci_ops = {
 	.set_io_capability = hciops_set_io_capability,
 	.create_bonding = hciops_create_bonding,
 	.cancel_bonding = hciops_cancel_bonding,
+	.read_local_oob_data = hciops_read_local_oob_data,
+	.add_remote_oob_data = hciops_add_remote_oob_data,
+	.remove_remote_oob_data = hciops_remove_remote_oob_data,
 };
 
 static int hciops_init(void)
diff --git a/plugins/mgmtops.c b/plugins/mgmtops.c
index a19a6cc..6c840ca 100644
--- a/plugins/mgmtops.c
+++ b/plugins/mgmtops.c
@@ -1669,6 +1669,34 @@ static int mgmt_cancel_bonding(int index, bdaddr_t *bdaddr)
 	return -ENOSYS;
 }
 
+static int mgmt_read_local_oob_data (int index)
+{
+	DBG("hci%d", index);
+
+	return -ENOSYS;
+}
+
+static int mgmt_add_remote_oob_data (int index, bdaddr_t *bdaddr,
+					uint8_t *hash, uint8_t *randomizer)
+{
+	char addr[18];
+
+	ba2str(bdaddr, addr);
+	DBG("hci%d bdaddr %s", index, addr);
+
+	return -ENOSYS;
+}
+
+static int mgmt_remove_remote_oob_data (int index, bdaddr_t *bdaddr)
+{
+	char addr[18];
+
+	ba2str(bdaddr, addr);
+	DBG("hci%d bdaddr %s", index, addr);
+
+	return -ENOSYS;
+}
+
 static struct btd_adapter_ops mgmt_ops = {
 	.setup = mgmt_setup,
 	.cleanup = mgmt_cleanup,
@@ -1708,6 +1736,9 @@ static struct btd_adapter_ops mgmt_ops = {
 	.set_io_capability = mgmt_set_io_capability,
 	.create_bonding = mgmt_create_bonding,
 	.cancel_bonding = mgmt_cancel_bonding,
+	.read_local_oob_data = mgmt_read_local_oob_data,
+	.add_remote_oob_data = mgmt_add_remote_oob_data,
+	.remove_remote_oob_data = mgmt_remove_remote_oob_data,
 };
 
 static int mgmt_init(void)
diff --git a/src/adapter.c b/src/adapter.c
index 2e11832..0c06dda 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3673,3 +3673,21 @@ int adapter_cancel_bonding(struct btd_adapter *adapter, bdaddr_t *bdaddr)
 {
 	return adapter_ops->cancel_bonding(adapter->dev_id, bdaddr);
 }
+
+int btd_adapter_read_local_oob_data(struct btd_adapter *adapter)
+{
+	return adapter_ops->read_local_oob_data(adapter->dev_id);
+}
+
+int btd_adapter_add_remote_oob_data (struct btd_adapter *adapter,
+			bdaddr_t *bdaddr, uint8_t *hash, uint8_t *randomizer)
+{
+	return adapter_ops->add_remote_oob_data(adapter->dev_id, bdaddr, hash,
+								randomizer);
+}
+
+int btd_adapter_remove_remote_oob_data (struct btd_adapter *adapter,
+							bdaddr_t *bdaddr)
+{
+	return adapter_ops->remove_remote_oob_data(adapter->dev_id, bdaddr);
+}
diff --git a/src/adapter.h b/src/adapter.h
index 8bc687d..377908b 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -237,6 +237,10 @@ struct btd_adapter_ops {
 	int (*set_io_capability) (int index, uint8_t io_capability);
 	int (*create_bonding) (int index, bdaddr_t *bdaddr, uint8_t io_cap);
 	int (*cancel_bonding) (int index, bdaddr_t *bdaddr);
+	int (*read_local_oob_data) (int index);
+	int (*add_remote_oob_data) (int index, bdaddr_t *bdaddr, uint8_t *hash,
+							uint8_t *randomizer);
+	int (*remove_remote_oob_data) (int index, bdaddr_t *bdaddr);
 };
 
 int btd_register_adapter_ops(struct btd_adapter_ops *ops, gboolean priority);
@@ -288,3 +292,11 @@ int adapter_create_bonding(struct btd_adapter *adapter, bdaddr_t *bdaddr,
 							uint8_t io_cap);
 
 int adapter_cancel_bonding(struct btd_adapter *adapter, bdaddr_t *bdaddr);
+
+int btd_adapter_read_local_oob_data (struct btd_adapter *adapter);
+
+int btd_adapter_add_remote_oob_data (struct btd_adapter *adapter,
+			bdaddr_t *bdaddr, uint8_t *hash, uint8_t *randomizer);
+
+int btd_adapter_remove_remote_oob_data (struct btd_adapter *adapter,
+							bdaddr_t *bdaddr);
diff --git a/src/oob.c b/src/oob.c
new file mode 100644
index 0000000..56b76ec
--- /dev/null
+++ b/src/oob.c
@@ -0,0 +1,43 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2011  ST-Ericsson SA
+ *
+ *  Author: Szymon Janc <szymon.janc@tieto.com> for ST-Ericsson
+ *
+ *
+ *  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
+ *
+ */
+
+#include "adapter.h"
+#include "oob.h"
+
+static void (*local_oob_read_cb)(struct btd_adapter *adapter, uint8_t *hash,
+		uint8_t *randomizer) = NULL;
+
+void oob_register_cb( void (*cb)(struct btd_adapter *adapter, uint8_t *hash,
+							uint8_t *randomizer))
+{
+	local_oob_read_cb = cb;
+}
+
+void oob_local_data_read(struct btd_adapter *adapter, uint8_t *hash,
+							uint8_t *randomizer)
+{
+	if (local_oob_read_cb)
+		local_oob_read_cb(adapter, hash, randomizer);
+}
diff --git a/src/oob.h b/src/oob.h
new file mode 100644
index 0000000..975cb71
--- /dev/null
+++ b/src/oob.h
@@ -0,0 +1,30 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2011  ST-Ericsson SA
+ *
+ *  Author: Szymon Janc <szymon.janc@tieto.com> for ST-Ericsson
+ *
+ *
+ *  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
+ *
+ */
+
+void oob_register_cb( void (*cb)(struct btd_adapter *adapter, uint8_t *hash,
+							uint8_t *randomizer));
+
+void oob_local_data_read(struct btd_adapter *adapter, uint8_t *hash,
+							uint8_t *randomizer);
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH v5 2/6] Add support for Out of Band (OOB) association model in mgmtops
From: Szymon Janc @ 2011-03-04 15:08 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: par-gunnar.p.hjalmdahl, henrik.possung, Szymon Janc
In-Reply-To: <1299251315-2041-1-git-send-email-szymon.janc@tieto.com>

---
 lib/mgmt.h        |   18 +++++++++
 plugins/mgmtops.c |  102 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 117 insertions(+), 3 deletions(-)

diff --git a/lib/mgmt.h b/lib/mgmt.h
index 7854ab1..bbe64d6 100644
--- a/lib/mgmt.h
+++ b/lib/mgmt.h
@@ -173,6 +173,24 @@ struct mgmt_rp_user_confirm_reply {
 
 #define MGMT_OP_USER_CONFIRM_NEG_REPLY	0x0016
 
+#define MGMT_OP_READ_LOCAL_OOB_DATA	0x0017
+struct mgmt_rp_read_local_oob_data {
+	uint8_t hash[16];
+	uint8_t randomizer[16];
+} __packed;
+
+#define MGMT_OP_ADD_REMOTE_OOB_DATA	0x0018
+struct mgmt_cp_add_remote_oob_data {
+	bdaddr_t bdaddr;
+	uint8_t hash[16];
+	uint8_t randomizer[16];
+} __packed;
+
+#define MGMT_OP_REMOVE_REMOTE_OOB_DATA	0x0019
+struct mgmt_cp_remove_remote_oob_data {
+	bdaddr_t bdaddr;
+} __packed;
+
 #define MGMT_EV_CMD_COMPLETE		0x0001
 struct mgmt_ev_cmd_complete {
 	uint16_t opcode;
diff --git a/plugins/mgmtops.c b/plugins/mgmtops.c
index 6c840ca..4a52be8 100644
--- a/plugins/mgmtops.c
+++ b/plugins/mgmtops.c
@@ -47,6 +47,7 @@
 #include "manager.h"
 #include "device.h"
 #include "event.h"
+#include "oob.h"
 
 #define MGMT_BUF_SIZE 1024
 
@@ -996,6 +997,49 @@ static void get_connections_complete(int sk, uint16_t index, void *buf,
 	read_info(sk, index);
 }
 
+static void read_local_oob_data_complete(int sk, uint16_t index, void *buf,
+								size_t len)
+{
+	struct mgmt_rp_read_local_oob_data *rp = buf;
+	struct btd_adapter *adapter;
+
+	if (len != sizeof(*rp)) {
+		error("Wrong read_local_oob_data_complete event size");
+		return;
+	}
+
+	if (index > max_index) {
+		error("Unexpected index %u in read_local_oob_data_complete",
+								index);
+		return;
+	}
+
+	DBG("hci%u", index);
+
+	adapter = manager_find_adapter_by_id(index);
+
+	if (adapter)
+		oob_local_data_read(adapter, rp->hash, rp->randomizer);
+}
+
+static void read_local_oob_data_failed(int sk, uint16_t index)
+{
+	struct btd_adapter *adapter;
+
+	if (index > max_index) {
+		error("Unexpected index %u in read_local_oob_data_failed",
+								index);
+		return;
+	}
+
+	DBG("hci%u", index);
+
+	adapter = manager_find_adapter_by_id(index);
+
+	if (adapter)
+		oob_local_data_read(adapter, NULL, NULL);
+}
+
 static void mgmt_cmd_complete(int sk, uint16_t index, void *buf, size_t len)
 {
 	struct mgmt_ev_cmd_complete *ev = buf;
@@ -1077,6 +1121,15 @@ static void mgmt_cmd_complete(int sk, uint16_t index, void *buf, size_t len)
 	case MGMT_OP_USER_CONFIRM_NEG_REPLY:
 		DBG("user_confirm_net_reply complete");
 		break;
+	case MGMT_OP_READ_LOCAL_OOB_DATA:
+		read_local_oob_data_complete(sk, index, ev->data, len);
+		break;
+	case MGMT_OP_ADD_REMOTE_OOB_DATA:
+		DBG("add_remote_oob_data complete");
+		break;
+	case MGMT_OP_REMOVE_REMOTE_OOB_DATA:
+		DBG("remove_remote_oob_data complete");
+		break;
 	default:
 		error("Unknown command complete for opcode %u", opcode);
 		break;
@@ -1096,6 +1149,10 @@ static void mgmt_cmd_status(int sk, uint16_t index, void *buf, size_t len)
 	opcode = btohs(bt_get_unaligned(&ev->opcode));
 
 	DBG("status %u opcode %u (index %u)", ev->status, opcode, index);
+
+	if (opcode == MGMT_OP_READ_LOCAL_OOB_DATA)
+		read_local_oob_data_failed(sk, index);
+
 }
 
 static void mgmt_controller_error(int sk, uint16_t index, void *buf, size_t len)
@@ -1671,30 +1728,69 @@ static int mgmt_cancel_bonding(int index, bdaddr_t *bdaddr)
 
 static int mgmt_read_local_oob_data (int index)
 {
+	struct mgmt_hdr hdr;
+
 	DBG("hci%d", index);
 
-	return -ENOSYS;
+	hdr.opcode = htobs(MGMT_OP_READ_LOCAL_OOB_DATA);
+	hdr.len = 0;
+	hdr.index = htobs(index);
+
+	if (write(mgmt_sock, &hdr, sizeof(hdr)) < 0)
+		return -errno;
+
+	return 0;
 }
 
 static int mgmt_add_remote_oob_data (int index, bdaddr_t *bdaddr,
 					uint8_t *hash, uint8_t *randomizer)
 {
+	char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_add_remote_oob_data)];
+	struct mgmt_hdr *hdr = (void *) buf;
+	struct mgmt_cp_add_remote_oob_data *cp = (void *) &buf[sizeof(*hdr)];
 	char addr[18];
 
 	ba2str(bdaddr, addr);
 	DBG("hci%d bdaddr %s", index, addr);
 
-	return -ENOSYS;
+	memset(buf, 0, sizeof(buf));
+
+	hdr->opcode = htobs(MGMT_OP_ADD_REMOTE_OOB_DATA);
+	hdr->index = htobs(index);
+	hdr->len = htobs(sizeof(*cp));
+
+	bacpy(&cp->bdaddr, bdaddr);
+	memcpy(cp->hash, hash, 16);
+	memcpy(cp->randomizer, randomizer, 16);
+
+	if (write(mgmt_sock, &buf, sizeof(buf)) < 0)
+		return -errno;
+
+	return 0;
 }
 
 static int mgmt_remove_remote_oob_data (int index, bdaddr_t *bdaddr)
 {
+	char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_remove_remote_oob_data)];
+	struct mgmt_hdr *hdr = (void *) buf;
+	struct mgmt_cp_remove_remote_oob_data *cp = (void *) &buf[sizeof(*hdr)];
 	char addr[18];
 
 	ba2str(bdaddr, addr);
 	DBG("hci%d bdaddr %s", index, addr);
 
-	return -ENOSYS;
+	memset(buf, 0, sizeof(buf));
+
+	hdr->opcode = htobs(MGMT_OP_REMOVE_REMOTE_OOB_DATA);
+	hdr->index = htobs(index);
+	hdr->len = htobs(sizeof(*cp));
+
+	bacpy(&cp->bdaddr, bdaddr);
+
+	if (write(mgmt_sock, &buf, sizeof(buf)) < 0)
+		return -errno;
+
+	return 0;
 }
 
 static struct btd_adapter_ops mgmt_ops = {
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH v5 3/6] Add support for Out of Band (OOB) association model in hciops
From: Szymon Janc @ 2011-03-04 15:08 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: par-gunnar.p.hjalmdahl, henrik.possung, Szymon Janc
In-Reply-To: <1299251315-2041-1-git-send-email-szymon.janc@tieto.com>

---
 plugins/hciops.c |  118 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 110 insertions(+), 8 deletions(-)

diff --git a/plugins/hciops.c b/plugins/hciops.c
index 74ff7d5..9013694 100644
--- a/plugins/hciops.c
+++ b/plugins/hciops.c
@@ -50,6 +50,7 @@
 #include "storage.h"
 #include "event.h"
 #include "manager.h"
+#include "oob.h"
 
 static int child_pipe[2] = { -1, -1 };
 
@@ -77,11 +78,18 @@ struct bt_conn {
 	uint8_t loc_auth;
 	uint8_t rem_cap;
 	uint8_t rem_auth;
+	uint8_t rem_oob_data;
 	gboolean bonding_initiator;
 	gboolean secmode3;
 	GIOChannel *io; /* For raw L2CAP socket (bonding) */
 };
 
+struct oob_data {
+	bdaddr_t bdaddr;
+	uint8_t hash[16];
+	uint8_t randomizer[16];
+};
+
 static int max_dev = -1;
 static struct dev_info {
 	int id;
@@ -120,6 +128,8 @@ static struct dev_info {
 	GSList *keys;
 	uint8_t pin_length;
 
+	GSList *oob_data;
+
 	GSList *uuids;
 
 	GSList *connections;
@@ -1053,14 +1063,43 @@ static void user_passkey_notify(int index, void *ptr)
 						btohl(req->passkey));
 }
 
-static void remote_oob_data_request(int index, void *ptr)
+static gint oob_bdaddr_cmp(gconstpointer a, gconstpointer b)
+{
+	const struct oob_data *data = a;
+	const bdaddr_t *bdaddr = b;
+
+	return bacmp(&data->bdaddr, bdaddr);
+}
+
+static void remote_oob_data_request(int index, bdaddr_t *bdaddr)
 {
 	struct dev_info *dev = &devs[index];
+	GSList *match;
 
 	DBG("hci%d", index);
 
-	hci_send_cmd(dev->sk, OGF_LINK_CTL,
-				OCF_REMOTE_OOB_DATA_NEG_REPLY, 6, ptr);
+	match = g_slist_find_custom(dev->oob_data, bdaddr, oob_bdaddr_cmp);
+
+	if (match) {
+		struct oob_data *data;
+		remote_oob_data_reply_cp cp;
+
+		data = match->data;
+
+		bacpy(&cp.bdaddr, &data->bdaddr);
+		memcpy(cp.hash, data->hash, sizeof(cp.hash));
+		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
+
+		dev->oob_data = g_slist_delete_link(dev->oob_data, match);
+
+		hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_REMOTE_OOB_DATA_REPLY,
+				REMOTE_OOB_DATA_REPLY_CP_SIZE, &cp);
+
+	} else {
+		hci_send_cmd(dev->sk, OGF_LINK_CTL,
+				OCF_REMOTE_OOB_DATA_NEG_REPLY, 6, bdaddr);
+	}
+
 }
 
 static int get_io_cap(int index, bdaddr_t *bdaddr, uint8_t *cap, uint8_t *auth)
@@ -1158,11 +1197,23 @@ static void io_capa_request(int index, void *ptr)
 					IO_CAPABILITY_NEG_REPLY_CP_SIZE, &cp);
 	} else {
 		io_capability_reply_cp cp;
+		struct bt_conn *conn;
+		GSList *match;
+
 		memset(&cp, 0, sizeof(cp));
 		bacpy(&cp.bdaddr, dba);
 		cp.capability = cap;
-		cp.oob_data = 0x00;
 		cp.authentication = auth;
+
+		conn = find_connection(dev, dba);
+		match = g_slist_find_custom(dev->oob_data, dba, oob_bdaddr_cmp);
+
+		if ((conn->bonding_initiator || conn->rem_oob_data == 0x01) &&
+				match)
+			cp.oob_data = 0x01;
+		else
+			cp.oob_data = 0x00;
+
 		hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_IO_CAPABILITY_REPLY,
 					IO_CAPABILITY_REPLY_CP_SIZE, &cp);
 	}
@@ -1182,6 +1233,7 @@ static void io_capa_response(int index, void *ptr)
 	if (conn) {
 		conn->rem_cap = evt->capability;
 		conn->rem_auth = evt->authentication;
+		conn->rem_oob_data = evt->oob_data;
 	}
 }
 
@@ -1788,6 +1840,20 @@ static void write_class_complete(int index, uint8_t status)
 		write_class(index, dev->wanted_cod);
 }
 
+static void read_local_oob_data_complete(int index, uint8_t status,
+						read_local_oob_data_rp *rp)
+{
+	struct btd_adapter *adapter = manager_find_adapter_by_id(index);
+
+	if (!adapter)
+		return;
+
+	if (status)
+		oob_local_data_read(adapter, NULL, NULL);
+	else
+		oob_local_data_read(adapter, rp->hash, rp->randomizer);
+}
+
 static inline void cmd_complete(int index, void *ptr)
 {
 	struct dev_info *dev = &devs[index];
@@ -1861,6 +1927,10 @@ static inline void cmd_complete(int index, void *ptr)
 		ptr += sizeof(evt_cmd_complete);
 		read_tx_power_complete(index, ptr);
 		break;
+	case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_LOCAL_OOB_DATA):
+		ptr += sizeof(evt_cmd_complete);
+		read_local_oob_data_complete(index, status, ptr);
+		break;
 	};
 }
 
@@ -2390,7 +2460,7 @@ static gboolean io_security_event(GIOChannel *chan, GIOCondition cond,
 		break;
 
 	case EVT_REMOTE_OOB_DATA_REQUEST:
-		remote_oob_data_request(index, ptr);
+		remote_oob_data_request(index, (bdaddr_t *) ptr);
 		break;
 	}
 
@@ -3560,30 +3630,62 @@ static int hciops_cancel_bonding(int index, bdaddr_t *bdaddr)
 
 static int hciops_read_local_oob_data (int index)
 {
+	struct dev_info *dev = &devs[index];
+
 	DBG("hci%d", index);
 
-	return -ENOSYS;
+	if (hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_READ_LOCAL_OOB_DATA, 0, 0)
+									< 0)
+		return -errno;
+
+	return 0;
 }
 
 static int hciops_add_remote_oob_data (int index, bdaddr_t *bdaddr,
 					uint8_t *hash, uint8_t *randomizer)
 {
 	char addr[18];
+	struct dev_info *dev = &devs[index];
+	GSList *match;
+	struct oob_data *data;
 
 	ba2str(bdaddr, addr);
 	DBG("hci%d bdaddr %s", index, addr);
 
-	return -ENOSYS;
+	match = g_slist_find_custom(dev->oob_data, &bdaddr, oob_bdaddr_cmp);
+
+	if (match) {
+		data = match->data;
+	} else {
+		data = g_new(struct oob_data, 1);
+		bacpy(&data->bdaddr, bdaddr);
+		dev->oob_data = g_slist_prepend(dev->oob_data, data);
+	}
+
+	memcpy(data->hash, hash, sizeof(data->hash));
+	memcpy(data->randomizer, randomizer, sizeof(data->randomizer));
+
+	return 0;
 }
 
 static int hciops_remove_remote_oob_data (int index, bdaddr_t *bdaddr)
 {
 	char addr[18];
+	struct dev_info *dev = &devs[index];
+	GSList *match;
 
 	ba2str(bdaddr, addr);
 	DBG("hci%d bdaddr %s", index, addr);
 
-	return -ENOSYS;
+	match = g_slist_find_custom(dev->oob_data, &bdaddr, oob_bdaddr_cmp);
+
+	if (!match)
+		return -ENOENT;
+
+	g_free(match->data);
+	dev->oob_data = g_slist_delete_link(dev->oob_data, match);
+
+	return 0;
 }
 
 static struct btd_adapter_ops hci_ops = {
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH v5 4/6] Add D-Bus OOB plugin
From: Szymon Janc @ 2011-03-04 15:08 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: par-gunnar.p.hjalmdahl, henrik.possung, Szymon Janc
In-Reply-To: <1299251315-2041-1-git-send-email-szymon.janc@tieto.com>

A sample OOB plugin that directly exposes OOB functionality over D-Bus.
---
 Makefile.am       |    5 +
 acinclude.m4      |    6 ++
 plugins/dbusoob.c |  241 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 252 insertions(+), 0 deletions(-)
 create mode 100644 plugins/dbusoob.c

diff --git a/Makefile.am b/Makefile.am
index 573673e..aa7cdbe 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -223,6 +223,11 @@ builtin_modules += maemo6
 builtin_sources += plugins/maemo6.c
 endif
 
+if DBUSOOBPLUGIN
+builtin_modules += dbusoob
+builtin_sources += plugins/dbusoob.c
+endif
+
 sbin_PROGRAMS += src/bluetoothd
 
 src_bluetoothd_SOURCES = $(gdbus_sources) $(builtin_sources) \
diff --git a/acinclude.m4 b/acinclude.m4
index 6aaa885..e96b5cf 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -204,6 +204,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 	configfiles_enable=yes
 	telephony_driver=dummy
 	maemo6_enable=no
+	dbusoob_enable=no
 
 	AC_ARG_ENABLE(optimization, AC_HELP_STRING([--disable-optimization], [disable code optimization]), [
 		optimization_enable=${enableval}
@@ -327,6 +328,10 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 		maemo6_enable=${enableval}
 	])
 
+	AC_ARG_ENABLE(dbusoob, AC_HELP_STRING([--enable-dbusoob], [compile with D-Bus OOB plugin]), [
+		dbusoob_enable=${enableval}
+	])
+
 	AC_ARG_ENABLE(hal, AC_HELP_STRING([--enable-hal], [Use HAL to determine adapter class]), [
 		hal_enable=${enableval}
 	])
@@ -384,4 +389,5 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 	AM_CONDITIONAL(UDEVRULES, test "${udevrules_enable}" = "yes")
 	AM_CONDITIONAL(CONFIGFILES, test "${configfiles_enable}" = "yes")
 	AM_CONDITIONAL(MAEMO6PLUGIN, test "${maemo6_enable}" = "yes")
+	AM_CONDITIONAL(DBUSOOBPLUGIN, test "${dbusoob_enable}" = "yes")
 ])
diff --git a/plugins/dbusoob.c b/plugins/dbusoob.c
new file mode 100644
index 0000000..8b7edc6
--- /dev/null
+++ b/plugins/dbusoob.c
@@ -0,0 +1,241 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2011  ST-Ericsson SA
+ *
+ *  Author: Szymon Janc <szymon.janc@tieto.com> for ST-Ericsson
+ *
+ *
+ *  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 <errno.h>
+#include <gdbus.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/sdp.h>
+
+#include "plugin.h"
+#include "log.h"
+#include "adapter.h"
+#include "device.h"
+#include "manager.h"
+#include "dbus-common.h"
+#include "event.h"
+#include "error.h"
+#include "oob.h"
+
+#define REQUEST_TIMEOUT		(60 * 1000)	/* 60 seconds */
+#define OOB_INTERFACE	"org.bluez.Oob"
+
+struct oob_request {
+	struct btd_adapter *adapter;
+	DBusMessage *msg;
+};
+
+static GSList *oob_requests = NULL;
+static DBusConnection *connection = NULL;
+
+static gint oob_request_cmp(gconstpointer a, gconstpointer b)
+{
+	const struct oob_request *data = a;
+	const struct btd_adapter *adapter = b;
+
+	return data->adapter != adapter;
+}
+
+static struct oob_request* find_oob_request(struct btd_adapter *adapter)
+{
+	GSList *match;
+
+	match = g_slist_find_custom(oob_requests, adapter, oob_request_cmp);
+
+	if (match)
+		return match->data;
+
+	return NULL;
+}
+
+static void local_data_read(struct btd_adapter *adapter, uint8_t *hash,
+				uint8_t *randomizer)
+{
+	struct DBusMessage *reply;
+	struct oob_request *oob_request;
+
+	oob_request = find_oob_request(adapter);
+	if (!oob_request)
+		return;
+
+	if (hash && randomizer)
+		reply = g_dbus_create_reply(oob_request->msg,
+			DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &hash, 16,
+			DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &randomizer, 16,
+			DBUS_TYPE_INVALID);
+	else
+		reply = btd_error_failed(oob_request->msg,
+					"Failed to read local OOB data.");
+
+	oob_requests = g_slist_remove(oob_requests, oob_request);
+	dbus_message_unref(oob_request->msg);
+	g_free(oob_request);
+
+	if (!reply) {
+		error("Couldn't allocate D-Bus message");
+		return;
+	}
+
+	if (!g_dbus_send_message(connection, reply))
+		error("D-Bus send failed");
+}
+
+static DBusMessage *read_local_data(DBusConnection *conn, DBusMessage *msg,
+								void *data)
+{
+	struct btd_adapter *adapter = data;
+	struct oob_request *oob_request;
+
+	if (find_oob_request(adapter))
+		return btd_error_in_progress(msg);
+
+	if (btd_adapter_read_local_oob_data(adapter))
+		return btd_error_failed(msg, "Request failed.");
+
+	oob_request = g_new(struct oob_request, 1);
+	oob_request->adapter = adapter;
+	oob_requests = g_slist_append(oob_requests, oob_request);
+	oob_request->msg = dbus_message_ref(msg);
+	return NULL;
+}
+
+static DBusMessage *add_remote_data(DBusConnection *conn, DBusMessage *msg,
+								void *data)
+{
+	struct btd_adapter *adapter = data;
+	uint8_t *hash, *randomizer;
+	int32_t hlen, rlen;
+	const char *addr;
+	bdaddr_t bdaddr;
+
+	if (!dbus_message_get_args(msg, NULL,
+			DBUS_TYPE_STRING, &addr,
+			DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &hash, &hlen,
+			DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &randomizer, &rlen,
+			DBUS_TYPE_INVALID))
+		return btd_error_invalid_args(msg);
+
+	if (hlen != 16 || rlen != 16 || bachk(addr))
+		return btd_error_invalid_args(msg);
+
+	str2ba(addr, &bdaddr);
+
+	if (btd_adapter_add_remote_oob_data(adapter, &bdaddr, hash, randomizer))
+		return btd_error_failed(msg, "Request failed");
+
+	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+static DBusMessage *remove_remote_data(DBusConnection *conn, DBusMessage *msg,
+								void *data)
+{
+	struct btd_adapter *adapter = data;
+	const char *addr;
+	bdaddr_t bdaddr;
+
+	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &addr,
+			DBUS_TYPE_INVALID))
+		return btd_error_invalid_args(msg);
+
+	if (bachk(addr))
+		return btd_error_invalid_args(msg);
+
+	str2ba(addr, &bdaddr);
+
+	if (btd_adapter_remove_remote_oob_data(adapter, &bdaddr))
+		return btd_error_failed(msg, "Request failed");
+
+	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+static GDBusMethodTable oob_methods[] = {
+	{"AddRemoteOobData",	"sayay", "",	 add_remote_data},
+	{"RemoveRemoteOobData",	"s",	 "",	 remove_remote_data},
+	{"ReadLocalOobData",	"",	 "ayay", read_local_data,
+						 G_DBUS_METHOD_FLAG_ASYNC},
+	{ }
+};
+
+static int oob_probe(struct btd_adapter *adapter)
+{
+	const char* path = adapter_get_path(adapter);
+
+	if (!g_dbus_register_interface(connection, path, OOB_INTERFACE,
+				oob_methods, NULL, NULL, adapter, NULL)) {
+			error("OOB interface init failed on path %s", path);
+			return -EIO;
+		}
+
+	return 0;
+}
+
+static void oob_remove(struct btd_adapter *adapter)
+{
+	local_data_read(adapter, NULL, NULL);
+
+	g_dbus_unregister_interface(connection, adapter_get_path(adapter),
+							OOB_INTERFACE);
+}
+
+
+static struct btd_adapter_driver oob_driver = {
+	.name	= "oob",
+	.probe	= oob_probe,
+	.remove	= oob_remove,
+};
+
+static int dbusoob_init(void)
+{
+	DBG("Setup dbusoob plugin");
+
+	connection = get_dbus_connection();
+
+	oob_register_cb(local_data_read);
+
+	return btd_register_adapter_driver(&oob_driver);
+}
+
+static void dbusoob_exit(void)
+{
+	struct oob_request *oob_request;
+	GSList *match;
+
+	DBG("Cleanup dbusoob plugin");
+
+	while ((match = g_slist_next(oob_requests))) {
+		oob_request = match->data;
+		oob_remove(oob_request->adapter);
+	}
+
+	btd_unregister_adapter_driver(&oob_driver);
+}
+
+BLUETOOTH_PLUGIN_DEFINE(dbusoob, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+						dbusoob_init, dbusoob_exit)
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH v5 5/6] Update mgmt-api.txt with OOB commands
From: Szymon Janc @ 2011-03-04 15:08 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: par-gunnar.p.hjalmdahl, henrik.possung, Szymon Janc
In-Reply-To: <1299251315-2041-1-git-send-email-szymon.janc@tieto.com>

---
 doc/mgmt-api.txt |   30 ++++++++++++++++++++++++++++++
 1 files changed, 30 insertions(+), 0 deletions(-)

diff --git a/doc/mgmt-api.txt b/doc/mgmt-api.txt
index 8e0e83b..34fdd1e 100644
--- a/doc/mgmt-api.txt
+++ b/doc/mgmt-api.txt
@@ -266,6 +266,36 @@ User Confirmation Negative Reply Command
 				Status (1 Octet)
 
 
+Read Local Out Of Band Data Command
+========================================
+
+	Command Code:		0x0017
+	Controller Index:	<controller id>
+	Command Parameters:
+	Return Paramters:	Hash (16 Octets)
+				Randomizer (16 Octets)
+
+
+Add Remote Out Of Band Data Command
+========================================
+
+	Command Code:		0x0018
+	Controller Index:	<controller id>
+	Command Parameters:	Address (6 Octets)
+				Hash (16 Octets)
+				Randomizer (16 Octets)
+	Return Paramters:
+
+
+Remove Remote Out Of Band Data Command
+========================================
+
+	Command Code:		0x0019
+	Controller Index:	<controller id>
+	Command Parameters:	Address (6 Octets)
+	Return Paramters:
+
+
 Read Tracing Buffer Size Command
 ================================
 
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH v5 6/6] Add oob-api.txt with documentation about OOB D-Bus methods
From: Szymon Janc @ 2011-03-04 15:08 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: par-gunnar.p.hjalmdahl, henrik.possung, Szymon Janc
In-Reply-To: <1299251315-2041-1-git-send-email-szymon.janc@tieto.com>

---
 doc/oob-api.txt |   38 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 38 insertions(+), 0 deletions(-)
 create mode 100644 doc/oob-api.txt

diff --git a/doc/oob-api.txt b/doc/oob-api.txt
new file mode 100644
index 0000000..7fa09f7
--- /dev/null
+++ b/doc/oob-api.txt
@@ -0,0 +1,38 @@
+BlueZ D-Bus Out Of Band API description
+***********************************
+
+Copyright (C) 2011  Szymon Janc <szymon.janc@tieto.com> for ST-Ericsson
+
+Service		org.bluez
+Interface	org.bluez.Oob
+Object path	[variable prefix]/{hci0,hci1,...}
+
+Methods		array{byte} hash, array{byte} randomizer ReadLocalOobData()
+
+			This method reads local OOB data from adapter. Return
+			value is pair of arrays 16 bytes each.
+
+			Note: This method will generate and return new local
+			OOB data.
+
+			Possible errors: org.bluez.Error.Failed
+					 org.bluez.Error.InProgress
+
+		void AddRemoteOobData(string address, array{byte} hash,
+							array{byte} randomizer)
+
+			This method adds new Out Of Band data for specified
+			address. If data for specified address already exists it
+			will be overwritten with new one.
+
+			Possible errors: org.bluez.Error.Failed
+					 org.bluez.Error.InvalidArguments
+
+		void RemoveRemoteOobData(string address)
+
+			This method removes Out Of Band data for specified
+			address. If data for specified address does not exist
+			nothing is removed.
+
+			Possible errors: org.bluez.Error.Failed
+					 org.bluez.Error.InvalidArguments
-- 
1.7.0.4


^ permalink raw reply related

* Re: [PATCH] Bluetooth: Add counter for not acked HCI commands
From: Brian Gix @ 2011-03-04 16:12 UTC (permalink / raw)
  To: Andrzej Kaczmarek
  Cc: linux-bluetooth@vger.kernel.org,
	par-gunnar.p.hjalmdahl@stericsson.com,
	henrik.possung@stericsson.com
In-Reply-To: <4D70DD01.2030003@tieto.com>

Hi Andrzej,

On 3/4/2011 4:37 AM, Andrzej Kaczmarek wrote:
> Hi Brian,
>
> On 01.03.2011 20:25, Brian Gix wrote:
>> The problem you describe sounds like one I had to solve in the past, but
>> unfortunately, I think it may be a little more difficult to solve here.
>> This particular baseband appears to have an outstanding Cmd queue of
>> 2. It also appears to consume one of them for extended periods of time
>> when making requests of the remote device, and using the NOP
>> Cmd-Status-Event to inform the host that the slot is now free.
>>
>> As you are observing, the completion of the task (triggering additional
>> requests locally) overlaps with these NOP responses, giving a false
>> count to the host of available cmd slots.
>>
>> Personally, I consider this to be a baseband bug, which could have been
>> avoided by having a max outstanding queue of 1.
>
> This particular controller uses 1 credit for each command that is being
> processed and having max outstanding queue of 1 would make some
> scenarios impossible - consider authentication with
> HCI_Authentication_Request pending and other HCI command to be sent in
> parallel.
>

The adjustment I suggest doesn't disallow this.  I was having a 
theory-of-operation talk with a baseband guy once, and this is what he 
had to say:

The HCI interface is intended to be an interface that immediately 
responds to *every* command. The problem is that some commands are 
intended for the local baseband (and can be handled immediately) and 
others require interaction outside of the control of the local baseband, 
and take an indeterminate amount of time.

So two response mechanism were created:

Command    Immediate Rsp     Delayed Rsp
Cmd   -->  Cmd Complete Evt                (Cmds handled Locally)
Cmd   -->  Cmd Status Evt --> Cmplt Event  ("long" Async Cmds)

The HCI flow control is contained in both the Cmd-Complt-Evt and the 
Cmd-Status-Evt.

So it is assumed that both flow control response event types will be 
delivered immediately after the baseband receives them. Of course 
because of the communication link, these response are still asyncronous 
in most cases including the BlueZ case.

The baseband guy basically said that "the baseband" does not expect the 
next command until the host has processed the (immediate) response to 
the previous one. And that the (immediate) response to the previous one 
should be RXed in milliseconds at the most.

So I would always delay sending the next command until the prior 
commands CmdStatus or CmdCmplt has been received. This should work 
unless there is something seriously wrong with the baseband.


-- 
Brian Gix
bgix@codeaurora.org
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply

* [PATCH 1/5] Add new UUID utility functions
From: Elvis Pfützenreuter @ 2011-03-04 16:20 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: epx, Claudio Takahasi

From: Claudio Takahasi <claudio.takahasi@openbossa.org>

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 <marcel@holtmann.org>
+ *
+ *
+ *  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 <marcel@holtmann.org>
+ *
+ *
+ *  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


^ permalink raw reply related

* [PATCH 2/5] Add more functions for new UUID handling
From: Elvis Pfützenreuter @ 2011-03-04 16:20 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: epx
In-Reply-To: <1299255640-13599-1-git-send-email-epx@signove.com>

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


^ permalink raw reply related

* [PATCH 3/5] Add "unit test" for new UUID functions
From: Elvis Pfützenreuter @ 2011-03-04 16:20 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: epx
In-Reply-To: <1299255640-13599-1-git-send-email-epx@signove.com>

---
 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


^ permalink raw reply related

* [PATCH 4/5] Use new UUID functions in GATT
From: Elvis Pfützenreuter @ 2011-03-04 16:20 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: epx
In-Reply-To: <1299255640-13599-1-git-send-email-epx@signove.com>

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


^ permalink raw reply related

* [PATCH 5/5] Use new UUID functions in example GATT server
From: Elvis Pfützenreuter @ 2011-03-04 16:20 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: epx
In-Reply-To: <1299255640-13599-1-git-send-email-epx@signove.com>

---
 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


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox