Skip to content

net: add Skald, a BLE advertising stack#8884

Merged
miri64 merged 10 commits intoRIOT-OS:masterfrom
haukepetersen:add_skald
Apr 6, 2018
Merged

net: add Skald, a BLE advertising stack#8884
miri64 merged 10 commits intoRIOT-OS:masterfrom
haukepetersen:add_skald

Conversation

@haukepetersen
Copy link
Copy Markdown
Contributor

Contribution description

This PR adds Skald to RIOT, a BLE advertising stack written from scratch. Skald is focused on the BLE broadcaster role only, but for this he is extremely small, allowing for very memory efficient implementation of all kind of BLE beacons (e.g. a iBeacon takes ~5k ROM with everything).

Currently, Skald supports Apple's iBeacons, Google's Eddystone beacons, and sending out custom GAP payloads.

This PR also contains a netdev tailoring for using BLE radios, as well as a BLE radio driver implementation for the nrf5x family of devices.

Note: currently only the nrf52dk is supported (and tested), other platforms will be added step-by-step

Testing

  1. flash the included iBeacon or the Eddystone example on a nrf52dk
  2. use any iOS or Android app that can scan for BLE devices to verify the beacon, e.g. Nordic's nRF Connect App (for Android or iOS). Alternatively you can use a Bluetooth 4.0 capable Linux and use Bluez hcitools... Or something else...

Issues/PRs references

Skald is a spin-off of my current BLE implementation efforts, a full BLE stack will follow soon...

@haukepetersen haukepetersen added Area: network Area: Networking Type: new feature The issue requests / The PR implemements a new feature for RIOT CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Area: BLE Area: Bluetooth Low Energy support labels Apr 5, 2018
Copy link
Copy Markdown
Member

@miri64 miri64 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First iteration of review.

*
* @note This driver is not thread safe (as of now)
*

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Newline ;-)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check

* @note This driver is not thread safe (as of now)
*

* @todo add support for netdev_ble_pkt_ext_t
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that this will show up in the documentation, maybe some more detailed elaboration on what this means would be great.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its outdated, removed.

/**
* @brief Reference to the netdev driver interface
*/
extern const netdev_driver_t nrfble_netdev;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this actually need to be exposed? This is set by nrfble_setup() inside _nrfble_dev, and used nowhere else. Also, the name is confusing. How about nrfble_driver (even when you internalize it)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will remove.

/**
* @brief Export the netdev device descriptor
*/
extern netdev_t nrfble_dev;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't have a corresponding internal definition. Also is this required to be public? nrfble_setup() returns a pointer to _nrfble_dev (which I assume to be the fragment this used to expose earlier (?))

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

@@ -0,0 +1,357 @@
/*
* Copyright (C) 2017 Freie Universität Berlin
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2018

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nope, 2017-2018 :-)

*
* # About
* This Skald module supports the creation and advertisement of BLE iBeacons as
* defined by Apple (see https://developer.apple.com/ibeacon/).
Copy link
Copy Markdown
Member

@miri64 miri64 Apr 5, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same proposal here:

This Skald module supports the creation and advertisement of BLE [iBeacons](https://developer.apple.com/ibeacon/) as defined by Apple.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I like the visibly printed link better, so I will leave it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NACK

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the NACK was superfluous, github interface didn't show my first comment....

/* advertise on the next adv channel - or skip this event if the radio is
* busy */
if (_radio->context != NULL) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there something missing here? Otherwise: the if is redundant.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

debugging leftover, removed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

{
assert(buf);

luid_get(buf, BLE_ADDR_LEN);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK, BLE addresses are MAC addresses as defined in IEEE 802. Please at least set the universal/local bit to local and the individual/group bit to individual after calling this:

    buf[0] &= 0x01;
    buf[0] |= 0x02;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

*
* @param[out] buf the generated address is written to this buffer
*/
void skald_generate_random_addr(uint8_t *buf);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

random might not be a good term here, since the result of get_luid() is not random, but pretty predeterminable.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but the bluetooth standard calls this type of address random.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, okay.

pre_t pre;
uint8_t tx_pwr;
uint8_t scheme;
uint8_t url;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The URL is only one byte long? oO

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, but this field is only used for its address.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe use url[] instead then to make this clearer. (additional benefit, you don't need the address operator & to get the pointer ;-)).

Copy link
Copy Markdown
Member

@miri64 miri64 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some more doc stuff I noticed when browsing through the rendered doc.

*/

/**
* @defgroup drivers_nrf5x_nrfble nRF BLE radio driver
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For other nRF drivers "NRF" (all upper case) was used was used in the group name. It took me a moment to find it ;-)

image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

uint32_t u32; /**< compact access */
} aa; /**< access address */
uint32_t crc; /**< CRC: 3 LSB for CRC, most
* significant bit for RX state*/
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe use a top comment for that and while doing so, you can make a graphic (but don't have to):

/**
 * @brief CRC and RX state
 * 
 * 3 LSB for CRC, most significant bit for RX state (R, marks if the CRC is
 * correct):
 *
 *         3                   2                   1                   0
 *     2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
 *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *     |R|   reserved  |                      CRC                      |
 *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 */

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overkill

*/

/**
* @defgroup net_ble General BLE defines
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think "Bluetooth Low Energy (BLE)" is easier to find in the list of modules. At least I wouldn't search under "G" for the Bluetooth definitions ;-)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't use the word 'bluetooth' anywhere on purpose, as I am not clear on the copyright/usage rights on that word and I have the dimm memory that there was trouble for others in the past using that word without the ok of the bluetooth SIG

#endif

/**
* @name BT version constants
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bluetooth

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mainly, because just BT in a heading looks weird IMHO:

image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see above

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

*/

/**
* @defgroup net_eddystone Eddystone Constants
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Drop the "Constants" for the group name.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check

* @name URL scheme prefix values
* @{
*/
#define EDDYSTONE_URL_HTTP_WWW (0x00) /**< http://www.URL */
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use ` around these URLs here and below:

/**< `http://www.URL` */

Doxygen interprets these as valid URLs (which leads to nowhere of course) with the current usage.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check

* @brief Generate a random public address
*
* @todo Make sure resulting address does not conflict with and assigned
* vendor prefix (however we will do that..)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is guaranteed, when you set the universal/local bit to local ;-).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

*/

/**
* @defgroup net_skald_ Skald meets Eddy
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

net_scald_eddystone?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

*/

/**
* @defgroup net_skald_ Skald meets Eddy
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Skald meets Eddystone"?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(but maybe I missed the joke here ;-))

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes.

@miri64
Copy link
Copy Markdown
Member

miri64 commented Apr 5, 2018

Noticed during testing: README (can be an adjusted copy of what you wrote in OP IMHO) for the examples is missing.

@aabadie
Copy link
Copy Markdown
Contributor

aabadie commented Apr 5, 2018

General comment (sorry): I am very happy with this BLE initiative but I don't like the skald name. It think that it doesn't means anything regarding ble. Why not simply using ble_advertising ? The name is longer but way more explicit.

Actually, we have the same problem with emcute, IMHO it should have been called mqtt-sn to be explicit.

If those 2 projects (skald and emcute) were external libraries imported as packages, it would have been perfectly fine but since they are designed as implementation of standard protocols within RIOT (and with respect to highly constrained devices), they should use the standard names.

@haukepetersen
Copy link
Copy Markdown
Contributor Author

I completely disagree regarding the name(s)! Naming an implementation after the protocol it implements is IMHO not a good idea - especially in the field of contrained devices where there is a tendency to have multiple implementations with different scopes!

And who says that Skald (or also emcute) is the default/standard implementation in RIOT for BLE advertising (or mqtt-sn, respectively)? They are simply the only ones we have currently...

And in the end I am the author, and I insist on this name :-)

@aabadie
Copy link
Copy Markdown
Contributor

aabadie commented Apr 5, 2018

Naming an implementation after the protocol it implements is IMHO not a good idea - especially in the field of contrained devices where there is a tendency to have multiple implementations with different scopes!

Then they should be provided as external libraries. Implementation contributed into RIOT should use standard names and try to implement in a standard (whatever this means).

They are simply the only ones we have currently...

Indeed, but the problem is that they hide the underlying features instead of advertising them. I think I already said to someone asking if RIOT has support for MQTT that the example application was called emcute. Reply: "Ah ok, I missed it"

@miri64
Copy link
Copy Markdown
Member

miri64 commented Apr 5, 2018

Tested on nrf52dk with an android app as partner. Works.

@miri64
Copy link
Copy Markdown
Member

miri64 commented Apr 5, 2018

Indeed, but the problem is that they hide the underlying features instead of advertising them. I think I already said to someone asking if RIOT has support for MQTT that the example application was called emcute. Reply: "Ah ok, I missed it"

I think this is more a matter of documentation than of naming.

@haukepetersen
Copy link
Copy Markdown
Contributor Author

But why is GNRC called GNRC instead of ip_stack?

@haukepetersen
Copy link
Copy Markdown
Contributor Author

@miri64 are you sufficiently happy with the doc now? I know its not perfect (yet), but considering this being a completely new feature (with a high probability of significant structural changes), I tend to rather let this module settle a bit before detailing out the doc to a 'perfect' state...

@haukepetersen
Copy link
Copy Markdown
Contributor Author

I think this is more a matter of documentation than of naming.

+1

Copy link
Copy Markdown
Member

@miri64 miri64 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One minor thing left that I think can be improved code-wise (see last comment in this review). Otherwise, I think you can squash.

uint8_t flags; /**< header flags */
uint8_t len; /**< actual length of PDU */
uint8_t pdu[NETDEV_BLE_PDU_MAXLEN]; /**< protocol data unit (PDU) */
} netdev_ble_pkt_t;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine then let's keep it here for now. But when we finalize this API, I think it would still be better to move it somewhere else.

uint32_t crc; /**< CRC: 3 LSB for CRC, most
* significant bit for RX state*/
uint8_t chan; /**< channel to use/used */
} netdev_ble_ctx_t;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

#endif

/**
* @name BT version constants
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

*
* @param[out] buf the generated address is written to this buffer
*/
void skald_generate_random_addr(uint8_t *buf);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, okay.

pre_t pre;
uint8_t tx_pwr;
uint8_t scheme;
uint8_t url;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe use url[] instead then to make this clearer. (additional benefit, you don't need the address operator & to get the pointer ;-)).

@aabadie
Copy link
Copy Markdown
Contributor

aabadie commented Apr 5, 2018

I think this is more a matter of documentation than of naming.

Just give the application a meaningful name, e.g. mqtt-sn, ble-eddystone, ble-ibeacon and everything will be fine.

Personally (and I'm sure I'm not the only one), I will be very difficult to convince with the name skald. This name inspires nothing related to ble, even uble would have been better. I also understand that changing the name you chose for your implementation will probably be even more difficult.

@haukepetersen
Copy link
Copy Markdown
Contributor Author

even uble would have been better.

Very subjective...

I guess we agree to not agree on the naming thing, but as the original author I think I have the right to chose a name to my liking :-)

@haukepetersen
Copy link
Copy Markdown
Contributor Author

@miri64 for some reason I don't seem to be allowed to comment on your last review comments...

Maybe use url[] instead then to make this clearer. (additional benefit, you don't need the address operator & to get the pointer ;-)).

fixed.

Copy link
Copy Markdown
Member

@miri64 miri64 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please squash.

@haukepetersen
Copy link
Copy Markdown
Contributor Author

my pleasure :-)

Copy link
Copy Markdown
Member

@miri64 miri64 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK

@miri64
Copy link
Copy Markdown
Member

miri64 commented Apr 6, 2018

Ah, the netopt module needs a new string in its array btw ;-).

Skald is a very small and simple, TX-only BLE stack that supports
sending advertisements only. It is useful for building all kinds
of BLE beacons with very minimal memory footprints.
@haukepetersen
Copy link
Copy Markdown
Contributor Author

Ah, the netopt module needs a new string in its array btw ;-).

fixed and squashed right in

@miri64
Copy link
Copy Markdown
Member

miri64 commented Apr 6, 2018

And go.

@miri64 miri64 merged commit a19cb84 into RIOT-OS:master Apr 6, 2018
@miri64 miri64 deleted the add_skald branch April 6, 2018 09:26
@miri64 miri64 restored the add_skald branch April 6, 2018 09:27
@haukepetersen
Copy link
Copy Markdown
Contributor Author

Thanks for the quick review! This makes is much easier to continue the actual BLE work :-)

@haukepetersen haukepetersen deleted the add_skald branch April 6, 2018 09:31
miri64 added a commit to miri64/RIOT that referenced this pull request Apr 6, 2018
Documentation of the option types was clarified in RIOT-OS#8655. I only noticed
after merging RIOT-OS#8884, that `NETOPT_BLE_CTX` was not documented using
that new style. So I deliver the change myself to make it quicker.
*/
NETOPT_TX_RETRIES_NEEDED,

NETOPT_BLE_CTX, /**< set radio context (channel, CRC, AA) */
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arghs, this doesn't uphold the new doc style for netopts introduced in #8655. Fix provided in #8892.

@emmanuelsearch
Copy link
Copy Markdown
Member

awesome ;)

miri64 added a commit to miri64/RIOT that referenced this pull request Apr 6, 2018
jcarrano pushed a commit to jcarrano/RIOT that referenced this pull request May 7, 2018
Documentation of the option types was clarified in RIOT-OS#8655. I only noticed
after merging RIOT-OS#8884, that `NETOPT_BLE_CTX` was not documented using
that new style. So I deliver the change myself to make it quicker.
jcarrano pushed a commit to jcarrano/RIOT that referenced this pull request May 9, 2018
Documentation of the option types was clarified in RIOT-OS#8655. I only noticed
after merging RIOT-OS#8884, that `NETOPT_BLE_CTX` was not documented using
that new style. So I deliver the change myself to make it quicker.
jia200x pushed a commit to jia200x/RIOT that referenced this pull request Jun 11, 2018
Documentation of the option types was clarified in RIOT-OS#8655. I only noticed
after merging RIOT-OS#8884, that `NETOPT_BLE_CTX` was not documented using
that new style. So I deliver the change myself to make it quicker.
panail pushed a commit to panail/RIOT that referenced this pull request Oct 29, 2018
Documentation of the option types was clarified in RIOT-OS#8655. I only noticed
after merging RIOT-OS#8884, that `NETOPT_BLE_CTX` was not documented using
that new style. So I deliver the change myself to make it quicker.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: BLE Area: Bluetooth Low Energy support Area: network Area: Networking CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Type: new feature The issue requests / The PR implemements a new feature for RIOT

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants