You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@mynewt.apache.org by Andrzej Kaczmarek <an...@codecoup.pl> on 2017/01/26 14:41:53 UTC

[RFC] Using BLE device address in API

Hi,

I think it would be nice to do one more API refactoring before 1.0 release
and simplify using BLE device address in API.

The current state here is similar to what we had with UUIDs in ATT code,
i.e. addresses are passed as pair of address type and address value and
there is no common way to e.g. compare or copy them. What more, with
Privacy enabled things are even more complicated since application needs to
chose which address to use when advertising or scanning and can use
different addresses for the same peer device.

So I propose few changes:

1. Application does not specify own_addr_type in APIs
This should be selected automatically by host. By this I mean that
application tells host somehow at startup which address to use (public or
random static) and host will set parameters accordingly depending on
whether Privacy is enabled (IRK is provided) or disabled (no IRK provided).

2. Application should always use peer identity address, if possible
Since host manages resolving list in controller already, address resolving
will be done automatically anyway. We can then assume that for any known
device, the address we use in API is identity address (assuming our IRK is
provided and thus Privacy is enabled) and honestly it does not need to know
so-called OTA address, because this is what host and controller take care
of. The only exception here would be for new devices for which application
will have random (RPA) address at first, but as soon as we are paired host
should notify application about identity address of such device - for this
new event shall be added.

3. And finally, of course, we need nice type and helpers to store and
handle device address in uniform way:
typedef struct {
    uint8_t type; // 0 = public, 1 = random
    uint8_t address[6];
} ble_address_t;

This is what I have in mind now. It may some time to fix all the internals,
but before release we would just need external APIs redefined. Then we can
work more on optimizing the internals.

Open points:
- selecting own address type could be automatic, i.e. host reads public
address from controller, if not available tries to read static random from
storage, if not available generates new one and stores it
- the same for IRK, i.e. read from storage, if not available randomize new
one
This can be however added later and old APIs can be just marked as
deprecated.

Comments?

BR,
Andrzej

Re: [RFC] Using BLE device address in API

Posted by Andrzej Kaczmarek <an...@codecoup.pl>.
Hi,

I created pull request which contains patch that introduces ble_addr_t type
and makes public API use it:
https://github.com/apache/incubator-mynewt-core/pull/173

In most cases internals are not updated since this in some cases requires a
lot of additional work and can be done later.
Apart from this change, it includes also:
- cleanup usage of address types and own address types (they use the same
values, but have different meaning and in some places improper symbols were
used)
- fixed pairing with privacy enabled (so when we use RPA)
- added event which tells application that we received peer's identity
address (after pairing)

Also please find some comments below for further discussion.

BR,
Andrzej


On Thu, Jan 26, 2017 at 5:59 PM, Christopher Collins <cc...@apache.org>
wrote:

> Hi Andrzej,
>
> On Thu, Jan 26, 2017 at 03:41:53PM +0100, Andrzej Kaczmarek wrote:
> > Hi,
> >
> > I think it would be nice to do one more API refactoring before 1.0
> release
> > and simplify using BLE device address in API.
> >
> > The current state here is similar to what we had with UUIDs in ATT code,
> > i.e. addresses are passed as pair of address type and address value and
> > there is no common way to e.g. compare or copy them. What more, with
> > Privacy enabled things are even more complicated since application needs
> to
> > chose which address to use when advertising or scanning and can use
> > different addresses for the same peer device.
> >
> > So I propose few changes:
> >
> > 1. Application does not specify own_addr_type in APIs
> > This should be selected automatically by host. By this I mean that
> > application tells host somehow at startup which address to use (public or
> > random static) and host will set parameters accordingly depending on
> > whether Privacy is enabled (IRK is provided) or disabled (no IRK
> provided).
>
> I think I have the same concern as Will.  I was under the impression
> that a device can use different own_addr_type values for each
> connection.  I know this has been useful for some low level debugging in
> the past, and it would nice if the host could support it.
>

Well, it depends on what you want to do :-)
#1 For some hacking, having low level (in this case HCI-like) interface is
definitely useful.
#2 For developing an application I'd prefer not to think about address
types too much. I just say: here's my identity, do what needs to be done
when I scan/advertise/connect.

I think main API should be application-friendly. I am perfectly fine with
lower level APIs as an addition though.


> In Zephyr, does the application specify a single own_addr_type at
> startup?
>

I don't know how it works in details, but IIRC host reads information on
statup from controller (address) or storage (address, IRK) and
automatically selects what it should do. Basically, you could as well
define this in build-time which is not much different than setting this at
startup.

My understanding is that this could work as below:
- read public device address
- if not found, check if we have stored random static address and use it
- if not found, randomize new random static address
- use the above as our address
- if privacy is enabled, try to load stored IRK or generated new one
- depending on privacy settings use proper own_addr_type when initiating
actions


> > 2. Application should always use peer identity address, if possible
> > Since host manages resolving list in controller already, address
> resolving
> > will be done automatically anyway. We can then assume that for any known
> > device, the address we use in API is identity address (assuming our IRK
> is
> > provided and thus Privacy is enabled)
>
> This is already the case, isn't it?  As far as I know, whenever the host
> API accepts a peer address type / peer address pair, it is always the
> identity address.
>

In some cases this was not possible, see below :-)

> and honestly it does not need to know so-called OTA address, because
> > this is what host and controller take care of. The only exception here
> > would be for new devices for which application will have random (RPA)
> > address at first, but as soon as we are paired host should notify
> > application about identity address of such device - for this new event
> > shall be added.
>
> Currently, when a connection is established, the host tells the
> application two peer addresses:
>     * Identity address
>     * OTA address (we made up this term; I couldn't find a name for this
>       in the spec).
>

Yes and no.
Yes, because if connection is established with bonded device then
controller will indeed provide identity address and OTA address.
No, because in case other than above both "identity" address and OTA
address are the same (which makes sense).

The problem is that once you are paired and identity address information is
exchanged, application still does only know "identity"=OTA=RPA and the only
way to know peer's actual identity address is to... disconnect and then
reconnect.

This is why I added new event in my pull request so we can consider this
handled - I think peer_id_addr in conn_desc structure is the address that
application should use to identify device at any time. Perhaps the name is
not quite correct since this does not need to be identity address (could be
e.g. RPA as well).


> (To clarify, an "OTA address" is the private address a device was using
> when the connection was established.)
>
> Just so I understand, you are proposing hiding the OTA address from the
> application?  Maybe it's just me, but I have found knowing a peer's
> OTA address helpful in the past.  I agree that in most cases an
> application won't care about this address, but it seems a shame hide it
> completely.  In fact, my heart sinks just a little bit when I use
> bluetooth tools that insist on hiding addresses from me.
>

OTA address can still be retrieve-able via conn info API (as it is now), I
have no problem with this.


> I think a good goal for the host is to provide a low-level
> implementation of the spec.  Policy decisions and high-level interfaces
> can be implmented by the application and support libraries.  This is why
> I disliked our advertising data API: it forced a high-level interface on
> the user.  Hiding OTA addresses from the application makes me a little
> uneasy because it feels like an unnecessary policy decision.
>
> > 3. And finally, of course, we need nice type and helpers to store and
> > handle device address in uniform way:
> > typedef struct {
> >     uint8_t type; // 0 = public, 1 = random
> >     uint8_t address[6];
> > } ble_address_t;
>
> This seems totally reasonable.
>
> >
> > This is what I have in mind now. It may some time to fix all the
> internals,
> > but before release we would just need external APIs redefined. Then we
> can
> > work more on optimizing the internals.
> >
> > Open points:
> > - selecting own address type could be automatic, i.e. host reads public
> > address from controller, if not available tries to read static random
> from
> > storage, if not available generates new one and stores it
> > - the same for IRK, i.e. read from storage, if not available randomize
> new
> > one
> > This can be however added later and old APIs can be just marked as
> > deprecated.
> >
> > Comments?
>
> Thanks,
> Chris
>

Re: [RFC] Using BLE device address in API

Posted by Christopher Collins <cc...@apache.org>.
Hi Andrzej,

On Thu, Jan 26, 2017 at 03:41:53PM +0100, Andrzej Kaczmarek wrote:
> Hi,
> 
> I think it would be nice to do one more API refactoring before 1.0 release
> and simplify using BLE device address in API.
> 
> The current state here is similar to what we had with UUIDs in ATT code,
> i.e. addresses are passed as pair of address type and address value and
> there is no common way to e.g. compare or copy them. What more, with
> Privacy enabled things are even more complicated since application needs to
> chose which address to use when advertising or scanning and can use
> different addresses for the same peer device.
> 
> So I propose few changes:
> 
> 1. Application does not specify own_addr_type in APIs
> This should be selected automatically by host. By this I mean that
> application tells host somehow at startup which address to use (public or
> random static) and host will set parameters accordingly depending on
> whether Privacy is enabled (IRK is provided) or disabled (no IRK provided).

I think I have the same concern as Will.  I was under the impression
that a device can use different own_addr_type values for each
connection.  I know this has been useful for some low level debugging in
the past, and it would nice if the host could support it.

In Zephyr, does the application specify a single own_addr_type at
startup?

> 2. Application should always use peer identity address, if possible
> Since host manages resolving list in controller already, address resolving
> will be done automatically anyway. We can then assume that for any known
> device, the address we use in API is identity address (assuming our IRK is
> provided and thus Privacy is enabled)

This is already the case, isn't it?  As far as I know, whenever the host
API accepts a peer address type / peer address pair, it is always the
identity address.

> and honestly it does not need to know so-called OTA address, because
> this is what host and controller take care of. The only exception here
> would be for new devices for which application will have random (RPA)
> address at first, but as soon as we are paired host should notify
> application about identity address of such device - for this new event
> shall be added.

Currently, when a connection is established, the host tells the
application two peer addresses:
    * Identity address
    * OTA address (we made up this term; I couldn't find a name for this
      in the spec).

(To clarify, an "OTA address" is the private address a device was using
when the connection was established.)

Just so I understand, you are proposing hiding the OTA address from the
application?  Maybe it's just me, but I have found knowing a peer's
OTA address helpful in the past.  I agree that in most cases an
application won't care about this address, but it seems a shame hide it
completely.  In fact, my heart sinks just a little bit when I use
bluetooth tools that insist on hiding addresses from me.  

I think a good goal for the host is to provide a low-level
implementation of the spec.  Policy decisions and high-level interfaces
can be implmented by the application and support libraries.  This is why
I disliked our advertising data API: it forced a high-level interface on
the user.  Hiding OTA addresses from the application makes me a little
uneasy because it feels like an unnecessary policy decision.  

> 3. And finally, of course, we need nice type and helpers to store and
> handle device address in uniform way:
> typedef struct {
>     uint8_t type; // 0 = public, 1 = random
>     uint8_t address[6];
> } ble_address_t;

This seems totally reasonable.

> 
> This is what I have in mind now. It may some time to fix all the internals,
> but before release we would just need external APIs redefined. Then we can
> work more on optimizing the internals.
> 
> Open points:
> - selecting own address type could be automatic, i.e. host reads public
> address from controller, if not available tries to read static random from
> storage, if not available generates new one and stores it
> - the same for IRK, i.e. read from storage, if not available randomize new
> one
> This can be however added later and old APIs can be just marked as
> deprecated.
> 
> Comments?

Thanks,
Chris

Re: [RFC] Using BLE device address in API

Posted by will sanfilippo <wi...@runtime.io>.
I dont know enough about the host to comment on whether we should change this API now or after release.

I think adding an address structure is a good idea.

A question about one of your open points. The spec has confused me a bit in this regard. Isnt it up to the application to decide whether it wants to use a public device address or a random static address? A device can contain both, so how does one decide which one to use? I thought that was up to the app but maybe apps dont really care about this and we can leave it up to the host?


> On Jan 26, 2017, at 6:41 AM, Andrzej Kaczmarek <an...@codecoup.pl> wrote:
> 
> Hi,
> 
> I think it would be nice to do one more API refactoring before 1.0 release
> and simplify using BLE device address in API.
> 
> The current state here is similar to what we had with UUIDs in ATT code,
> i.e. addresses are passed as pair of address type and address value and
> there is no common way to e.g. compare or copy them. What more, with
> Privacy enabled things are even more complicated since application needs to
> chose which address to use when advertising or scanning and can use
> different addresses for the same peer device.
> 
> So I propose few changes:
> 
> 1. Application does not specify own_addr_type in APIs
> This should be selected automatically by host. By this I mean that
> application tells host somehow at startup which address to use (public or
> random static) and host will set parameters accordingly depending on
> whether Privacy is enabled (IRK is provided) or disabled (no IRK provided).
> 
> 2. Application should always use peer identity address, if possible
> Since host manages resolving list in controller already, address resolving
> will be done automatically anyway. We can then assume that for any known
> device, the address we use in API is identity address (assuming our IRK is
> provided and thus Privacy is enabled) and honestly it does not need to know
> so-called OTA address, because this is what host and controller take care
> of. The only exception here would be for new devices for which application
> will have random (RPA) address at first, but as soon as we are paired host
> should notify application about identity address of such device - for this
> new event shall be added.
> 
> 3. And finally, of course, we need nice type and helpers to store and
> handle device address in uniform way:
> typedef struct {
>    uint8_t type; // 0 = public, 1 = random
>    uint8_t address[6];
> } ble_address_t;
> 
> This is what I have in mind now. It may some time to fix all the internals,
> but before release we would just need external APIs redefined. Then we can
> work more on optimizing the internals.
> 
> Open points:
> - selecting own address type could be automatic, i.e. host reads public
> address from controller, if not available tries to read static random from
> storage, if not available generates new one and stores it
> - the same for IRK, i.e. read from storage, if not available randomize new
> one
> This can be however added later and old APIs can be just marked as
> deprecated.
> 
> Comments?
> 
> BR,
> Andrzej