Merge pull request #8884 from haukepetersen/add_skald
net: add Skald, a BLE advertising stack
This commit is contained in:
commit
a19cb8431d
@ -698,6 +698,15 @@ ifneq (,$(filter benchmark,$(USEMODULE)))
|
|||||||
USEMODULE += xtimer
|
USEMODULE += xtimer
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(filter skald_%,$(USEMODULE)))
|
||||||
|
USEMODULE += skald
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(filter skald,$(USEMODULE)))
|
||||||
|
FEATURES_REQUIRED += radio_ble
|
||||||
|
USEMODULE += xtimer
|
||||||
|
USEMODULE += random
|
||||||
|
endif
|
||||||
# always select gpio (until explicit dependencies are sorted out)
|
# always select gpio (until explicit dependencies are sorted out)
|
||||||
FEATURES_OPTIONAL += periph_gpio
|
FEATURES_OPTIONAL += periph_gpio
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
ifneq (,$(filter saul_default,$(USEMODULE)))
|
ifneq (,$(filter saul_default,$(USEMODULE)))
|
||||||
USEMODULE += saul_gpio
|
USEMODULE += saul_gpio
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(filter skald,$(USEMODULE)))
|
||||||
|
USEMODULE += nrfble
|
||||||
|
endif
|
||||||
|
|||||||
@ -7,6 +7,8 @@ FEATURES_PROVIDED += periph_timer
|
|||||||
FEATURES_PROVIDED += periph_uart
|
FEATURES_PROVIDED += periph_uart
|
||||||
|
|
||||||
# Various other features (if any)
|
# Various other features (if any)
|
||||||
|
FEATURES_PROVIDED += radio_ble
|
||||||
|
FEATURES_PROVIDED += radio_nrfble
|
||||||
FEATURES_PROVIDED += radio_nrfmin
|
FEATURES_PROVIDED += radio_nrfmin
|
||||||
|
|
||||||
# The board MPU family (used for grouping by the CI system)
|
# The board MPU family (used for grouping by the CI system)
|
||||||
|
|||||||
@ -2,6 +2,9 @@ MODULE = cpu_common
|
|||||||
DIRS = periph
|
DIRS = periph
|
||||||
|
|
||||||
# build one of the radio drivers, if enabled
|
# build one of the radio drivers, if enabled
|
||||||
|
ifneq (,$(filter nrfble,$(USEMODULE)))
|
||||||
|
DIRS += radio/nrfble
|
||||||
|
endif
|
||||||
ifneq (,$(filter nrfmin,$(USEMODULE)))
|
ifneq (,$(filter nrfmin,$(USEMODULE)))
|
||||||
DIRS += radio/nrfmin
|
DIRS += radio/nrfmin
|
||||||
endif
|
endif
|
||||||
|
|||||||
55
cpu/nrf5x_common/include/nrfble.h
Normal file
55
cpu/nrf5x_common/include/nrfble.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017-2018 Freie Universität Berlin
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup drivers_nrf5x_nrfble NRF BLE radio driver
|
||||||
|
* @ingroup drivers_netdev
|
||||||
|
* @brief Radio driver for nRF5x SoCs for using the radio in BLE mode
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Interface definition for the nrfble radio driver
|
||||||
|
*
|
||||||
|
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NRFBLE_H
|
||||||
|
#define NRFBLE_H
|
||||||
|
|
||||||
|
#include "net/netdev.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief nrfble channel configuration
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define NRFBLE_CHAN_MIN (0U)
|
||||||
|
#define NRFBLE_CHAN_MAX (39U)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Default transmission power used
|
||||||
|
*/
|
||||||
|
#define NRFBLE_TXPOWER_DEFAULT (0) /* 0dBm */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Setup the device driver's data structures
|
||||||
|
*
|
||||||
|
* @return pointer to the device's netdev struct
|
||||||
|
*/
|
||||||
|
netdev_t *nrfble_setup(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* NRFBLE_H */
|
||||||
|
/** @} */
|
||||||
3
cpu/nrf5x_common/radio/nrfble/Makefile
Normal file
3
cpu/nrf5x_common/radio/nrfble/Makefile
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
MODULE = nrfble
|
||||||
|
|
||||||
|
include $(RIOTBASE)/Makefile.base
|
||||||
360
cpu/nrf5x_common/radio/nrfble/nrfble.c
Normal file
360
cpu/nrf5x_common/radio/nrfble/nrfble.c
Normal file
@ -0,0 +1,360 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017-2018 Freie Universität Berlin
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup drivers_nrf5x_nrfble
|
||||||
|
*
|
||||||
|
* @note This driver is not thread safe and should only be used by a
|
||||||
|
* single thread at once!
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Bluetooth low energy radio driver for nRF5x SoCs
|
||||||
|
*
|
||||||
|
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||||
|
*
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "cpu.h"
|
||||||
|
#include "assert.h"
|
||||||
|
|
||||||
|
#include "nrfble.h"
|
||||||
|
#include "net/netdev/ble.h"
|
||||||
|
|
||||||
|
#define ENABLE_DEBUG (0)
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
/* driver specific device configuration */
|
||||||
|
#define CONF_MODE RADIO_MODE_MODE_Ble_1Mbit
|
||||||
|
#define CONF_LEN (8U)
|
||||||
|
#define CONF_S0 (1U)
|
||||||
|
#define CONF_S1 (0U)
|
||||||
|
#define CONF_STATLEN (0U)
|
||||||
|
#define CONF_BASE_ADDR_LEN (3U)
|
||||||
|
#define CONF_ENDIAN RADIO_PCNF1_ENDIAN_Little
|
||||||
|
#define CONF_WHITENING RADIO_PCNF1_WHITEEN_Enabled
|
||||||
|
#define CONF_TIFS (150U)
|
||||||
|
#define CONF_CRC_LEN (0X3 | RADIO_CRCCNF_SKIPADDR_Msk)
|
||||||
|
#define CONF_CRC_POLY (0x00065b)
|
||||||
|
|
||||||
|
/* used shortcuts */
|
||||||
|
#define SHORTS_BASE (RADIO_SHORTS_READY_START_Msk | \
|
||||||
|
RADIO_SHORTS_END_DISABLE_Msk)
|
||||||
|
#define SHORTS_RX (SHORTS_BASE | RADIO_SHORTS_DISABLED_TXEN_Msk)
|
||||||
|
#define SHORTS_TX (SHORTS_BASE | RADIO_SHORTS_DISABLED_RXEN_Msk)
|
||||||
|
|
||||||
|
/* interrupt masks */
|
||||||
|
#define INT_DIS (RADIO_INTENCLR_DISABLED_Msk | \
|
||||||
|
RADIO_INTENCLR_ADDRESS_Msk)
|
||||||
|
#define INT_EN (RADIO_INTENSET_DISABLED_Msk | \
|
||||||
|
RADIO_INTENSET_ADDRESS_Msk)
|
||||||
|
|
||||||
|
/* driver internal radio states */
|
||||||
|
#define STATE_IDLE (0x00)
|
||||||
|
#define STATE_RX (0x01)
|
||||||
|
#define STATE_TX (0x02)
|
||||||
|
#define STATE_BUSY (0x80)
|
||||||
|
|
||||||
|
/* forward declaration of the netdev driver struct */
|
||||||
|
static const netdev_driver_t netdev_driver;
|
||||||
|
|
||||||
|
/* current radio state */
|
||||||
|
static volatile uint8_t _state = STATE_IDLE;
|
||||||
|
|
||||||
|
/* active radio context */
|
||||||
|
static netdev_ble_ctx_t *_ctx = NULL;
|
||||||
|
|
||||||
|
/* allocate the netdev device descriptor */
|
||||||
|
netdev_t _nrfble_dev;
|
||||||
|
|
||||||
|
/* map logical BLE channel values to actual radio frequencies */
|
||||||
|
static const uint8_t _ble_chan_map[40] = {
|
||||||
|
[ 0] = 4,
|
||||||
|
[ 1] = 6,
|
||||||
|
[ 2] = 8,
|
||||||
|
[ 3] = 10,
|
||||||
|
[ 4] = 12,
|
||||||
|
[ 5] = 14,
|
||||||
|
[ 6] = 16,
|
||||||
|
[ 7] = 18,
|
||||||
|
[ 8] = 20,
|
||||||
|
[ 9] = 22,
|
||||||
|
[10] = 24,
|
||||||
|
[11] = 28,
|
||||||
|
[12] = 30,
|
||||||
|
[13] = 32,
|
||||||
|
[14] = 34,
|
||||||
|
[15] = 36,
|
||||||
|
[16] = 38,
|
||||||
|
[17] = 40,
|
||||||
|
[18] = 42,
|
||||||
|
[19] = 44,
|
||||||
|
[20] = 46,
|
||||||
|
[21] = 48,
|
||||||
|
[22] = 50,
|
||||||
|
[23] = 52,
|
||||||
|
[24] = 54,
|
||||||
|
[25] = 56,
|
||||||
|
[26] = 58,
|
||||||
|
[27] = 60,
|
||||||
|
[28] = 62,
|
||||||
|
[29] = 64,
|
||||||
|
[30] = 66,
|
||||||
|
[31] = 68,
|
||||||
|
[32] = 70,
|
||||||
|
[33] = 72,
|
||||||
|
[34] = 74,
|
||||||
|
[35] = 76,
|
||||||
|
[36] = 78,
|
||||||
|
[37] = 2,
|
||||||
|
[38] = 26,
|
||||||
|
[39] = 80,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set radio into idle (DISABLED) state
|
||||||
|
*/
|
||||||
|
static void _go_idle(void)
|
||||||
|
{
|
||||||
|
if (!(_state & STATE_BUSY)) {
|
||||||
|
NRF_RADIO->INTENCLR = INT_DIS;
|
||||||
|
NRF_RADIO->SHORTS = 0;
|
||||||
|
NRF_RADIO->EVENTS_DISABLED = 0;
|
||||||
|
NRF_RADIO->TASKS_DISABLE = 1;
|
||||||
|
while (NRF_RADIO->EVENTS_DISABLED == 0) {}
|
||||||
|
_state = STATE_IDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set radio context (channel, CRC, whitening, and access address)
|
||||||
|
*/
|
||||||
|
static void _set_context(netdev_ble_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
if (ctx) {
|
||||||
|
assert(ctx->chan <= NRFBLE_CHAN_MAX);
|
||||||
|
|
||||||
|
_ctx = ctx;
|
||||||
|
NRF_RADIO->FREQUENCY = _ble_chan_map[ctx->chan];
|
||||||
|
NRF_RADIO->PREFIX0 = ctx->aa.raw[3];
|
||||||
|
NRF_RADIO->BASE0 = (uint32_t)((ctx->aa.raw[0] << 8) |
|
||||||
|
(ctx->aa.raw[1] << 16) |
|
||||||
|
(ctx->aa.raw[2] << 24));
|
||||||
|
NRF_RADIO->DATAWHITEIV = ctx->chan;
|
||||||
|
NRF_RADIO->CRCINIT = (ctx->crc & NETDEV_BLE_CRC_MASK);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_go_idle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int16_t _nrfble_get_txpower(void)
|
||||||
|
{
|
||||||
|
int8_t p = (int8_t)NRF_RADIO->TXPOWER;
|
||||||
|
if (p < 0) {
|
||||||
|
return (int16_t)(0xff00 | p);
|
||||||
|
}
|
||||||
|
return (int16_t)p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _nrfble_set_txpower(int16_t power)
|
||||||
|
{
|
||||||
|
if (power > 2) {
|
||||||
|
NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Pos4dBm;
|
||||||
|
}
|
||||||
|
else if (power > -2) {
|
||||||
|
NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_0dBm;
|
||||||
|
}
|
||||||
|
else if (power > -6) {
|
||||||
|
NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Neg4dBm;
|
||||||
|
}
|
||||||
|
else if (power > -10) {
|
||||||
|
NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Neg8dBm;
|
||||||
|
}
|
||||||
|
else if (power > -14) {
|
||||||
|
NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Neg12dBm;
|
||||||
|
}
|
||||||
|
else if (power > -18) {
|
||||||
|
NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Neg16dBm;
|
||||||
|
}
|
||||||
|
else if (power > -25) {
|
||||||
|
NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Neg20dBm;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Neg30dBm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Radio interrupt routine
|
||||||
|
*/
|
||||||
|
void isr_radio(void)
|
||||||
|
{
|
||||||
|
if (NRF_RADIO->EVENTS_ADDRESS) {
|
||||||
|
NRF_RADIO->EVENTS_ADDRESS = 0;
|
||||||
|
_state |= STATE_BUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NRF_RADIO->EVENTS_DISABLED) {
|
||||||
|
NRF_RADIO->EVENTS_DISABLED = 0;
|
||||||
|
|
||||||
|
if (_state == (STATE_BUSY | STATE_RX)) {
|
||||||
|
_state = STATE_TX;
|
||||||
|
if (NRF_RADIO->CRCSTATUS) {
|
||||||
|
_ctx->crc |= NETDEV_BLE_CRC_OK;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_ctx->crc &= ~(NETDEV_BLE_CRC_OK);
|
||||||
|
}
|
||||||
|
_nrfble_dev.event_callback(&_nrfble_dev, NETDEV_EVENT_RX_COMPLETE);
|
||||||
|
}
|
||||||
|
else { /* on TX done */
|
||||||
|
_state = STATE_RX;
|
||||||
|
_nrfble_dev.event_callback(&_nrfble_dev, NETDEV_EVENT_TX_COMPLETE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cortexm_isr_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
netdev_t *nrfble_setup(void)
|
||||||
|
{
|
||||||
|
_nrfble_dev.driver = &netdev_driver;
|
||||||
|
_nrfble_dev.event_callback = NULL;
|
||||||
|
_nrfble_dev.context = NULL;
|
||||||
|
#ifdef MODULE_NETSTATS_L2
|
||||||
|
memset(&_nrfble_dev.stats, 0, sizeof(netstats_t));;
|
||||||
|
#endif
|
||||||
|
return &_nrfble_dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _nrfble_init(netdev_t *dev)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
assert(_nrfble_dev.driver && _nrfble_dev.event_callback);
|
||||||
|
|
||||||
|
/* power on the NRFs radio */
|
||||||
|
NRF_RADIO->POWER = 1;
|
||||||
|
/* configure variable parameters to default values */
|
||||||
|
NRF_RADIO->TXPOWER = NRFBLE_TXPOWER_DEFAULT;
|
||||||
|
/* always send from and listen to logical address 0 */
|
||||||
|
NRF_RADIO->TXADDRESS = 0x00UL;
|
||||||
|
NRF_RADIO->RXADDRESSES = 0x01UL;
|
||||||
|
/* load driver specific configuration */
|
||||||
|
NRF_RADIO->MODE = CONF_MODE;
|
||||||
|
/* configure data fields and packet length whitening and endianess */
|
||||||
|
NRF_RADIO->PCNF0 = ((CONF_S1 << RADIO_PCNF0_S1LEN_Pos) |
|
||||||
|
(CONF_S0 << RADIO_PCNF0_S0LEN_Pos) |
|
||||||
|
(CONF_LEN << RADIO_PCNF0_LFLEN_Pos));
|
||||||
|
NRF_RADIO->PCNF1 = ((CONF_WHITENING << RADIO_PCNF1_WHITEEN_Pos) |
|
||||||
|
(CONF_ENDIAN << RADIO_PCNF1_ENDIAN_Pos) |
|
||||||
|
(CONF_BASE_ADDR_LEN << RADIO_PCNF1_BALEN_Pos) |
|
||||||
|
(CONF_STATLEN << RADIO_PCNF1_STATLEN_Pos) |
|
||||||
|
(NETDEV_BLE_PDU_MAXLEN << RADIO_PCNF1_MAXLEN_Pos));
|
||||||
|
/* set inter frame spacing to 150us */
|
||||||
|
NRF_RADIO->TIFS = CONF_TIFS;
|
||||||
|
/* configure CRC length and polynomial */
|
||||||
|
NRF_RADIO->CRCCNF = CONF_CRC_LEN;
|
||||||
|
NRF_RADIO->CRCPOLY = CONF_CRC_POLY;
|
||||||
|
/* enable global interrupts, but mask all local interrupts for now */
|
||||||
|
NRF_RADIO->INTENCLR = 0xffffffff;
|
||||||
|
NVIC_EnableIRQ(RADIO_IRQn);
|
||||||
|
|
||||||
|
DEBUG("[nrfble] initialization successful\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _nrfble_send(netdev_t *dev, const iolist_t *data)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
assert(data);
|
||||||
|
|
||||||
|
NRF_RADIO->PACKETPTR = (uint32_t)data->iol_base;
|
||||||
|
NRF_RADIO->SHORTS = SHORTS_TX;
|
||||||
|
|
||||||
|
/* in case no trx sequence is active, we start a new one now */
|
||||||
|
if (_state == STATE_IDLE) {
|
||||||
|
_state = STATE_TX;
|
||||||
|
NRF_RADIO->EVENTS_DISABLED = 0;
|
||||||
|
NRF_RADIO->INTENSET = INT_EN;
|
||||||
|
NRF_RADIO->TASKS_TXEN = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _nrfble_recv(netdev_t *dev, void *buf, size_t len, void *info)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
(void)len;
|
||||||
|
(void)info;
|
||||||
|
assert(buf && (len == sizeof(netdev_ble_pkt_t)));
|
||||||
|
|
||||||
|
NRF_RADIO->PACKETPTR = (uint32_t)buf;
|
||||||
|
NRF_RADIO->SHORTS = SHORTS_RX;
|
||||||
|
|
||||||
|
/* in case no trx sequence is active, we start a new one now */
|
||||||
|
if (_state == STATE_IDLE) {
|
||||||
|
_state = STATE_RX;
|
||||||
|
NRF_RADIO->EVENTS_DISABLED = 0;
|
||||||
|
NRF_RADIO->INTENSET = INT_EN;
|
||||||
|
NRF_RADIO->TASKS_RXEN = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _nrfble_get(netdev_t *dev, netopt_t opt, void *val, size_t max_len)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
(void)max_len;
|
||||||
|
|
||||||
|
switch (opt) {
|
||||||
|
case NETOPT_TX_POWER:
|
||||||
|
assert(max_len >= sizeof(int16_t));
|
||||||
|
*((int16_t *)val) = _nrfble_get_txpower();
|
||||||
|
return sizeof(int16_t);
|
||||||
|
case NETOPT_DEVICE_TYPE:
|
||||||
|
assert(max_len >= sizeof(uint16_t));
|
||||||
|
*((uint16_t *)val) = NETDEV_TYPE_BLE;
|
||||||
|
return sizeof(uint16_t);
|
||||||
|
default:
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _nrfble_set(netdev_t *dev, netopt_t opt, const void *val, size_t len)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
(void)len;
|
||||||
|
|
||||||
|
switch (opt) {
|
||||||
|
case NETOPT_BLE_CTX:
|
||||||
|
_set_context((netdev_ble_ctx_t *)val);
|
||||||
|
return sizeof(netdev_ble_ctx_t);
|
||||||
|
case NETOPT_TX_POWER:
|
||||||
|
assert(len == sizeof(int16_t));
|
||||||
|
_nrfble_set_txpower(*((const int16_t *)val));
|
||||||
|
return sizeof(int16_t);
|
||||||
|
default:
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* export of the netdev interface */
|
||||||
|
static const netdev_driver_t netdev_driver = {
|
||||||
|
.send = _nrfble_send,
|
||||||
|
.recv = _nrfble_recv,
|
||||||
|
.init = _nrfble_init,
|
||||||
|
.isr = NULL,
|
||||||
|
.get = _nrfble_get,
|
||||||
|
.set = _nrfble_set
|
||||||
|
};
|
||||||
200
drivers/include/net/netdev/ble.h
Normal file
200
drivers/include/net/netdev/ble.h
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017-2018 Freie Universität Berlin
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup drivers_netdev_ble netdev BLE mode
|
||||||
|
* @ingroup drivers_netdev_api
|
||||||
|
* @brief BLE adaption of netdev
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @warning This API is experimental and in an early state - expect
|
||||||
|
* significant changes!
|
||||||
|
*
|
||||||
|
* # About
|
||||||
|
*
|
||||||
|
* BLE defines a very specific environment for the used radio, both in terms of
|
||||||
|
* communication sequences and in terms of timings. BLE communication is
|
||||||
|
* structured in so called events, where each event is a sequence of request and
|
||||||
|
* reply packets send between two peers. A radio context (frequency, CRC
|
||||||
|
* initializer, and access address) is used throughout such an event and
|
||||||
|
* typically changed for the next one. In addition, the timing of the packets
|
||||||
|
* sent in a sequence is fixed to an inter-frame-spacing of exactly 150us.
|
||||||
|
*
|
||||||
|
* To cater with these specific attributes of BLE, this interface tailors the
|
||||||
|
* generic netdev interface to be used for BLE radios.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* # Interface Adaption / Netdev Interpretation
|
||||||
|
*
|
||||||
|
* ## Transmission Sequence Based Approach
|
||||||
|
*
|
||||||
|
* To be able to handle the exact inter-packet-spacing if 150us seconds, this
|
||||||
|
* interface expects the device driver to stay in a continuous alternating
|
||||||
|
* RX-TX sequence, until it is manually aborted. While in this sequence, the
|
||||||
|
* radio driver needs to take care of switching to RX mode 150us after sending
|
||||||
|
* the last packet, and to send the next packet 150us after the last packet was
|
||||||
|
* received.
|
||||||
|
*
|
||||||
|
* Such a transmission sequence is started by calling either the radio's send
|
||||||
|
* or receive function while the radio is in idle/standby mode.
|
||||||
|
*
|
||||||
|
* Once a transmission sequence is in progress, the next packet to be send, or
|
||||||
|
* the next reception buffer to be used is specified also using the send/recv
|
||||||
|
* functions. They should be called in the `event_callback` right after the
|
||||||
|
* last transmission (RX or TX) was finished.
|
||||||
|
*
|
||||||
|
* The transmission sequence is aborted by calling `netdev_ble_stop(dev)`
|
||||||
|
* (`netdev->set(dev, NETOPT_BLE_CTX, NULL, 0)`). This will put the radio back
|
||||||
|
* into idle/standby mode.
|
||||||
|
*
|
||||||
|
* ## Radio Context
|
||||||
|
*
|
||||||
|
* As BLE uses time sliced channel hopping, the used channel needs to be set
|
||||||
|
* regularly. Additionally, also the used access address and the CRC initializer
|
||||||
|
* need to be set regularly, as they differ for different BLE connections. To
|
||||||
|
* make setting these values more efficient, this interface combines these three
|
||||||
|
* values in to a so called `radio context` and adds a `netopt` option to set
|
||||||
|
* all three values at once using `netdev_ble_set_ctx(dev, ctx)`
|
||||||
|
* (`netdev->set(dev, NETOPT_BLE_CTX, ctx, sizeof(netdev_ble_ctx_t))`).
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* # Implementation Status and Limitations
|
||||||
|
* - This interface works for memory mapped radios only (no support for
|
||||||
|
* bus-connected devices). This is mainly for timing reasons.
|
||||||
|
* - No support for LE Data Length Extension (bigger packet size), yet
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief BLE specific adaption for the Netdev API
|
||||||
|
*
|
||||||
|
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NET_NETDEV_BLE_H
|
||||||
|
#define NET_NETDEV_BLE_H
|
||||||
|
|
||||||
|
#include "net/netdev.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum payload length of a standard BLE packet
|
||||||
|
*/
|
||||||
|
#define NETDEV_BLE_PDU_MAXLEN (37U)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Mask for the actual (3 byte) CRC data in the context's CRC field
|
||||||
|
*/
|
||||||
|
#define NETDEV_BLE_CRC_MASK (0x00ffffff)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flag for marking a correct CRC on packet reception
|
||||||
|
*/
|
||||||
|
#define NETDEV_BLE_CRC_OK (0x80000000)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief BLE packet structure (as defined by the BLE standard)
|
||||||
|
*/
|
||||||
|
typedef struct __attribute__((packed)) {
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Radio context
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
union {
|
||||||
|
uint8_t raw[4]; /**< byte-wise access */
|
||||||
|
uint32_t u32; /**< compact access */
|
||||||
|
} aa; /**< access address */
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Send the given packet on the next occasion
|
||||||
|
*
|
||||||
|
* If a transmission sequence is in progress, the given packet will be send
|
||||||
|
* after 150us after receptions of the last packet. If no sequence is currently
|
||||||
|
* active, the packet will be send immediately and a new transmission sequence
|
||||||
|
* is started.
|
||||||
|
*
|
||||||
|
* @note Call this function only to start a new transmission sequence (radio
|
||||||
|
* is currently idle), or right after a packet was received. If called
|
||||||
|
* at any other point in time, the behavior is undefined.
|
||||||
|
*
|
||||||
|
* @param[in] dev radio to use for sending
|
||||||
|
* @param[in] pkt data to send
|
||||||
|
*
|
||||||
|
* @return 0 on success
|
||||||
|
* @return `< 0` on error
|
||||||
|
*/
|
||||||
|
static inline int netdev_ble_send(netdev_t *dev, netdev_ble_pkt_t *pkt)
|
||||||
|
{
|
||||||
|
struct iolist data = { NULL, pkt, sizeof(netdev_ble_pkt_t) };
|
||||||
|
return dev->driver->send(dev, &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Start listening for an incoming packet and write it into @p pkt
|
||||||
|
*
|
||||||
|
* If a transmission sequence is in progress, the radio will use the given
|
||||||
|
* buffer for reception when it goes in to RX mode 150us after sending the last
|
||||||
|
* packet. If no sequence is in progress, the radio will go into RX mode
|
||||||
|
* immediately (using the given RX buffer), and a new transmission sequence is
|
||||||
|
* started.
|
||||||
|
*
|
||||||
|
* @note Call this function only to start a new transmission sequence (radio
|
||||||
|
* is currently idle), or right after a packet was sent. If called
|
||||||
|
* at any other point in time, the behavior is undefined.
|
||||||
|
*
|
||||||
|
* @param[in] dev radio to use for receiving
|
||||||
|
* @param[out] pkt buffer to write new packet to
|
||||||
|
*
|
||||||
|
* @return 0 on success
|
||||||
|
* @return `< 0` on error
|
||||||
|
*/
|
||||||
|
static inline int netdev_ble_recv(netdev_t *dev, netdev_ble_pkt_t *pkt)
|
||||||
|
{
|
||||||
|
return dev->driver->recv(dev, pkt, sizeof(netdev_ble_pkt_t), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the radio context for the given radio device
|
||||||
|
*
|
||||||
|
* @param[in] dev target radio device
|
||||||
|
* @param[in] ctx new radio context (CRC, channel, access address)
|
||||||
|
*/
|
||||||
|
static inline void netdev_ble_set_ctx(netdev_t *dev, netdev_ble_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
dev->driver->set(dev, NETOPT_BLE_CTX, ctx, sizeof(netdev_ble_ctx_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stop the ongoing RX/TX sequence
|
||||||
|
*
|
||||||
|
* @note This function has not effect if the radio is in the middle of a
|
||||||
|
* data transfer
|
||||||
|
*
|
||||||
|
* @param[in] dev target radio device
|
||||||
|
*/
|
||||||
|
static inline void netdev_ble_stop(netdev_t *dev)
|
||||||
|
{
|
||||||
|
dev->driver->set(dev, NETOPT_BLE_CTX, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* NET_NETDEV_BLE_H */
|
||||||
|
/** @} */
|
||||||
21
examples/skald_eddystone/Makefile
Normal file
21
examples/skald_eddystone/Makefile
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# name of your application
|
||||||
|
APPLICATION = skald_eddystone
|
||||||
|
|
||||||
|
# If no BOARD is found in the environment, use this default:
|
||||||
|
BOARD ?= nrf52dk
|
||||||
|
|
||||||
|
# This has to be the absolute path to the RIOT base directory:
|
||||||
|
RIOTBASE ?= $(CURDIR)/../..
|
||||||
|
|
||||||
|
# include Skald
|
||||||
|
USEMODULE += skald_eddystone
|
||||||
|
|
||||||
|
# Comment this out to disable code in RIOT that does safety checking
|
||||||
|
# which is not needed in a production environment but helps in the
|
||||||
|
# development process:
|
||||||
|
# CFLAGS += -DDEVELHELP
|
||||||
|
|
||||||
|
# Change this to 0 show compiler invocation lines by default:
|
||||||
|
QUIET ?= 1
|
||||||
|
|
||||||
|
include $(RIOTBASE)/Makefile.include
|
||||||
8
examples/skald_eddystone/README.md
Normal file
8
examples/skald_eddystone/README.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# Skald iBeacon Example
|
||||||
|
|
||||||
|
This example demonstrates the usage of `Skald` for creating an Google
|
||||||
|
`Eddystone` beacon, advertising an`Eddystone-URI` and an `Eddystone-URL`
|
||||||
|
concurrently.
|
||||||
|
|
||||||
|
Simply compile and flash, and verify your newly created beacon with any type of
|
||||||
|
BLE scanner.
|
||||||
55
examples/skald_eddystone/main.c
Normal file
55
examples/skald_eddystone/main.c
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 Freie Universität Berlin
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup examples
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief BLE Eddystone beacon example using Skald
|
||||||
|
*
|
||||||
|
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||||
|
*
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#include "net/skald/eddystone.h"
|
||||||
|
|
||||||
|
/* example of an Eddystone URI:
|
||||||
|
* - namespace (ASCII): 'supercool!'
|
||||||
|
* - instance (ASCII): `_RIOT_` */
|
||||||
|
#define URI_NAMESPACE { 0x73, 0x75, 0x70, 0x65, 0x72, \
|
||||||
|
0x63, 0x6f, 0x6f, 0x6c, 0x21 }
|
||||||
|
#define URI_INSTANCE { 0x5f, 0x52, 0x49, 0x4f, 0x54, 0x5f }
|
||||||
|
|
||||||
|
/* advertise this short URL, points to https://www.riot-os.org */
|
||||||
|
#define URL "bit.ly/2Ep11dm"
|
||||||
|
/* calibrated TX power value */
|
||||||
|
#define TX_PWR (0U)
|
||||||
|
|
||||||
|
|
||||||
|
/* allocate two advertising contexts, one for Eddystone-URL and one for
|
||||||
|
* Eddystone-URI */
|
||||||
|
static skald_ctx_t _ctx_uid;
|
||||||
|
static skald_ctx_t _ctx_url;
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
LOG_INFO("Skald and the tail of Eddystone\n");
|
||||||
|
|
||||||
|
/* advertise the defined URI */
|
||||||
|
skald_eddystone_uid_t uid = { URI_NAMESPACE, URI_INSTANCE };
|
||||||
|
skald_eddystone_uid_adv(&_ctx_uid, &uid, TX_PWR);
|
||||||
|
|
||||||
|
/* also advertise the defined short-URL */
|
||||||
|
skald_eddystone_url_adv(&_ctx_url, EDDYSTONE_URL_HTTPS, URL, TX_PWR);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
21
examples/skald_ibeacon/Makefile
Normal file
21
examples/skald_ibeacon/Makefile
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# name of your application
|
||||||
|
APPLICATION = skald_ibeacon
|
||||||
|
|
||||||
|
# If no BOARD is found in the environment, use this default:
|
||||||
|
BOARD ?= nrf52dk
|
||||||
|
|
||||||
|
# This has to be the absolute path to the RIOT base directory:
|
||||||
|
RIOTBASE ?= $(CURDIR)/../..
|
||||||
|
|
||||||
|
# include Skald
|
||||||
|
USEMODULE += skald_ibeacon
|
||||||
|
|
||||||
|
# Comment this out to disable code in RIOT that does safety checking
|
||||||
|
# which is not needed in a production environment but helps in the
|
||||||
|
# development process:
|
||||||
|
# CFLAGS += -DDEVELHELP
|
||||||
|
|
||||||
|
# Change this to 0 show compiler invocation lines by default:
|
||||||
|
QUIET ?= 1
|
||||||
|
|
||||||
|
include $(RIOTBASE)/Makefile.include
|
||||||
6
examples/skald_ibeacon/README.md
Normal file
6
examples/skald_ibeacon/README.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# Skald iBeacon Example
|
||||||
|
|
||||||
|
This example demonstrates the usage of `Skald` for creating an Apple `iBeacon`.
|
||||||
|
|
||||||
|
Simply compile and flash, and verify your newly created beacon with any type of
|
||||||
|
BLE scanner.
|
||||||
44
examples/skald_ibeacon/main.c
Normal file
44
examples/skald_ibeacon/main.c
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017-2018 Freie Universität Berlin
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup examples
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Setting up an iBeacon using Skald
|
||||||
|
*
|
||||||
|
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||||
|
*
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#include "net/skald/ibeacon.h"
|
||||||
|
|
||||||
|
/* configure the iBeacon */
|
||||||
|
#define UUID { 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, \
|
||||||
|
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, }
|
||||||
|
#define MAJOR (0x0023)
|
||||||
|
#define MINOR (0x0017)
|
||||||
|
#define TXPOWER (0U)
|
||||||
|
|
||||||
|
/* allocate a single advertising context */
|
||||||
|
static skald_ctx_t _ctx;
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
LOG_INFO("Skald and the tail of the iBeacon\n");
|
||||||
|
|
||||||
|
/* this will configure the iBeacon and start advertising it */
|
||||||
|
skald_uuid_t uuid = { UUID };
|
||||||
|
skald_ibeacon_advertise(&_ctx, &uuid, MAJOR, MINOR, TXPOWER);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@ -117,3 +117,8 @@ PSEUDOMODULES += stm32_periph_%
|
|||||||
# declare periph submodules as pseudomodules, but exclude periph_common
|
# declare periph submodules as pseudomodules, but exclude periph_common
|
||||||
PSEUDOMODULES += periph_%
|
PSEUDOMODULES += periph_%
|
||||||
NO_PSEUDOMODULES += periph_common
|
NO_PSEUDOMODULES += periph_common
|
||||||
|
|
||||||
|
# Submodules and auto-init code provided by Skald
|
||||||
|
PSEUDOMODULES += auto_init_skald
|
||||||
|
PSEUDOMODULES += skald_ibeacon
|
||||||
|
PSEUDOMODULES += skald_eddystone
|
||||||
|
|||||||
@ -124,6 +124,9 @@ endif
|
|||||||
ifneq (,$(filter nanocoap,$(USEMODULE)))
|
ifneq (,$(filter nanocoap,$(USEMODULE)))
|
||||||
DIRS += net/application_layer/nanocoap
|
DIRS += net/application_layer/nanocoap
|
||||||
endif
|
endif
|
||||||
|
ifneq (,$(filter skald,$(USEMODULE)))
|
||||||
|
DIRS += net/skald
|
||||||
|
endif
|
||||||
|
|
||||||
DIRS += $(dir $(wildcard $(addsuffix /Makefile, $(USEMODULE))))
|
DIRS += $(dir $(wildcard $(addsuffix /Makefile, $(USEMODULE))))
|
||||||
|
|
||||||
|
|||||||
@ -80,6 +80,10 @@
|
|||||||
#include "net/gnrc/ipv6/nib.h"
|
#include "net/gnrc/ipv6/nib.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODULE_SKALD
|
||||||
|
#include "net/skald.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define ENABLE_DEBUG (0)
|
#define ENABLE_DEBUG (0)
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
@ -151,6 +155,10 @@ void auto_init(void)
|
|||||||
DEBUG("Auto init gnrc_ipv6_nib module.\n");
|
DEBUG("Auto init gnrc_ipv6_nib module.\n");
|
||||||
gnrc_ipv6_nib_init();
|
gnrc_ipv6_nib_init();
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef MODULE_SKALD
|
||||||
|
DEBUG("Auto init Skald\n");
|
||||||
|
skald_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
/* initialize network devices */
|
/* initialize network devices */
|
||||||
#ifdef MODULE_AUTO_INIT_GNRC_NETIF
|
#ifdef MODULE_AUTO_INIT_GNRC_NETIF
|
||||||
|
|||||||
405
sys/include/net/ble.h
Normal file
405
sys/include/net/ble.h
Normal file
@ -0,0 +1,405 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 Freie Universität Berlin
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup net_ble BLE defines
|
||||||
|
* @ingroup net
|
||||||
|
* @brief General values defined by the BT standard
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief General BLE values as defined by the BT standard
|
||||||
|
*
|
||||||
|
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NET_BLE_H
|
||||||
|
#define NET_BLE_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name BT version constants
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define BLE_VERSION_40 (0x06)
|
||||||
|
#define BLE_VERSION_41 (0x07)
|
||||||
|
#define BLE_VERSION_42 (0x08)
|
||||||
|
#define BLE_VERSION_50 (0x09)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Collections of general BLE constants
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define BLE_AA_LEN (4U) /**< access address length */
|
||||||
|
#define BLE_ADDR_LEN (6U) /**< link layer address length */
|
||||||
|
#define BLE_CRC_LEN (3U) /**< CRC length */
|
||||||
|
#define BLE_CHANMAP_LEN (5U) /**< channel map length */
|
||||||
|
#define BLE_CHAN_NUMOF (40U) /**< number of available channels */
|
||||||
|
#define BLE_CHAN_ADV_NUMOF (3U) /**< number of advertising channels */
|
||||||
|
#define BLE_CHAN_DAT_NUMOF (37U) /**< number of data channels */
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name GATT Declaration UUIDs
|
||||||
|
*
|
||||||
|
* @see https://www.bluetooth.com/specifications/gatt/declarations
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define BLE_DECL_PRI_SERVICE (0x2800)
|
||||||
|
#define BLE_DECL_SEC_SERVICE (0x2801)
|
||||||
|
#define BLE_DECL_INCLUDE (0x2802)
|
||||||
|
#define BLE_DECL_CHAR (0x2803)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name GATT descriptor UUIDs
|
||||||
|
*
|
||||||
|
* @see https://www.bluetooth.com/specifications/gatt/descriptors
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define BLE_DESC_AGGR_FMT (0x2905)
|
||||||
|
#define BLE_DESC_EXT_PROP (0x2900)
|
||||||
|
#define BLE_DESC_PRES_FMT (0x2904)
|
||||||
|
#define BLE_DESC_USER_DESC (0x2901)
|
||||||
|
#define BLE_DESC_CLIENT_CONFIG (0x2902)
|
||||||
|
#define BLE_DESC_ENV_CONFIG (0x290b)
|
||||||
|
#define BLE_DESC_ENV_MEASUREMENT (0x290c)
|
||||||
|
#define BLE_DESC_ENV_TRIGGER_SETTING (0x290d)
|
||||||
|
#define BLE_DESC_EXT_REPORT_REF (0x2907)
|
||||||
|
#define BLE_DESC_NUMOF_DIGITS (0x2909)
|
||||||
|
#define BLE_DESC_REPORT_REF (0x2908)
|
||||||
|
#define BLE_DESC_SERVER_CONFIG (0x2903)
|
||||||
|
#define BLE_DESC_TIME_TRIGGER_SETTING (0x290e)
|
||||||
|
#define BLE_DESC_VALID_RANGE (0x2906)
|
||||||
|
#define BLE_DESC_VALUE_TRIGGER_SETTING (0x290a)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Characteristic format types (8-bit)
|
||||||
|
*
|
||||||
|
* @see https://www.bluetooth.com/specifications/assigned-numbers/format-types
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define BLE_UNIT_BLE_FMT_BOOL (0x01)
|
||||||
|
#define BLE_UNIT_BLE_FMT_2bit (0x02)
|
||||||
|
#define BLE_UNIT_BLE_FMT_NIBBLE (0x03)
|
||||||
|
#define BLE_UNIT_BLE_FMT_UINT8 (0x04)
|
||||||
|
#define BLE_UNIT_BLE_FMT_UINT12 (0x05)
|
||||||
|
#define BLE_UNIT_BLE_FMT_UINT16 (0x06)
|
||||||
|
#define BLE_UNIT_BLE_FMT_UINT24 (0x07)
|
||||||
|
#define BLE_UNIT_BLE_FMT_UINT32 (0x08)
|
||||||
|
#define BLE_UNIT_BLE_FMT_UINT48 (0x09)
|
||||||
|
#define BLE_UNIT_BLE_FMT_UINT64 (0x0A)
|
||||||
|
#define BLE_UNIT_BLE_FMT_UINT128 (0x0B)
|
||||||
|
#define BLE_UNIT_BLE_FMT_SINT8 (0x0C)
|
||||||
|
#define BLE_UNIT_BLE_FMT_SINT12 (0x0D)
|
||||||
|
#define BLE_UNIT_BLE_FMT_SINT16 (0x0E)
|
||||||
|
#define BLE_UNIT_BLE_FMT_SINT24 (0x0F)
|
||||||
|
#define BLE_UNIT_BLE_FMT_SINT32 (0x10)
|
||||||
|
#define BLE_UNIT_BLE_FMT_SINT48 (0x11)
|
||||||
|
#define BLE_UNIT_BLE_FMT_SINT64 (0x12)
|
||||||
|
#define BLE_UNIT_BLE_FMT_SINT128 (0x13)
|
||||||
|
#define BLE_UNIT_BLE_FMT_FLOAT32 (0x14)
|
||||||
|
#define BLE_UNIT_BLE_FMT_FLOAT64 (0x15)
|
||||||
|
#define BLE_UNIT_BLE_FMT_SFLOAT (0x16)
|
||||||
|
#define BLE_UNIT_BLE_FMT_FLOAT (0x17)
|
||||||
|
#define BLE_UNIT_BLE_FMT_DUINT16 (0x18)
|
||||||
|
#define BLE_UNIT_BLE_FMT_UTF8 (0x19)
|
||||||
|
#define BLE_UNIT_BLE_FMT_UTF16 (0x1A)
|
||||||
|
#define BLE_UNIT_BLE_FMT_STRUCT (0x1B)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Units (16-bit)
|
||||||
|
*
|
||||||
|
* @see https://www.bluetooth.com/specifications/assigned-numbers/units
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define BLE_UNIT_NONE (0x2700) /**< no unit */
|
||||||
|
#define BLE_UNIT_BLE_UNIT_METRE (0x2701) /**< length [metre] */
|
||||||
|
#define BLE_UNIT_KILOGRAM (0x2702) /**< mass [kilogram] */
|
||||||
|
#define BLE_UNIT_SECOND (0x2703) /**< time [second] */
|
||||||
|
#define BLE_UNIT_AMPERE (0x2704) /**< electric_current [ampere] */
|
||||||
|
#define BLE_UNIT_KELVIN (0x2705) /**< thermodynamic_temperature [kelvin] */
|
||||||
|
#define BLE_UNIT_MOLE (0x2706) /**< amount_of_substance [mole] */
|
||||||
|
#define BLE_UNIT_CANDELA (0x2707) /**< luminous_intensity [candela] */
|
||||||
|
#define BLE_UNIT_SQUARE_METRES (0x2710) /**< area [square_metres] */
|
||||||
|
#define BLE_UNIT_CUBIC_METRES (0x2711) /**< volume [cubic_metres] */
|
||||||
|
#define BLE_UNIT_METRES_PER_SECOND (0x2712) /**< velocity [metres_per_second] */
|
||||||
|
#define BLE_UNIT_METRES_PER_SECOND_SQUARED (0x2713) /**< acceleration [metres_per_second_squared] */
|
||||||
|
#define BLE_UNIT_RECIPROCAL_METRE (0x2714) /**< wavenumber [reciprocal_metre] */
|
||||||
|
#define BLE_UNIT_KG_PER_CUBIC_METRE (0x2715) /**< density [kilogram_per_cubic_metre] */
|
||||||
|
#define BLE_UNIT_KG_PER_SQUARE_METRE (0x2716) /**< surface_density [kilogram_per_square_metre] */
|
||||||
|
#define BLE_UNIT_CUBIC_METRE_PER_KILOGRAM (0x2717) /**< specific_volume [cubic_metre_per_kilogram] */
|
||||||
|
#define BLE_UNIT_AMPERE_PER_SQUARE_METRE (0x2718) /**< current_density [ampere_per_square_metre] */
|
||||||
|
#define BLE_UNIT_AMPERE_PER_METRE (0x2719) /**< magnetic_field_strength [ampere_per_metre] */
|
||||||
|
#define BLE_UNIT_MOLE_PER_CUBIC_METRE (0x271a) /**< amount_concentration [mole_per_cubic_metre] */
|
||||||
|
#define BLE_UNIT_KILOGRAM_PER_CUBIC_METRE (0x271b) /**< mass_concentration [kilogram_per_cubic_metre] */
|
||||||
|
#define BLE_UNIT_CANDELA_PER_SQUARE_METRE (0x271c) /**< luminance [candela_per_square_metre] */
|
||||||
|
#define BLE_UNIT_REFRACTIVE_INDEX (0x271d) /**< refractive index */
|
||||||
|
#define BLE_UNIT_RELATIVE_PERMEABILITY (0x271e) /**< relative permeability */
|
||||||
|
#define BLE_UNIT_RADIAN (0x2720) /**< plane_angle [radian] */
|
||||||
|
#define BLE_UNIT_STERADIAN (0x2721) /**< solid_angle [steradian] */
|
||||||
|
#define BLE_UNIT_HERTZ (0x2722) /**< frequency [hertz] */
|
||||||
|
#define BLE_UNIT_NEWTON (0x2723) /**< force [newton] */
|
||||||
|
#define BLE_UNIT_PASCAL (0x2724) /**< pressure [pascal] */
|
||||||
|
#define BLE_UNIT_JOULE (0x2725) /**< energy [joule] */
|
||||||
|
#define BLE_UNIT_WATT (0x2726) /**< power [watt] */
|
||||||
|
#define BLE_UNIT_COULOMB (0x2727) /**< electric_charge [coulomb] */
|
||||||
|
#define BLE_UNIT_VOLT (0x2728) /**< electric_potential_difference [volt] */
|
||||||
|
#define BLE_UNIT_FARAD (0x2729) /**< capacitance [farad] */
|
||||||
|
#define BLE_UNIT_OHM (0x272a) /**< electric_resistance [ohm] */
|
||||||
|
#define BLE_UNIT_SIEMENS (0x272b) /**< electric_conductance [siemens] */
|
||||||
|
#define BLE_UNIT_WEBER (0x272c) /**< magnetic_flux [weber] */
|
||||||
|
#define BLE_UNIT_TESLA (0x272d) /**< magnetic_flux_density [tesla] */
|
||||||
|
#define BLE_UNIT_HENRY (0x272e) /**< inductance [henry] */
|
||||||
|
#define BLE_UNIT_DEGREE_CELSIUS (0x272f) /**< thermodynamic_temperature [degree_celsius] */
|
||||||
|
#define BLE_UNIT_LUMEN (0x2730) /**< luminous_flux [lumen] */
|
||||||
|
#define BLE_UNIT_LUX (0x2731) /**< illuminance [lux] */
|
||||||
|
#define BLE_UNIT_BECQUEREL (0x2732) /**< activity_referred_to_a_radionuclide [becquerel] */
|
||||||
|
#define BLE_UNIT_GRAY (0x2733) /**< absorbed_dose [gray] */
|
||||||
|
#define BLE_UNIT_SIEVERT (0x2734) /**< dose_equivalent [sievert] */
|
||||||
|
#define BLE_UNIT_KATAL (0x2735) /**< catalytic_activity [katal] */
|
||||||
|
#define BLE_UNIT_PASCAL_SECOND (0x2740) /**< dynamic_viscosity [pascal_second] */
|
||||||
|
#define BLE_UNIT_NEWTON_METRE (0x2741) /**< moment_of_force [newton_metre] */
|
||||||
|
#define BLE_UNIT_NEWTON_PER_METRE (0x2742) /**< surface_tension [newton_per_metre] */
|
||||||
|
#define BLE_UNIT_RADIAN_PER_SECOND (0x2743) /**< angular_velocity [radian_per_second] */
|
||||||
|
#define BLE_UNIT_RADIAN_PER_SECOND_SQUARED (0x2744) /**< angular_acceleration [radian_per_second_squared] */
|
||||||
|
#define BLE_UNIT_HEAT_FLUX_WATT_PER_M2 (0x2745) /**< heat_flux_density [watt_per_square_metre] */
|
||||||
|
#define BLE_UNIT_JOULE_PER_KELVIN (0x2746) /**< heat_capacity [joule_per_kelvin] */
|
||||||
|
#define BLE_UNIT_JOULE_PER_KG_KELVIN (0x2747) /**< specific_heat_capacity [joule_per_kilogram_kelvin] */
|
||||||
|
#define BLE_UNIT_JOULE_PER_KG (0x2748) /**< specific_energy [joule_per_kilogram] */
|
||||||
|
#define BLE_UNIT_WATT_PER_METRE_KELVIN (0x2749) /**< thermal_conductivity [watt_per_metre_kelvin] */
|
||||||
|
#define BLE_UNIT_JOULE_PER_CUBIC_METRE (0x274a) /**< energy_density [joule_per_cubic_metre] */
|
||||||
|
#define BLE_UNIT_VOLT_PER_METRE (0x274b) /**< electric_field_strength [volt_per_metre] */
|
||||||
|
#define BLE_UNIT_COULOMB_PER_CUBIC_METRE (0x274c) /**< electric_charge_density [coulomb_per_cubic_metre] */
|
||||||
|
#define BLE_UNIT_COULOMB_PER_M2 (0x274d) /**< surface_charge_density [coulomb_per_square_metre] */
|
||||||
|
#define BLE_UNIT_FLUX_COULOMB_PER_M2 (0x274e) /**< electric_flux_density [coulomb_per_square_metre] */
|
||||||
|
#define BLE_UNIT_FARAD_PER_METRE (0x274f) /**< permittivity [farad_per_metre] */
|
||||||
|
#define BLE_UNIT_HENRY_PER_METRE (0x2750) /**< permeability [henry_per_metre] */
|
||||||
|
#define BLE_UNIT_JOULE_PER_MOLE (0x2751) /**< molar_energy [joule_per_mole] */
|
||||||
|
#define BLE_UNIT_JOULE_PER_MOLE_KELVIN (0x2752) /**< molar_entropy [joule_per_mole_kelvin] */
|
||||||
|
#define BLE_UNIT_COULOMB_PER_KG (0x2753) /**< exposure [coulomb_per_kilogram] */
|
||||||
|
#define BLE_UNIT_GRAY_PER_SECOND (0x2754) /**< absorbed_dose_rate [gray_per_second] */
|
||||||
|
#define BLE_UNIT_WATT_PER_STERADIAN (0x2755) /**< radiant_intensity [watt_per_steradian] */
|
||||||
|
#define BLE_UNIT_WATT_PER_M2_STERADIAN (0x2756) /**< radiance [watt_per_square_metre_steradian] */
|
||||||
|
#define BLE_UNIT_KATAL_PER_CUBIC_METRE (0x2757) /**< catalytic_activity_concentration [katal_per_cubic_metre] */
|
||||||
|
#define BLE_UNIT_MINUTE (0x2760) /**< time [minute] */
|
||||||
|
#define BLE_UNIT_HOUR (0x2761) /**< time [hour] */
|
||||||
|
#define BLE_UNIT_DAY (0x2762) /**< time [day] */
|
||||||
|
#define BLE_UNIT_ANGLE_DEGREE (0x2763) /**< plane_angle [degree] */
|
||||||
|
#define BLE_UNIT_ANGLE_MINUTE (0x2764) /**< plane_angle [minute] */
|
||||||
|
#define BLE_UNIT_ANGLE_SECOND (0x2765) /**< plane_angle [second] */
|
||||||
|
#define BLE_UNIT_HECTARE (0x2766) /**< area [hectare] */
|
||||||
|
#define BLE_UNIT_LITRE (0x2767) /**< volume [litre] */
|
||||||
|
#define BLE_UNIT_TONNE (0x2768) /**< mass [tonne] */
|
||||||
|
#define BLE_UNIT_BAR (0x2780) /**< pressure [bar] */
|
||||||
|
#define BLE_UNIT_MILLIMETRE_OF_MERCURY (0x2781) /**< pressure [millimetre_of_mercury] */
|
||||||
|
#define BLE_UNIT_NGSTRM (0x2782) /**< length [ngstrm] */
|
||||||
|
#define BLE_UNIT_NAUTICAL_MILE (0x2783) /**< length [nautical_mile] */
|
||||||
|
#define BLE_UNIT_BARN (0x2784) /**< area [barn] */
|
||||||
|
#define BLE_UNIT_KNOT (0x2785) /**< velocity [knot] */
|
||||||
|
#define BLE_UNIT_NEPER (0x2786) /**< logarithmic_radio_quantity [neper] */
|
||||||
|
#define BLE_UNIT_BEL (0x2787) /**< logarithmic_radio_quantity [bel] */
|
||||||
|
#define BLE_UNIT_YARD (0x27a0) /**< length [yard] */
|
||||||
|
#define BLE_UNIT_PARSEC (0x27a1) /**< length [parsec] */
|
||||||
|
#define BLE_UNIT_INCH (0x27a2) /**< length [inch] */
|
||||||
|
#define BLE_UNIT_FOOT (0x27a3) /**< length [foot] */
|
||||||
|
#define BLE_UNIT_MILE (0x27a4) /**< length [mile] */
|
||||||
|
#define BLE_UNIT_POUND_FORCE_PER_SQU_INCH (0x27a5) /**< pressure [pound_force_per_square_inch] */
|
||||||
|
#define BLE_UNIT_KILOMETRE_PER_HOUR (0x27a6) /**< velocity [kilometre_per_hour] */
|
||||||
|
#define BLE_UNIT_MILE_PER_HOUR (0x27a7) /**< velocity [mile_per_hour] */
|
||||||
|
#define BLE_UNIT_REVOLUTION_PER_MINUTE (0x27a8) /**< angular_velocity [revolution_per_minute] */
|
||||||
|
#define BLE_UNIT_GRAM_CALORIE (0x27a9) /**< energy [gram_calorie] */
|
||||||
|
#define BLE_UNIT_KG_CALORIE (0x27aa) /**< energy [kilogram_calorie] */
|
||||||
|
#define BLE_UNIT_KILOWATT_HOUR (0x27ab) /**< energy [kilowatt_hour] */
|
||||||
|
#define BLE_UNIT_DEGREE_FAHRENHEIT (0x27ac) /**< thermodynamic_temperature [degree_fahrenheit] */
|
||||||
|
#define BLE_UNIT_PERCENTAGE (0x27ad) /**< percentage */
|
||||||
|
#define BLE_UNIT_PER_MILLE (0x27ae) /**< per mille */
|
||||||
|
#define BLE_UNIT_BEATS_PER_MINUTE (0x27af) /**< period [beats_per_minute] */
|
||||||
|
#define BLE_UNIT_AMPERE_HOURS (0x27b0) /**< electric_charge [ampere_hours] */
|
||||||
|
#define BLE_UNIT_MILLIGRAM_PER_DECILITRE (0x27b1) /**< mass_density [milligram_per_decilitre] */
|
||||||
|
#define BLE_UNIT_MILLIMOLE_PER_LITRE (0x27b2) /**< mass_density [millimole_per_litre] */
|
||||||
|
#define BLE_UNIT_YEAR (0x27b3) /**< time [year] */
|
||||||
|
#define BLE_UNIT_MONTH (0x27b4) /**< time [month] */
|
||||||
|
#define BLE_UNIT_COUNT_PER_CUBIC_METRE (0x27b5) /**< concentration [count_per_cubic_metre] */
|
||||||
|
#define BLE_UNIT_WATT_PER_SQUARE_METRE (0x27b6) /**< irradiance [watt_per_square_metre] */
|
||||||
|
#define BLE_UNIT_MLIT_PER_KG_PER_MINUTE (0x27b7) /**< transfer_rate [milliliter_per_kilogram_per_minute] */
|
||||||
|
#define BLE_UNIT_POUND (0x27b8) /**< mass [pound] */
|
||||||
|
#define BLE_UNIT_METABOLIC_EQU (0x27b9) /**< metabolic equivalent */
|
||||||
|
#define BLE_UNIT_STEP_PER_MINUTE (0x27ba) /**< steps per minute */
|
||||||
|
#define BLE_UNIT_STROKE_PER_MINUTE (0x27bc) /**< strokes per minute */
|
||||||
|
#define BLE_UNIT_KILOMETER_PER_MINUTE (0x27bd) /**< velocity [kilometer_per_minute] */
|
||||||
|
#define BLE_UNIT_LUMEN_PER_WATT (0x27be) /**< luminous_efficacy [lumen_per_watt] */
|
||||||
|
#define BLE_UNIT_LUMEN_HOUR (0x27bf) /**< luminous_energy [lumen_hour] */
|
||||||
|
#define BLE_UNIT_LUX_HOUR (0x27c0) /**< luminous_exposure [lux_hour] */
|
||||||
|
#define BLE_UNIT_GRAM_PER_SECOND (0x27c1) /**< mass_flow [gram_per_second] */
|
||||||
|
#define BLE_UNIT_LITRE_PER_SECOND (0x27c2) /**< volume_flow [litre_per_second] */
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name ATT protocol opcodes
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define BLE_ATT_ERROR_RESP (0x01)
|
||||||
|
#define BLE_ATT_MTU_REQ (0x02)
|
||||||
|
#define BLE_ATT_MTU_RESP (0x03)
|
||||||
|
#define BLE_ATT_FIND_INFO_REQ (0x04)
|
||||||
|
#define BLE_ATT_FIND_INFO_RESP (0x05)
|
||||||
|
#define BLE_ATT_FIND_BY_VAL_REQ (0x06)
|
||||||
|
#define BLE_ATT_FIND_BY_VAL_RESP (0x07)
|
||||||
|
#define BLE_ATT_READ_BY_TYPE_REQ (0x08)
|
||||||
|
#define BLE_ATT_READ_BY_TYPE_RESP (0x09)
|
||||||
|
#define BLE_ATT_READ_REQ (0x0a)
|
||||||
|
#define BLE_ATT_READ_RESP (0x0b)
|
||||||
|
#define BLE_ATT_READ_BLOB_REQ (0x0c)
|
||||||
|
#define BLE_ATT_READ_BLOB_RESP (0x0d)
|
||||||
|
#define BLE_ATT_READ_MUL_REQ (0x0e)
|
||||||
|
#define BLE_ATT_READ_MUL_RESP (0x0f)
|
||||||
|
#define BLE_ATT_READ_BY_GROUP_TYPE_REQ (0x10)
|
||||||
|
#define BLE_ATT_READ_BY_GROUP_TYPE_RESP (0x11)
|
||||||
|
#define BLE_ATT_WRITE_REQ (0x12)
|
||||||
|
#define BLE_ATT_WRITE_RESP (0x13)
|
||||||
|
#define BLE_ATT_WRITE_COMMAND (0x52)
|
||||||
|
#define BLE_ATT_PREP_WRITE_REQ (0x16)
|
||||||
|
#define BLE_ATT_PREP_WRITE_RESP (0x17)
|
||||||
|
#define BLE_ATT_EXEC_WRITE_REQ (0x18)
|
||||||
|
#define BLE_ATT_EXEC_WRITE_RESP (0x19)
|
||||||
|
#define BLE_ATT_VAL_NOTIFICATION (0x1b)
|
||||||
|
#define BLE_ATT_VAL_INDICATION (0x1d)
|
||||||
|
#define BLE_ATT_VAL_CONFIRMATION (0x1e)
|
||||||
|
#define BLE_ATT_SIGNED_WRITE_CMD (0xd2)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name ATT protocol error codes
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define BLE_ATT_INVALID_HANDLE (0x01)
|
||||||
|
#define BLE_ATT_READ_NOT_PERMITTED (0x02)
|
||||||
|
#define BLE_ATT_WRITE_NOT_PERMITTED (0x03)
|
||||||
|
#define BLE_ATT_INVALID_PDU (0x04)
|
||||||
|
#define BLE_ATT_INSUFFICIENT_AUTHEN (0x05)
|
||||||
|
#define BLE_ATT_REQUEST_NOT_SUP (0x06)
|
||||||
|
#define BLE_ATT_INVALID_OFFSET (0x07)
|
||||||
|
#define BLE_ATT_INSUFFICIENT_AUTHOR (0x08)
|
||||||
|
#define BLE_ATT_PREPARE_QUEUE_FULL (0x09)
|
||||||
|
#define BLE_ATT_ATTRIBUTE_NOT_FOUND (0x0a)
|
||||||
|
#define BLE_ATT_ATTRIBUTE_NOT_LONG (0x0b)
|
||||||
|
#define BLE_ATT_INSUFFICENT_KEY_SIZE (0x0c)
|
||||||
|
#define BLE_ATT_INVALID_ATTR_VAL_LEN (0x0d)
|
||||||
|
#define BLE_ATT_ULIKELY_ERROR (0x0e)
|
||||||
|
#define BLE_ATT_INSUFFICIENT_ENCRYPTION (0x0f)
|
||||||
|
#define BLE_ATT_UNSUPPORTED_GROUP_TYPE (0x10)
|
||||||
|
#define BLE_ATT_INSUFFICIENT_RESSOURCES (0x11)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name ATT property flags
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define BLE_ATT_BROADCAST (0x01)
|
||||||
|
#define BLE_ATT_READ (0x02)
|
||||||
|
#define BLE_ATT_WRITE_WO_RESP (0x04)
|
||||||
|
#define BLE_ATT_WRITE (0x08)
|
||||||
|
#define BLE_ATT_NOTIFY (0x10)
|
||||||
|
#define BLE_ATT_INDICATE (0x20)
|
||||||
|
#define BLE_ATT_AUTH_SIGNED_WRITES (0x40)
|
||||||
|
#define BLE_ATT_EXT_PROPERTIES (0x80)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Flags used in certain types of ATT PDUs
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define BLE_ATT_FORMAT_U16 (0x01) /**< used in FIND_INFO_RESP */
|
||||||
|
#define BLE_ATT_FORMAT_U128 (0x02) /**< used in FIND_INFO_RESP */
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Flags used in GAP advertisement packets
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define BLE_GAP_DISCOVER_LIM (0x01)
|
||||||
|
#define BLE_GAP_DISCOVERABLE (0x02)
|
||||||
|
#define BLE_GAP_FLAG_BREDR_NOTSUP (0x04)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name BLE advertising packet types
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define BLE_PDU_MASK (0x0f)
|
||||||
|
#define BLE_ADV_IND (0x00)
|
||||||
|
#define BLE_DIRECT_IND (0x01)
|
||||||
|
#define BLE_ADV_NONCON_IND (0x02)
|
||||||
|
#define BLE_SCAN_REQ (0x03)
|
||||||
|
#define BLE_AUX_SCAN_REQ (0x03)
|
||||||
|
#define BLE_SCAN_RESP (0x04)
|
||||||
|
#define BLE_CONNECT_IND (0x05)
|
||||||
|
#define BLE_AUX_CONNECT_REQ (0x05)
|
||||||
|
#define BLE_ADV_SCAN_IND (0x06)
|
||||||
|
#define BLE_ADV_EXT_IND (0x07)
|
||||||
|
#define BLE_AUX_ADV_IND (0x07)
|
||||||
|
#define BLE_AUX_SCAN_RSP (0x07)
|
||||||
|
#define BLE_AUX_SYNC_IND (0x07)
|
||||||
|
#define BLE_AUX_CHAIN_IND (0x07)
|
||||||
|
#define BLE_CONNECT_RESP (0x08)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Advertising packet flags
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define BLE_LL_FLAG_CHSEL (0x20)
|
||||||
|
#define BLE_LL_FLAG_TXADD (0x40)
|
||||||
|
#define BLE_LL_FLAG_RXADD (0x80)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Link layer control message opcodes
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define BLE_LL_CONN_UPDATE_IND (0x00)
|
||||||
|
#define BLE_LL_CHANNEL_MAP_IND (0x01)
|
||||||
|
#define BLE_LL_TERMINATE_IND (0x02)
|
||||||
|
#define BLE_LL_ENC_REQ (0x03)
|
||||||
|
#define BLE_LL_ENC_RSP (0x04)
|
||||||
|
#define BLE_LL_START_ENC_REQ (0x05)
|
||||||
|
#define BLE_LL_START_ENC_RSP (0x06)
|
||||||
|
#define BLE_LL_UNKNOWN_RSP (0x07)
|
||||||
|
#define BLE_LL_FEATURE_REQ (0x08)
|
||||||
|
#define BLE_LL_FEATURE_RSP (0x09)
|
||||||
|
#define BLE_LL_PAUSE_ENC_REQ (0x0a)
|
||||||
|
#define BLE_LL_PAUSE_ENC_RSP (0x0b)
|
||||||
|
#define BLE_LL_VERSION_IND (0x0c)
|
||||||
|
#define BLE_LL_REJECT_IND (0x0d)
|
||||||
|
#define BLE_LL_SLAVE_FEATURE_REQ (0x0e)
|
||||||
|
#define BLE_LL_CONN_PARAM_REQ (0x0f)
|
||||||
|
#define BLE_LL_CONN_PARAM_RSP (0x10)
|
||||||
|
#define BLE_LL_REJECT_EXT_IND (0x11)
|
||||||
|
#define BLE_LL_PING_REQ (0x12)
|
||||||
|
#define BLE_LL_PING_RSP (0x13)
|
||||||
|
#define BLE_LL_LENGTH_REQ (0x14)
|
||||||
|
#define BLE_LL_LENGTH_RSP (0x15)
|
||||||
|
#define BLE_LL_PHY_REQ (0x16)
|
||||||
|
#define BLE_LL_PHY_RSP (0x17)
|
||||||
|
#define BLE_LL_PHY_UPDATE_IND (0x18)
|
||||||
|
#define BLE_LL_MIN_USED_CHAN_IND (0x19)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* NET_BLE_H */
|
||||||
|
/** @} */
|
||||||
63
sys/include/net/eddystone.h
Normal file
63
sys/include/net/eddystone.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 Freie Universität Berlin
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup net_eddystone Eddystone
|
||||||
|
* @ingroup net
|
||||||
|
* @brief General values defined by the BLE Eddystone beacon format
|
||||||
|
*
|
||||||
|
* @see https://github.com/google/eddystone/blob/master/protocol-specification.md
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Constants defined by the Eddystone specification
|
||||||
|
*
|
||||||
|
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NET_EDDYSTONE_H
|
||||||
|
#define NET_EDDYSTONE_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Collection of general Eddystone constants
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define EDDYSTONE_NAMESPACE_LEN (10U)
|
||||||
|
#define EDDYSTONE_INSTANCE_LEN (6U)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name URL scheme prefix values
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define EDDYSTONE_URL_HTTP_WWW (0x00) /**< `http://www.URL` */
|
||||||
|
#define EDDYSTONE_URL_HTTPS_WWWW (0x01) /**< `https://www.URL` */
|
||||||
|
#define EDDYSTONE_URL_HTTP (0x02) /**< `http://URL` */
|
||||||
|
#define EDDYSTONE_URL_HTTPS (0x03) /**< `https://URL` */
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Eddystone frame types
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define EDDYSTONE_UID (0x00)
|
||||||
|
#define EDDYSTONE_URL (0x10)
|
||||||
|
#define EDDYSTONE_TLM (0x20)
|
||||||
|
#define EDDYSTONE_EID (0x30)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* NET_EDDYSTONE_H */
|
||||||
|
/** @} */
|
||||||
@ -532,6 +532,8 @@ typedef enum {
|
|||||||
*/
|
*/
|
||||||
NETOPT_TX_RETRIES_NEEDED,
|
NETOPT_TX_RETRIES_NEEDED,
|
||||||
|
|
||||||
|
NETOPT_BLE_CTX, /**< set radio context (channel, CRC, AA) */
|
||||||
|
|
||||||
/* add more options if needed */
|
/* add more options if needed */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
124
sys/include/net/skald.h
Normal file
124
sys/include/net/skald.h
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 Freie Universität Berlin
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup net_skald Skald, who advertises to the world
|
||||||
|
* @ingroup net
|
||||||
|
* @brief Skald, a minimalistic BLE advertising stack
|
||||||
|
*
|
||||||
|
* # About
|
||||||
|
*
|
||||||
|
* Skald is a very minimalistic BLE implementation, implementing the
|
||||||
|
* `broadcaster` role only. With this focus, the stack allows for setting up
|
||||||
|
* different kind of beacons using an extremely low memory footprint.
|
||||||
|
*
|
||||||
|
* # Design Decisions and Limitations
|
||||||
|
* - support for local addresses only (using `luid` to generate them)
|
||||||
|
* - advertising interval is configured during compile time, override by setting
|
||||||
|
* `CFLAGS+=-DSKALD_INTERVAL=xxx`
|
||||||
|
* - advertising channels are configured during compile time, override by
|
||||||
|
* setting `CFLAGS+=-DSKALD_ADV_CHAN={37,39}`
|
||||||
|
*
|
||||||
|
* # Implementation state
|
||||||
|
* Supported:
|
||||||
|
* - advertising of custom GAP payloads
|
||||||
|
* - iBeacon (full support)
|
||||||
|
* - Eddystone (partly supported)
|
||||||
|
*
|
||||||
|
* Limitations:
|
||||||
|
* - currently Skald supports random static addresses only (generated using
|
||||||
|
* the `luid` module)
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
* @file
|
||||||
|
* @brief Skald's basic interface
|
||||||
|
*
|
||||||
|
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NET_SKALD_H
|
||||||
|
#define NET_SKALD_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "xtimer.h"
|
||||||
|
#include "net/ble.h"
|
||||||
|
#include "net/netdev/ble.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Static advertising interval
|
||||||
|
*/
|
||||||
|
#ifndef SKALD_INTERVAL
|
||||||
|
#define SKALD_INTERVAL (1 * US_PER_SEC)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Static list of used advertising channels
|
||||||
|
*/
|
||||||
|
#ifndef SKALD_ADV_CHAN
|
||||||
|
#define SKALD_ADV_CHAN { 37, 38, 39 }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief UUID representation format used by Skald
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint8_t u8[16]; /**< UUID with byte-wise access */
|
||||||
|
} skald_uuid_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Advertising context holding the advertising data and state
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
netdev_ble_pkt_t pkt; /**< packet holding the advertisement (GAP) data */
|
||||||
|
xtimer_t timer; /**< timer for scheduling advertising events */
|
||||||
|
uint32_t last; /**< last timer trigger (for offset compensation) */
|
||||||
|
uint8_t cur_chan; /**< keep track of advertising channels */
|
||||||
|
} skald_ctx_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize Skald and the underlying radio
|
||||||
|
*/
|
||||||
|
void skald_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Start advertising the given packet
|
||||||
|
*
|
||||||
|
* The packet will be send out each advertising interval (see SKALD_INTERVAL) on
|
||||||
|
* each of the defined advertising channels (see SKALD_ADV_CHAN).
|
||||||
|
*
|
||||||
|
* @param[in,out] ctx start advertising this context
|
||||||
|
*/
|
||||||
|
void skald_adv_start(skald_ctx_t *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stop the ongoing advertisement
|
||||||
|
*
|
||||||
|
* @param[in,out] ctx stop advertising this context
|
||||||
|
*/
|
||||||
|
void skald_adv_stop(skald_ctx_t *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate a random public address
|
||||||
|
*
|
||||||
|
* @note @p buf must be able to hold BLE_ADDR_LEN (6) bytes
|
||||||
|
*
|
||||||
|
* @param[out] buf the generated address is written to this buffer
|
||||||
|
*/
|
||||||
|
void skald_generate_random_addr(uint8_t *buf);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* NET_SKALD_H */
|
||||||
|
/** @} */
|
||||||
83
sys/include/net/skald/eddystone.h
Normal file
83
sys/include/net/skald/eddystone.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 Freie Universität Berlin
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup net_skald_eddystone Skald meets Eddy
|
||||||
|
* @ingroup net_skald
|
||||||
|
* @brief Skald's Eddystone implementation
|
||||||
|
*
|
||||||
|
* # About
|
||||||
|
* This module allows for creation and advertisement of Eddystone beacons (see
|
||||||
|
* https://github.com/google/eddystone).
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* # Implementation state
|
||||||
|
* supported:
|
||||||
|
* - Eddystone-UID
|
||||||
|
* - Eddystone-URL
|
||||||
|
*
|
||||||
|
* not (yet) supported:
|
||||||
|
* - Eddystone-TLM
|
||||||
|
* - Eddystone-EID
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
* @file
|
||||||
|
* @brief Skald's basic interface
|
||||||
|
*
|
||||||
|
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NET_SKALD_EDDYSTONE_H
|
||||||
|
#define NET_SKALD_EDDYSTONE_H
|
||||||
|
|
||||||
|
#include "net/eddystone.h"
|
||||||
|
#include "net/skald.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unique and opaque 16-byte beacon id format used by Eddystone
|
||||||
|
*/
|
||||||
|
typedef struct __attribute__((packed)) {
|
||||||
|
uint8_t namespace[EDDYSTONE_NAMESPACE_LEN]; /**< 10-byte namespace */
|
||||||
|
uint8_t instance[EDDYSTONE_INSTANCE_LEN]; /**< 6-byte instance */
|
||||||
|
} skald_eddystone_uid_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Advertise Eddystone-UID data
|
||||||
|
*
|
||||||
|
* @see https://github.com/google/eddystone/tree/master/eddystone-uid
|
||||||
|
*
|
||||||
|
* @param[out] ctx advertising context
|
||||||
|
* @param[in] uid UID to advertise
|
||||||
|
* @param[in] tx_pwr calibrated TX power to be advertised by the beacon
|
||||||
|
*/
|
||||||
|
void skald_eddystone_uid_adv(skald_ctx_t *ctx,
|
||||||
|
const skald_eddystone_uid_t *uid, uint8_t tx_pwr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Advertise Eddystone-URL data
|
||||||
|
*
|
||||||
|
* @see https://github.com/google/eddystone/tree/master/eddystone-url
|
||||||
|
*
|
||||||
|
* @param[out] ctx advertising context
|
||||||
|
* @param[in] scheme encoded URL scheme prefix
|
||||||
|
* @param[in] url (short) url as \0 terminated string
|
||||||
|
* @param[in] tx_pwr calibrated TX power to be advertised by the beacon
|
||||||
|
*/
|
||||||
|
void skald_eddystone_url_adv(skald_ctx_t *ctx,
|
||||||
|
uint8_t scheme, const char *url, uint8_t tx_pwr);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* NET_SKALD_EDDYSTONE_H */
|
||||||
|
/** @} */
|
||||||
54
sys/include/net/skald/ibeacon.h
Normal file
54
sys/include/net/skald/ibeacon.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 Freie Universität Berlin
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup net_skald_ibeacon Skald about iBeacon
|
||||||
|
* @ingroup net_skald
|
||||||
|
* @brief Skald's simple iBeacon abstraction
|
||||||
|
*
|
||||||
|
* # About
|
||||||
|
* This Skald module supports the creation and advertisement of BLE iBeacons as
|
||||||
|
* defined by Apple (see https://developer.apple.com/ibeacon/).
|
||||||
|
*
|
||||||
|
* # Implementation state
|
||||||
|
* - all known iBeacon properties are supported
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
* @file
|
||||||
|
* @brief Skald's basic interface
|
||||||
|
*
|
||||||
|
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NET_SKALD_IBEACON_H
|
||||||
|
#define NET_SKALD_IBEACON_H
|
||||||
|
|
||||||
|
#include "net/skald.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Configure the IBeacon payload and start advertising
|
||||||
|
*
|
||||||
|
* @param[out] ctx advertising context
|
||||||
|
* @param[in] uuid UUID advertised by the iBeacon
|
||||||
|
* @param[in] major the iBeacon's major number
|
||||||
|
* @param[in] minor the iBeacon's minor number
|
||||||
|
* @param[in] txpower calibrated TX power to be advertised by the beacon
|
||||||
|
*/
|
||||||
|
void skald_ibeacon_advertise(skald_ctx_t *ctx, const skald_uuid_t *uuid,
|
||||||
|
uint16_t major, uint16_t minor, uint8_t txpower);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* NET_SKALD_IBEACON_H */
|
||||||
|
/** @} */
|
||||||
@ -89,6 +89,7 @@ static const char *_netopt_strmap[] = {
|
|||||||
[NETOPT_IQ_INVERT] = "NETOPT_IQ_INVERT",
|
[NETOPT_IQ_INVERT] = "NETOPT_IQ_INVERT",
|
||||||
[NETOPT_TX_RETRIES_NEEDED] = "NETOPT_TX_RETRIES_NEEDED",
|
[NETOPT_TX_RETRIES_NEEDED] = "NETOPT_TX_RETRIES_NEEDED",
|
||||||
[NETOPT_6LO_IPHC] = "NETOPT_6LO_IPHC",
|
[NETOPT_6LO_IPHC] = "NETOPT_6LO_IPHC",
|
||||||
|
[NETOPT_BLE_CTX] = "NETOPT_BLE_CTX",
|
||||||
[NETOPT_NUMOF] = "NETOPT_NUMOF",
|
[NETOPT_NUMOF] = "NETOPT_NUMOF",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
11
sys/net/skald/Makefile
Normal file
11
sys/net/skald/Makefile
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
SRC = skald.c
|
||||||
|
|
||||||
|
ifneq (,$(filter skald_ibeacon,$(USEMODULE)))
|
||||||
|
SRC += skald_ibeacon.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(filter skald_eddystone,$(USEMODULE)))
|
||||||
|
SRC += skald_eddystone.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
include $(RIOTBASE)/Makefile.base
|
||||||
158
sys/net/skald/skald.c
Normal file
158
sys/net/skald/skald.c
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 Freie Universität Berlin
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup net_skald
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Skald's link layer implementation
|
||||||
|
*
|
||||||
|
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||||
|
*
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "assert.h"
|
||||||
|
#include "random.h"
|
||||||
|
#include "luid.h"
|
||||||
|
|
||||||
|
#include "net/netdev/ble.h"
|
||||||
|
#include "net/skald.h"
|
||||||
|
|
||||||
|
/* include fitting radio driver */
|
||||||
|
#if defined(MODULE_NRFBLE)
|
||||||
|
#include "nrfble.h"
|
||||||
|
/* add other BLE radio drivers once implemented - and potentially move to
|
||||||
|
* auto-init at some point */
|
||||||
|
#else
|
||||||
|
#error "[skald] error: unable to find any netdev-ble capable radio"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ENABLE_DEBUG (0)
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#define JITTER_MIN (0U) /* 0ms */
|
||||||
|
#define JITTER_MAX (10000U) /* 10ms */
|
||||||
|
|
||||||
|
#define ADV_CHAN_NUMOF sizeof(_adv_chan)
|
||||||
|
#define ADV_AA (0x8e89bed6) /* access address */
|
||||||
|
#define ADV_CRC (0x00555555) /* CRC initializer */
|
||||||
|
|
||||||
|
static const uint8_t _adv_chan[] = SKALD_ADV_CHAN;
|
||||||
|
|
||||||
|
static netdev_ble_ctx_t _ble_ctx = {
|
||||||
|
.aa.u32 = ADV_AA,
|
||||||
|
.crc = ADV_CRC,
|
||||||
|
};
|
||||||
|
|
||||||
|
static netdev_t *_radio;
|
||||||
|
|
||||||
|
static void _stop_radio(void)
|
||||||
|
{
|
||||||
|
netdev_ble_stop(_radio);
|
||||||
|
_radio->context = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _sched_next(skald_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
ctx->last += SKALD_INTERVAL;
|
||||||
|
/* schedule next advertising event, adding a random jitter between
|
||||||
|
* 0ms and 10ms (see spec v5.0-vol6-b-4.4.2.2.1) */
|
||||||
|
ctx->last += random_uint32_range(JITTER_MIN, JITTER_MAX);
|
||||||
|
/* compensate the time passed since the timer triggered last by using the
|
||||||
|
* current value of the timer */
|
||||||
|
xtimer_set(&ctx->timer, (ctx->last - xtimer_now_usec()));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _on_adv_evt(void *arg)
|
||||||
|
{
|
||||||
|
skald_ctx_t *ctx = (skald_ctx_t *)arg;
|
||||||
|
|
||||||
|
/* advertise on the next adv channel - or skip this event if the radio is
|
||||||
|
* busy */
|
||||||
|
if ((ctx->cur_chan < ADV_CHAN_NUMOF) && (_radio->context == NULL)) {
|
||||||
|
_radio->context = ctx;
|
||||||
|
_ble_ctx.chan = _adv_chan[ctx->cur_chan];
|
||||||
|
netdev_ble_set_ctx(_radio, &_ble_ctx);
|
||||||
|
netdev_ble_send(_radio, &ctx->pkt);
|
||||||
|
++ctx->cur_chan;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ctx->cur_chan = 0;
|
||||||
|
_sched_next(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _on_radio_evt(netdev_t *netdev, netdev_event_t event)
|
||||||
|
{
|
||||||
|
(void)netdev;
|
||||||
|
|
||||||
|
if (event == NETDEV_EVENT_TX_COMPLETE) {
|
||||||
|
skald_ctx_t *ctx = _radio->context;
|
||||||
|
_stop_radio();
|
||||||
|
xtimer_set(&ctx->timer, 150);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void skald_init(void)
|
||||||
|
{
|
||||||
|
assert(dev);
|
||||||
|
|
||||||
|
/* setup and a fitting radio driver - potentially move to auto-init at some
|
||||||
|
* point */
|
||||||
|
#if defined(MODULE_NRFBLE)
|
||||||
|
_radio = nrfble_setup();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_radio->event_callback = _on_radio_evt;
|
||||||
|
_radio->driver->init(_radio);
|
||||||
|
}
|
||||||
|
|
||||||
|
void skald_adv_start(skald_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
assert(ctx);
|
||||||
|
|
||||||
|
/* make sure the given context is not advertising at the moment */
|
||||||
|
skald_adv_stop(ctx);
|
||||||
|
|
||||||
|
/* initialize advertising context */
|
||||||
|
ctx->timer.callback = _on_adv_evt;
|
||||||
|
ctx->timer.arg = ctx;
|
||||||
|
ctx->last = xtimer_now_usec();
|
||||||
|
ctx->cur_chan = 0;
|
||||||
|
ctx->pkt.flags = (BLE_ADV_NONCON_IND | BLE_LL_FLAG_TXADD);
|
||||||
|
|
||||||
|
/* start advertising */
|
||||||
|
_sched_next(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void skald_adv_stop(skald_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
assert(ctx);
|
||||||
|
|
||||||
|
xtimer_remove(&ctx->timer);
|
||||||
|
if (_radio->context == (void *)ctx) {
|
||||||
|
_stop_radio();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void skald_generate_random_addr(uint8_t *buf)
|
||||||
|
{
|
||||||
|
assert(buf);
|
||||||
|
|
||||||
|
luid_get(buf, BLE_ADDR_LEN);
|
||||||
|
/* swap byte 0 and 5, so that the unique byte given by luid does not clash
|
||||||
|
* with universal/local and individual/group bits of address */
|
||||||
|
uint8_t tmp = buf[5];
|
||||||
|
buf[5] = buf[0];
|
||||||
|
/* make address individual and local */
|
||||||
|
buf[0] = ((tmp & 0xfc) | 0x02);
|
||||||
|
}
|
||||||
109
sys/net/skald/skald_eddystone.c
Normal file
109
sys/net/skald/skald_eddystone.c
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 Freie Universität Berlin
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup net_skald_eddystone
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Skald's Eddystone implementation
|
||||||
|
*
|
||||||
|
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||||
|
*
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "assert.h"
|
||||||
|
#include "net/skald/eddystone.h"
|
||||||
|
|
||||||
|
#define PREAMBLE_LEN (11U)
|
||||||
|
#define PA_LEN (7U)
|
||||||
|
#define PB_LEN (3U)
|
||||||
|
|
||||||
|
#define URL_HDR_LEN (6U)
|
||||||
|
|
||||||
|
#define UID_LEN (23U)
|
||||||
|
|
||||||
|
typedef struct __attribute__((packed)) {
|
||||||
|
uint8_t txadd[BLE_ADDR_LEN];
|
||||||
|
uint8_t pa[PA_LEN];
|
||||||
|
uint8_t service_data_len;
|
||||||
|
uint8_t pb[PB_LEN];
|
||||||
|
uint8_t type;
|
||||||
|
} pre_t;
|
||||||
|
|
||||||
|
typedef struct __attribute__((packed)) {
|
||||||
|
pre_t pre;
|
||||||
|
uint8_t tx_pwr;
|
||||||
|
uint8_t namespace[EDDYSTONE_NAMESPACE_LEN];
|
||||||
|
uint8_t instance[EDDYSTONE_INSTANCE_LEN];
|
||||||
|
uint8_t reserved[2];
|
||||||
|
} eddy_uid_t;
|
||||||
|
|
||||||
|
typedef struct __attribute__((packed)) {
|
||||||
|
pre_t pre;
|
||||||
|
uint8_t tx_pwr;
|
||||||
|
uint8_t scheme;
|
||||||
|
uint8_t url[];
|
||||||
|
} eddy_url_t;
|
||||||
|
|
||||||
|
/* ćonstant GAP data preamble parts, containing the following GAP fields:
|
||||||
|
* - flags: BR/EDR not support set
|
||||||
|
* - complete list of 16-bit UUIDs: holding the Eddystone UUID only (0xfeaa)
|
||||||
|
* - service data of type 0xfeaa (Eddystone) */
|
||||||
|
static const uint8_t _pa[PA_LEN] = { 0x02, 0x01, 0x04, 0x03, 0x03, 0xaa, 0xfe };
|
||||||
|
static const uint8_t _pb[PB_LEN] = { 0x16, 0xaa, 0xfe };
|
||||||
|
|
||||||
|
static void _init_pre(pre_t *data, uint8_t type, uint8_t len)
|
||||||
|
{
|
||||||
|
skald_generate_random_addr(data->txadd);
|
||||||
|
memcpy(data->pa, _pa, PA_LEN);
|
||||||
|
memcpy(data->pb, _pb, PB_LEN);
|
||||||
|
data->service_data_len = len;
|
||||||
|
data->type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void skald_eddystone_uid_adv(skald_ctx_t *ctx,
|
||||||
|
const skald_eddystone_uid_t *uid, uint8_t tx_pwr)
|
||||||
|
{
|
||||||
|
assert(ctx && uid);
|
||||||
|
|
||||||
|
eddy_uid_t *pdu = (eddy_uid_t *)ctx->pkt.pdu;
|
||||||
|
_init_pre(&pdu->pre, EDDYSTONE_UID, UID_LEN);
|
||||||
|
|
||||||
|
pdu->tx_pwr = tx_pwr;
|
||||||
|
memcpy(pdu->namespace, uid->namespace, EDDYSTONE_NAMESPACE_LEN);
|
||||||
|
memcpy(pdu->instance, uid->instance, EDDYSTONE_INSTANCE_LEN);
|
||||||
|
memset(pdu->reserved, 0, 2);
|
||||||
|
|
||||||
|
/* start advertising */
|
||||||
|
ctx->pkt.len = sizeof(eddy_uid_t);
|
||||||
|
skald_adv_start(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void skald_eddystone_url_adv(skald_ctx_t *ctx,
|
||||||
|
uint8_t scheme, const char *url, uint8_t tx_pwr)
|
||||||
|
{
|
||||||
|
assert(url && ctx);
|
||||||
|
size_t len = strlen(url);
|
||||||
|
assert(len <= (NETDEV_BLE_PDU_MAXLEN - (URL_HDR_LEN + PREAMBLE_LEN)));
|
||||||
|
|
||||||
|
eddy_url_t *pdu = (eddy_url_t *)ctx->pkt.pdu;
|
||||||
|
_init_pre(&pdu->pre, EDDYSTONE_URL, (URL_HDR_LEN + len));
|
||||||
|
|
||||||
|
/* set remaining service data fields */
|
||||||
|
pdu->tx_pwr = tx_pwr;
|
||||||
|
pdu->scheme = scheme;
|
||||||
|
memcpy(pdu->url, url, len);
|
||||||
|
|
||||||
|
/* start advertising */
|
||||||
|
ctx->pkt.len = (sizeof(pre_t) + 2 + len);
|
||||||
|
skald_adv_start(ctx);
|
||||||
|
}
|
||||||
63
sys/net/skald/skald_ibeacon.c
Normal file
63
sys/net/skald/skald_ibeacon.c
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 Freie Universität Berlin
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup net_skald_ibeacon
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Skald's iBeacon implementation
|
||||||
|
*
|
||||||
|
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||||
|
*
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "byteorder.h"
|
||||||
|
|
||||||
|
#include "net/skald/ibeacon.h"
|
||||||
|
|
||||||
|
#define PREFIX_LEN (9U)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief PDU format for iBeacon packets
|
||||||
|
*/
|
||||||
|
typedef struct __attribute__((packed)) {
|
||||||
|
uint8_t txadd[BLE_ADDR_LEN];
|
||||||
|
uint8_t prefix[PREFIX_LEN];
|
||||||
|
skald_uuid_t uuid;
|
||||||
|
be_uint16_t major;
|
||||||
|
be_uint16_t minor;
|
||||||
|
uint8_t txpower;
|
||||||
|
} ibeacon_t;
|
||||||
|
|
||||||
|
/* constant GAP type value fields, fixed for the iBeacon format */
|
||||||
|
static const uint8_t prefix[PREFIX_LEN] = { 0x02, 0x01, 0x06, 0x1a, 0xff,
|
||||||
|
0x4c, 0x00, 0x02, 0x15 };
|
||||||
|
|
||||||
|
void skald_ibeacon_advertise(skald_ctx_t *ctx, const skald_uuid_t *uuid,
|
||||||
|
uint16_t major, uint16_t minor, uint8_t txpower)
|
||||||
|
{
|
||||||
|
/* configure the iBeacon PDU */
|
||||||
|
ibeacon_t *pdu = (ibeacon_t *)ctx->pkt.pdu;
|
||||||
|
|
||||||
|
ctx->pkt.len = (uint8_t)sizeof(ibeacon_t);
|
||||||
|
|
||||||
|
skald_generate_random_addr(pdu->txadd);
|
||||||
|
memcpy(pdu->prefix, prefix, PREFIX_LEN);
|
||||||
|
memcpy(&pdu->uuid, uuid, sizeof(skald_uuid_t));
|
||||||
|
be_uint16_t tmp = byteorder_htons(major);
|
||||||
|
memcpy(&pdu->major, &tmp, sizeof(uint16_t));
|
||||||
|
tmp = byteorder_htons(minor);
|
||||||
|
memcpy(&pdu->minor, &tmp, sizeof(uint16_t));
|
||||||
|
pdu->txpower = txpower;
|
||||||
|
|
||||||
|
skald_adv_start(ctx);
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user