1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-17 04:52:59 +01:00

pkg/nimble: add 'autoconn' connection manager

This commit is contained in:
Hauke Petersen 2019-08-29 15:56:24 +02:00
parent a7d951a0d7
commit 004eb5e0b6
9 changed files with 634 additions and 3 deletions

View File

@ -59,6 +59,7 @@ PSEUDOMODULES += netstats_l2
PSEUDOMODULES += netstats_ipv6
PSEUDOMODULES += netstats_rpl
PSEUDOMODULES += nimble
PSEUDOMODULES += nimble_autoconn_%
PSEUDOMODULES += newlib
PSEUDOMODULES += newlib_gnu_source
PSEUDOMODULES += newlib_nano

View File

@ -21,7 +21,8 @@ else
CFLAGS += -Wno-unused-but-set-variable
endif
SUBMODS := $(filter nimble_%,$(USEMODULE))
IGNORE := nimble_autoconn_%
SUBMODS := $(filter-out $(IGNORE),$(filter nimble_%,$(USEMODULE)))
.PHONY: all
@ -74,6 +75,9 @@ nimble_drivers_nrf5x:
nimble_addr:
"$(MAKE)" -C $(TDIR)/addr/
nimble_autoconn:
"$(MAKE)" -C $(TDIR)/autoconn
nimble_netif:
"$(MAKE)" -C $(TDIR)/netif/

View File

@ -39,6 +39,16 @@ ifneq (,$(filter nimble_addr,$(USEMODULE)))
USEMODULE += bluetil_addr
endif
ifneq (,$(filter nimble_autoconn_%,$(USEMODULE)))
USEMODULE += nimble_autoconn
endif
ifneq (,$(filter nimble_autoconn,$(USEMODULE)))
USEMODULE += nimble_netif
USEMODULE += nimble_scanner
USEMODULE += bluetil_ad
endif
ifneq (,$(filter nimble_scanlist,$(USEMODULE)))
USEMODULE += nimble_addr
USEMODULE += bluetil_ad

View File

@ -76,6 +76,9 @@ endif
ifneq (,$(filter nimble_addr,$(USEMODULE)))
INCLUDES += -I$(RIOTPKG)/nimble/addr/include
endif
ifneq (,$(filter nimble_autoconn,$(USEMODULE)))
INCLUDES += -I$(RIOTPKG)/nimble/autoconn/include
endif
ifneq (,$(filter nimble_netif,$(USEMODULE)))
INCLUDES += -I$(RIOTPKG)/nimble/netif/include

View File

@ -0,0 +1,3 @@
MODULE = nimble_autoconn
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,202 @@
/*
* Copyright (C) 2019 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 pkg_nimble_autoconn Autoconn
* @ingroup pkg_nimble
* @brief Simple connection manager that automatically opens BLE
* connections to any node that fits some given filter criteria
*
* @experimental
*
* # WARNING
* This module is highly experimental! Expect bugs, instabilities and sudden API
* changes :-)
*
*
* # About
* This NimBLE submodule implements a connection manager for BLE. It takes care
* of scanning, advertising, and opening connections to neighboring nodes. For
* this autoconn periodically switches between advertising and scanning mode,
* hence from accepting incoming connection requests to scanning actively for
* new neighbors.
*
*
* # Concept
* The IETF and BT SIG standards describing IP-over-BLE only describe how to
* transfer IP data over L2CAP connection oriented channels. But they do not
* say anything about when BLE connections should be established between two
* BLE nodes in the first place. While this can be done manually (e.g. via RIOTs
* `ble` shell command), this is certainly no option in massive M2M deployments.
*
* To enable nodes to automatically connect to their neighbors, autoconn
* implements a naive strategy which makes nodes to connect to any neighbor they
* see, as long as the neighbor signals a predefined set of capabilities.
*
* In particular, neighbors are simply filtered by looking at the 16-bit service
* UUIDs included in the `Incomplete List of 16-bit Service UUIDs` field in the
* advertising data that is received from neighbors.
*
* The logical network topology (as seen by IP) is formed by the established
* BLE link layer connections. It is important to node, that the autoconn module
* will form a random topology on the link layer, as no further context
* information is used for the connection decisions. This can potentially lead
* to fragmented, non-connected sub-networks in larger deployments!
*
*
* # State Machine
* Autoconn implements a state machine, that switches a nodes role periodically
* between scanning and advertising. To make sure, that nodes always have a
* chance to see each other, especially when booted at the same point in time,
* the intervals of each role consist of a constant amount of time plus a
* random interval. This way two nodes will eventually see each other and be
* able to establish a connection.
*
* All timing values for the interval duration and the maximum amount of the
* random offset are configurable.
*
*
* # Usage
* In the current state, the filtering of neighbors is hard coded into the
* autoconn module. Two options are implemented:
*
* 1. connect to any neighbor capable of IP-over-BLE -> @ref BLE_GATT_SVC_IPSS
* UUID included in the BLE_GAP_AD_UUID16_INCOMP field of the received
* advertising data
* 2. connect to any neighbor capable of NDN-over-BLE -> @ref BLE_GATT_SVC_NDNSS
* UUID included in the BLE_GAP_AD_UUID16_INCOMP field of the received
* advertising data
*
* The active filter used in autoconn is selected using one of two submodules
* during build time:
*
* 1. `USEMDOULE += nimble_autoconn_ipsp`
* 2. `USEMODULE += nibmle_autoconn_ndnsp'
*
* @note The NDN support service (NDNSP) is defined by us and it is not at
* all standardized nor sanctioned by the BT SIG. For experimental use
* only...
*
*
* # Implementation Status
* - The filter function could be more powerful. It is probably a good idea to
* extend this module to allow for passing custom filter functions using a
* function pointer
* - Currently this module does not allow to use NimBLE as IP-over-BLE node and
* as a GATT server concurrently. This could be enabled by adding an
* additional callback function which exposes some/all GAP events to a user
* application (i.e. BLE_GAP_EVENT_SUBSCRIBE, BLE_GAP_EVENT_NOTIFY_RX,
* BLE_GAP_EVENT_NOTIFY_TX).
* - It might make sense to get rid of the periodic switching between scanning
* and advertising in favor of doing both in parallel. This would simplify the
* code (and configuration) quite a bit. But in the past, there were severe
* stability issues with NimBLE doing this, so it needs to be evaluated in the
* future if this is a feasible option.
*
* @{
*
* @file
* @brief Simple automated connection manager for NimBLE netif
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*/
#ifndef NIMBLE_AUTOCONN_H
#define NIMBLE_AUTOCONN_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Return codes used by the autoconn module
*/
enum {
NIMBLE_AUTOCONN_OK = 0, /**< like a walk in the park */
NIMBLE_AUTOCONN_PARAMERR = -1, /**< invalid parameters given */
NIMBLE_AUTOCONN_ADERR = -2, /**< error generating advertising data */
};
/**
* @brief Set of configuration parameters needed to run autoconn
*/
typedef struct {
/** amount of time spend in scanning mode [in ms] */
uint32_t period_scan;
/** amount of time spend in advertising mode [in ms] */
uint32_t period_adv;
/** a random value from 0 to this value is added to the duration of each
* scanning and advertising period [in ms] */
uint32_t period_jitter;
/** advertising interval used when in advertising mode [in ms] */
uint32_t adv_itvl;
/** scan interval applied while in scanning state [in ms] */
uint32_t scan_itvl;
/** scan window applied while in scanning state [in ms] */
uint32_t scan_win;
/** connection interval used when opening a new connection [in ms] */
uint32_t conn_itvl;
/** slave latency used for new connections [in ms] */
uint16_t conn_latency;
/** supervision timeout used for new connections [in ms] */
uint32_t conn_super_to;
/** node ID included in the advertising data, may be NULL */
const char *node_id;
} nimble_autoconn_params_t;
/**
* @brief Initialize and enable the autoconn module
*
* @warning This function **must** only be called once. Typically this is during
* system initialization or at the beginning of the user application.
* Use nimble_autoconn_update() to update parameters at runtime.
*
* @warning Autoconn expects nimble_netif to be initialized. So make sure
* nimble_netif_init() was called before calling nimble_autoconn_init().
*
* @param[in] params timing parameters to use
* @param[in] ad advertising data, if NULL it is generated
* @param[in] adlen length of @p ad in bytes
*/
int nimble_autoconn_init(const nimble_autoconn_params_t *params,
const uint8_t *ad, size_t adlen);
/**
* @brief Update the used parameters (timing and node ID)
*
* @param[in] params new parameters to apply
* @param[in] ad advertising data, if NULL it is generated
* @param[in] adlen length of @p ad in bytes
*
* @return NIMBLE_AUTOCONN_OK if everything went fine
* @return NIMBLE_AUTOCONN_INVALID if given parameters can not be applied
*/
int nimble_autoconn_update(const nimble_autoconn_params_t *params,
const uint8_t *ad, size_t adlen);
/**
* @brief Enable automated creation of new BLE connections
*/
void nimble_autoconn_enable(void);
/**
* @brief Disable the automated connection management
*
* @note All existing connections are kept, only the scanning and advertising
* is canceled
*/
void nimble_autoconn_disable(void);
#ifdef __cplusplus
}
#endif
#endif /* NIMBLE_AUTOCONN_H */
/** @} */

View File

@ -0,0 +1,91 @@
/*
* Copyright (C) 2019 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 pkg_nimble_autoconn
*
* @{
* @file
* @brief Default configuration for the nimble_autoconn module
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*/
#ifndef NIMBLE_AUTOCONN_PARAMS_H
#define NIMBLE_AUTOCONN_PARAMS_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name Default parameters used for the nimble_netif_autoconn module
* @{
*/
#ifndef NIMBLE_AUTOCONN_PERIOD_SCAN
#define NIMBLE_AUTOCONN_PERIOD_SCAN (2000U) /* 2s */
#endif
#ifndef NIMBLE_AUTOCONN_PERIOD_ADV
#define NIMBLE_AUTOCONN_PERIOD_ADV (10000U) /* 10s */
#endif
#ifndef NIMBLE_AUTOCONN_PERIOD_JITTER
#define NIMBLE_AUTOCONN_PERIOD_JITTER (5000U) /* 0-5s */
#endif
#ifndef NIMBLE_AUTOCONN_ADV_ITVL
#define NIMBLE_AUTOCONN_ADV_ITVL (100U) /* 100ms */
#endif
#ifndef NIMBLE_AUTOCONN_SCAN_ITVL
#define NIMBLE_AUTOCONN_SCAN_ITVL (1500U) /* 1.5s */
#endif
#ifndef NIMBLE_AUTOCONN_SCAN_WIN
#define NIMBLE_AUTOCONN_SCAN_WIN (110U) /* 110ms */
#endif
#ifndef NIMBLE_AUTOCONN_CONN_ITVL
#define NIMBLE_AUTOCONN_CONN_ITVL (75U) /* 75ms */
#endif
#ifndef NIMBLE_AUTOCONN_CONN_LATENCY
#define NIMBLE_AUTOCONN_CONN_LATENCY (0)
#endif
#ifndef NIMBLE_AUTOCONN_CONN_SUPER_TO
#define NIMBLE_AUTOCONN_CONN_SUPER_TO (2500U) /* 2.5s */
#endif
#ifndef NIMBLE_AUTOCONN_NODE_ID
#define NIMBLE_AUTOCONN_NODE_ID "RIOT-autoconn"
#endif
#ifndef NIMBLE_AUTOCONN_PARAMS
#define NIMBLE_AUTOCONN_PARAMS \
{ .period_scan = NIMBLE_AUTOCONN_PERIOD_SCAN, \
.period_adv = NIMBLE_AUTOCONN_PERIOD_ADV, \
.period_jitter = NIMBLE_AUTOCONN_PERIOD_JITTER, \
.adv_itvl = NIMBLE_AUTOCONN_ADV_ITVL, \
.scan_itvl = NIMBLE_AUTOCONN_SCAN_ITVL, \
.scan_win = NIMBLE_AUTOCONN_SCAN_WIN, \
.conn_itvl = NIMBLE_AUTOCONN_CONN_ITVL, \
.conn_latency = NIMBLE_AUTOCONN_CONN_LATENCY, \
.conn_super_to = NIMBLE_AUTOCONN_CONN_SUPER_TO, \
.node_id = NIMBLE_AUTOCONN_NODE_ID, }
#endif
/**@}*/
/**
* @brief nimble_netif_autoconn configuration
*/
static const nimble_autoconn_params_t nimble_autoconn_params =
NIMBLE_AUTOCONN_PARAMS;
#ifdef __cplusplus
}
#endif
#endif /* NIMBLE_AUTOCONN_PARAMS_H */
/** @} */

View File

@ -0,0 +1,301 @@
/*
* Copyright (C) 2018-2019 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 pkg_nimble_autoconn
* @{
*
* @file
* @brief Autoconn connection manager implementation
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*
* @}
*/
#include "assert.h"
#include "random.h"
#include "net/bluetil/ad.h"
#include "net/bluetil/addr.h"
#include "nimble_netif.h"
#include "nimble_netif_conn.h"
#include "nimble_scanner.h"
#include "nimble_autoconn.h"
#include "nimble_autoconn_params.h"
#include "host/ble_hs.h"
#include "nimble/nimble_port.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#if defined(MODULE_NIMBLE_AUTOCONN_IPSP)
#define SVC_FILTER BLE_GATT_SVC_IPSS
#elif defined(MODULE_NIMBLE_AUTOCONN_NDNSP)
#define SVC_FILTER BLE_GATT_SVC_NDNSS
#else
#error "NimBLE autoconn: please select a fitting submodule"
#endif
#define CONN_TIMEOUT_MUL (5U)
enum {
STATE_SCAN,
STATE_ADV,
STATE_IDLE,
STATE_CONN,
};
static volatile uint8_t _state = STATE_IDLE;
static bluetil_ad_t _ad;
static uint8_t _ad_buf[BLE_HS_ADV_MAX_SZ];
static struct ble_gap_adv_params _adv_params;
static struct ble_gap_conn_params _conn_params;
static uint32_t _conn_timeout;
static struct ble_npl_callout _state_evt;
static ble_npl_time_t _timeout_adv_period;
static ble_npl_time_t _timeout_scan_period;
static ble_npl_time_t _period_jitter;
/* this is run inside the NimBLE host thread */
static void _on_state_change(struct ble_npl_event *ev)
{
(void)ev;
ble_npl_time_t offset;
offset = (ble_npl_time_t)random_uint32_range(0, (uint32_t)_period_jitter);
if (_state == STATE_SCAN) {
/* stop scanning */
nimble_scanner_stop();
/* start advertising/accepting */
int res = nimble_netif_accept(_ad.buf, _ad.pos, &_adv_params);
assert((res == NIMBLE_NETIF_OK) || (res == NIMBLE_NETIF_NOMEM));
(void)res;
/* schedule next state change */
_state = STATE_ADV;
ble_npl_callout_reset(&_state_evt, (_timeout_adv_period + offset));
}
else if (_state == STATE_ADV) {
/* stop advertising/accepting */
nimble_netif_accept_stop();
/* start scanning */
nimble_scanner_start();
_state = STATE_SCAN;
ble_npl_callout_reset(&_state_evt, (_timeout_scan_period + offset));
}
}
static int _filter_uuid(const bluetil_ad_t *ad)
{
bluetil_ad_data_t incomp;
if (bluetil_ad_find(ad, BLE_GAP_AD_UUID16_INCOMP, &incomp) == BLUETIL_AD_OK) {
uint16_t filter_uuid = SVC_FILTER;
for (unsigned i = 0; i < incomp.len; i += 2) {
if (memcmp(&filter_uuid, &incomp.data[i], 2) == 0) {
return 1;
}
}
}
return 0;
}
static void _on_scan_evt(uint8_t type, const ble_addr_t *addr, int8_t rssi,
const uint8_t *ad_buf, size_t ad_len)
{
(void)rssi;
/* we are only interested in ADV_IND packets, the rest can be dropped right
* away */
if (type != BLE_HCI_ADV_TYPE_ADV_IND) {
return;
}
bluetil_ad_t ad = {
.buf = (uint8_t *)ad_buf,
.pos = ad_len,
.size = ad_len
};
/* for connection checking we need the address in network byte order */
uint8_t addrn[BLE_ADDR_LEN];
bluetil_addr_swapped_cp(addr->val, addrn);
if (_filter_uuid(&ad) && !nimble_netif_conn_connected(addrn)) {
nimble_autoconn_disable();
_state = STATE_CONN;
int res = nimble_netif_connect(addr, &_conn_params, _conn_timeout);
assert(res >= 0);
(void)res;
DEBUG("[autoconn] SCAN success, initiating connection\n");
}
}
static void _on_netif_evt(int handle, nimble_netif_event_t event)
{
switch (event) {
case NIMBLE_NETIF_CONNECTED_MASTER:
DEBUG("[autoconn] CONNECTED as master %i\n", handle);
assert(_state == STATE_CONN);
_state = STATE_IDLE;
nimble_autoconn_enable();
break;
case NIMBLE_NETIF_CONNECTED_SLAVE:
DEBUG("[autoconn] CONNECTED as slave %i\n", handle);
nimble_autoconn_enable();
break;
case NIMBLE_NETIF_CLOSED_MASTER:
DEBUG("[autoconn] CLOSED master connection\n");
nimble_autoconn_enable();
break;
case NIMBLE_NETIF_CLOSED_SLAVE:
DEBUG("[autoconn] CLOSED slave connection\n");
nimble_autoconn_enable();
break;
case NIMBLE_NETIF_CONNECT_ABORT:
DEBUG("[autoconn] CONNECT ABORT\n");
assert(_state == STATE_CONN);
_state = STATE_IDLE;
nimble_autoconn_enable();
break;
case NIMBLE_NETIF_CONN_UPDATED:
DEBUG("[autoconn] CONNECTION UPDATED %i\n", handle);
/* nothing to do here */
break;
default:
/* this should never happen */
assert(0);
}
}
static int _conn_update(nimble_netif_conn_t *conn, int handle, void *arg)
{
(void)conn;
nimble_netif_update(handle, (const struct ble_gap_upd_params *)arg);
return 0;
}
int nimble_autoconn_init(const nimble_autoconn_params_t *params,
const uint8_t *ad, size_t adlen)
{
/* register our event callback */
nimble_netif_eventcb(_on_netif_evt);
/* setup state machine timer (we use NimBLEs callouts for this) */
ble_npl_callout_init(&_state_evt, nimble_port_get_dflt_eventq(),
_on_state_change, NULL);
/* at last, set the given parameters */
return nimble_autoconn_update(params, ad, adlen);
}
int nimble_autoconn_update(const nimble_autoconn_params_t *params,
const uint8_t *ad, size_t adlen)
{
int res;
(void)res;
if ((params == NULL) || (adlen > sizeof(_ad_buf)) ||
((adlen > 0) && (ad == NULL))) {
return NIMBLE_AUTOCONN_PARAMERR;
}
/* scan and advertising period configuration */
ble_npl_time_ms_to_ticks(params->period_adv, &_timeout_adv_period);
ble_npl_time_ms_to_ticks(params->period_scan, &_timeout_scan_period);
ble_npl_time_ms_to_ticks(params->period_jitter, &_period_jitter);
/* populate the connection parameters */
_conn_params.scan_itvl = ((params->scan_itvl * 1000) / BLE_HCI_SCAN_ITVL);
_conn_params.scan_window = ((params->scan_win * 1000) / BLE_HCI_SCAN_ITVL);
_conn_params.itvl_min = ((params->conn_itvl * 1000) / BLE_HCI_CONN_ITVL);
_conn_params.itvl_max = ((params->conn_itvl * 1000) / BLE_HCI_CONN_ITVL);
_conn_params.latency = 0;
_conn_params.supervision_timeout = (params->conn_super_to / 10);
_conn_params.min_ce_len = 0;
_conn_params.max_ce_len = 0;
_conn_timeout = params->adv_itvl * CONN_TIMEOUT_MUL;
/* we use the same values to updated existing connections */
struct ble_gap_upd_params conn_update_params;
conn_update_params.itvl_min = _conn_params.itvl_min;
conn_update_params.itvl_max = _conn_params.itvl_max;
conn_update_params.latency = _conn_params.latency;
conn_update_params.supervision_timeout = _conn_params.supervision_timeout;
conn_update_params.min_ce_len = 0;
conn_update_params.max_ce_len = 0;
/* calculate the used scan parameters */
struct ble_gap_disc_params scan_params;
scan_params.itvl = ((params->scan_itvl * 1000) / BLE_HCI_SCAN_ITVL),
scan_params.window = ((params->scan_win * 1000) / BLE_HCI_SCAN_ITVL),
scan_params.filter_policy = 0,
scan_params.limited = 0,
scan_params.passive = 0,
scan_params.filter_duplicates = 1,
/* set the advertising parameters used */
_adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
_adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
_adv_params.itvl_min = ((params->adv_itvl * 1000) / BLE_HCI_ADV_ITVL);
_adv_params.itvl_max = ((params->adv_itvl * 1000) / BLE_HCI_ADV_ITVL);
_adv_params.channel_map = 0;
_adv_params.filter_policy = 0;
_adv_params.high_duty_cycle = 0;
/* initialize the advertising data that will be used */
if (adlen > 0) {
memcpy(_ad_buf, ad, adlen);
bluetil_ad_init(&_ad, _ad_buf, adlen, sizeof(_ad_buf));
}
else {
uint16_t svc = SVC_FILTER;
bluetil_ad_init_with_flags(&_ad, _ad_buf, sizeof(_ad_buf),
BLUETIL_AD_FLAGS_DEFAULT);
bluetil_ad_add(&_ad, BLE_GAP_AD_UUID16_INCOMP, &svc, sizeof(svc));
if (params->node_id) {
res = bluetil_ad_add(&_ad, BLE_GAP_AD_NAME,
params->node_id, strlen(params->node_id));
if (res != BLUETIL_AD_OK) {
return NIMBLE_AUTOCONN_ADERR;
}
}
}
/* initialize scanner with default parameters */
nimble_scanner_init(&scan_params, _on_scan_evt);
/* we also need to apply the new connection parameters to all BLE
* connections where we are in the MASTER role */
nimble_netif_conn_foreach(NIMBLE_NETIF_GAP_MASTER, _conn_update,
&conn_update_params);
return NIMBLE_AUTOCONN_OK;
}
void nimble_autoconn_enable(void)
{
DEBUG("[autoconn] ACTIVE\n");
if (nimble_netif_conn_count(NIMBLE_NETIF_UNUSED) > 0) {
_state = STATE_ADV;
_on_state_change(NULL);
}
}
void nimble_autoconn_disable(void)
{
DEBUG("[autoconn] DISABLED\n");
if ((_state == STATE_ADV) || (_state == STATE_SCAN)) {
_state = STATE_IDLE;
ble_npl_callout_stop(&_state_evt);
nimble_scanner_stop();
nimble_netif_accept_stop();
}
}

View File

@ -35,6 +35,11 @@
#include "services/ipss/ble_svc_ipss.h"
#endif
#if defined(MODULE_NIMBLE_AUTOCONN) && !defined(MODULE_NIMBLE_AUTOCONN_NOAUTOINIT)
#include "nimble_autoconn.h"
#include "nimble_autoconn_params.h"
#endif
#ifdef MODULE_NIMBLE_CONTROLLER
#if defined(CPU_FAM_NRF52) || defined(CPU_FAM_NRF51)
#include "nrf_clock.h"
@ -81,6 +86,9 @@ static void *_host_thread(void *arg)
void nimble_riot_init(void)
{
int res;
(void)res;
/* and finally initialize and run the host */
thread_create(_stack_host, sizeof(_stack_host),
NIMBLE_HOST_PRIO,
@ -94,11 +102,10 @@ void nimble_riot_init(void)
/* for reducing code duplication, we read our own address type once here
* so it can be re-used later on */
int res = ble_hs_util_ensure_addr(0);
res = ble_hs_util_ensure_addr(0);
assert(res == 0);
res = ble_hs_id_infer_auto(0, &nimble_riot_own_addr_type);
assert(res == 0);
(void)res;
#ifdef MODULE_NIMBLE_NETIF
extern void nimble_netif_init(void);
@ -119,4 +126,13 @@ void nimble_riot_init(void)
#ifdef MODULE_NIMBLE_SVC_IPSS
ble_svc_ipss_init();
#endif
#if defined(MODULE_NIMBLE_AUTOCONN) && !defined(MODULE_NIMBLE_AUTOCONN_NOAUTOINIT)
ble_gatts_start();
/* CAUTION: this must be called after nimble_netif_init() and also only
* after the GATT server has been initialized */
res = nimble_autoconn_init(&nimble_autoconn_params, NULL, 0);
assert(res == NIMBLE_AUTOCONN_OK);
nimble_autoconn_enable();
#endif
}