mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-24 22:13:52 +01:00
Merge pull request #16860 from haukepetersen/add_nimble_netifextadv
nimble/netif: add support for BT5 PHY modes
This commit is contained in:
commit
dbae3ed706
@ -154,8 +154,11 @@ PSEUDOMODULES += netstats_rpl
|
||||
PSEUDOMODULES += nimble
|
||||
PSEUDOMODULES += nimble_adv_ext
|
||||
PSEUDOMODULES += nimble_autoconn_%
|
||||
PSEUDOMODULES += nimble_netif_ext
|
||||
PSEUDOMODULES += nimble_phy_coded
|
||||
PSEUDOMODULES += nimble_phy_2mbit
|
||||
PSEUDOMODULES += nimble_rpble_ext
|
||||
PSEUDOMODULES += nimble_statconn_ext
|
||||
PSEUDOMODULES += newlib
|
||||
PSEUDOMODULES += newlib_gnu_source
|
||||
PSEUDOMODULES += newlib_nano
|
||||
|
||||
@ -23,7 +23,7 @@ else
|
||||
CFLAGS += -Wno-unused-but-set-variable
|
||||
endif
|
||||
|
||||
IGNORE := nimble_autoconn_% nimble_phy_% nimble_adv_ext
|
||||
IGNORE := nimble_autoconn_% nimble_phy_% nimble_%_ext
|
||||
SUBMODS := $(filter-out $(IGNORE),$(filter nimble_%,$(USEMODULE)))
|
||||
|
||||
.PHONY: all
|
||||
|
||||
@ -12,6 +12,15 @@ USEMODULE += nimble_riot_contrib
|
||||
# RIOT port
|
||||
USEMODULE += nimble_porting_nimble
|
||||
|
||||
# Pull in dependencies based on used features
|
||||
ifneq (,$(filter ble_phy_coded,$(FEATURES_USED)))
|
||||
USEMODULE += nimble_phy_coded
|
||||
endif
|
||||
|
||||
ifneq (,$(filter ble_phy_2mbit,$(FEATURES_USED)))
|
||||
USEMODULE += nimble_phy_2mbit
|
||||
endif
|
||||
|
||||
# NOTE: this dependency depends on inclusion order, for it to work properly
|
||||
# mynewt-core should be selected as nimble backend as early as possible,
|
||||
# i.e. at the application level.
|
||||
@ -56,6 +65,10 @@ ifneq (,$(filter nimble_autoadv,$(USEMODULE)))
|
||||
USEMODULE += bluetil_ad
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_autoconn_ext,$(USEMODULE)))
|
||||
USEMODULE += nimble_netif_ext
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_autoconn_%,$(USEMODULE)))
|
||||
USEMODULE += nimble_autoconn
|
||||
endif
|
||||
@ -67,10 +80,6 @@ ifneq (,$(filter nimble_autoconn,$(USEMODULE)))
|
||||
USEMODULE += bluetil_ad
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_phy_%,$(USEMODULE)))
|
||||
USEMODULE += nimble_adv_ext
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_phy_2mbit,$(USEMODULE)))
|
||||
FEATURES_REQUIRED += ble_phy_2mbit
|
||||
endif
|
||||
@ -79,6 +88,11 @@ ifneq (,$(filter nimble_phy_coded,$(USEMODULE)))
|
||||
FEATURES_REQUIRED += ble_phy_coded
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_rpble_ext,$(USEMODULE)))
|
||||
USEMODULE += nimble_rpble
|
||||
USEMODULE += nimble_netif_ext
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_rpble,$(USEMODULE)))
|
||||
USEMODULE += gnrc_rpl
|
||||
USEMODULE += nimble_netif
|
||||
@ -92,12 +106,22 @@ ifneq (,$(filter nimble_scanlist,$(USEMODULE)))
|
||||
USEMODULE += ztimer_usec
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_statconn_ext,$(USEMODULE)))
|
||||
USEMODULE += nimble_statconn
|
||||
USEMODULE += nimble_netif_ext
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_statconn,$(USEMODULE)))
|
||||
USEMODULE += random
|
||||
USEMODULE += nimble_netif
|
||||
USEMODULE += nimble_addr
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_netif_ext,$(USEMODULE)))
|
||||
USEMODULE += nimble_netif
|
||||
USEMODULE += nimble_adv_ext
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_netif,$(USEMODULE)))
|
||||
FEATURES_REQUIRED += ble_nimble_netif
|
||||
USEMODULE += random
|
||||
|
||||
@ -26,6 +26,14 @@ ifneq (,$(filter nimble_controller,$(USEMODULE)))
|
||||
ifneq (,$(filter nimble_drivers_nrf5x,$(USEMODULE)))
|
||||
INCLUDES += $(NIMIBASE)/nimble/drivers/$(CPU_FAM)/include
|
||||
endif
|
||||
|
||||
# Enable additional PHY modes if requested by the build
|
||||
ifneq (,$(filter ble_phy_2mbit,$(FEATURES_USED)))
|
||||
CFLAGS += -DMYNEWT_VAL_BLE_LL_CFG_FEAT_LE_2M_PHY=1
|
||||
endif
|
||||
ifneq (,$(filter ble_phy_coded,$(FEATURES_USED)))
|
||||
CFLAGS += -DMYNEWT_VAL_BLE_LL_CFG_FEAT_LE_CODED_PHY=1
|
||||
endif
|
||||
endif
|
||||
|
||||
# include nimble host headers
|
||||
@ -94,18 +102,6 @@ ifneq (,$(filter nimble_adv_ext,$(USEMODULE)))
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_phy_2mbit,$(USEMODULE)))
|
||||
ifneq (,$(filter nimble_controller,$(USEMODULE)))
|
||||
CFLAGS += -DMYNEWT_VAL_BLE_LL_CFG_FEAT_LE_2M_PHY=1
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_phy_coded,$(USEMODULE)))
|
||||
ifneq (,$(filter nimble_controller,$(USEMODULE)))
|
||||
CFLAGS += -DMYNEWT_VAL_BLE_LL_CFG_FEAT_LE_CODED_PHY=1
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_netif,$(USEMODULE)))
|
||||
INCLUDES += -I$(RIOTPKG)/nimble/netif/include
|
||||
|
||||
|
||||
@ -131,29 +131,31 @@ enum {
|
||||
*/
|
||||
typedef struct {
|
||||
/** amount of time spend in scanning mode [in ms] */
|
||||
uint32_t period_scan;
|
||||
uint32_t period_scan_ms;
|
||||
/** amount of time spend in advertising mode [in ms] */
|
||||
uint32_t period_adv;
|
||||
uint32_t period_adv_ms;
|
||||
/** 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;
|
||||
uint32_t period_jitter_ms;
|
||||
/** advertising interval used when in advertising mode [in ms] */
|
||||
uint32_t adv_itvl;
|
||||
uint32_t adv_itvl_ms;
|
||||
/** scan interval applied while in scanning state [in ms] */
|
||||
uint32_t scan_itvl;
|
||||
uint32_t scan_itvl_ms;
|
||||
/** scan window applied while in scanning state [in ms] */
|
||||
uint32_t scan_win;
|
||||
uint32_t scan_win_ms;
|
||||
/** opening a new connection is aborted after this time [in ms] */
|
||||
uint32_t conn_timeout;
|
||||
uint32_t conn_timeout_ms;
|
||||
/** connection interval used when opening a new connection, lower bound.
|
||||
* [in ms] */
|
||||
uint32_t conn_itvl_min;
|
||||
uint32_t conn_itvl_min_ms;
|
||||
/** connection interval, upper bound [in ms] */
|
||||
uint32_t conn_itvl_max;
|
||||
/** slave latency used for new connections [in ms] */
|
||||
uint32_t conn_itvl_max_ms;
|
||||
/** slave latency used for new connections */
|
||||
uint16_t conn_latency;
|
||||
/** supervision timeout used for new connections [in ms] */
|
||||
uint32_t conn_super_to;
|
||||
uint32_t conn_super_to_ms;
|
||||
/** BLE PHY mode to use */
|
||||
nimble_phy_t phy_mode;
|
||||
/** node ID included in the advertising data, may be NULL */
|
||||
const char *node_id;
|
||||
} nimble_autoconn_params_t;
|
||||
|
||||
@ -64,24 +64,32 @@ extern "C" {
|
||||
#define NIMBLE_AUTOCONN_CONN_SVTO_MS (2500U) /* 2.5s */
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Default BLE PHY mode used by autoconn
|
||||
*/
|
||||
#ifndef NIMBLE_AUTOCONN_PHY_MODE
|
||||
#define NIMBLE_AUTOCONN_PHY_MODE NIMBLE_PHY_1M
|
||||
#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_MS, \
|
||||
.period_adv = NIMBLE_AUTOCONN_PERIOD_ADV_MS, \
|
||||
.period_jitter = NIMBLE_AUTOCONN_PERIOD_JITTER_MS, \
|
||||
.adv_itvl = NIMBLE_AUTOCONN_ADV_ITVL_MS, \
|
||||
.scan_itvl = NIMBLE_AUTOCONN_SCAN_ITVL_MS, \
|
||||
.scan_win = NIMBLE_AUTOCONN_SCAN_WIN_MS, \
|
||||
.conn_timeout = NIMBLE_AUTOCONN_CONN_TIMEOUT_MS, \
|
||||
.conn_itvl_min = NIMBLE_AUTOCONN_CONN_ITVL_MIN_MS, \
|
||||
.conn_itvl_max = NIMBLE_AUTOCONN_CONN_ITVL_MAX_MS, \
|
||||
.conn_latency = NIMBLE_AUTOCONN_CONN_LATENCY, \
|
||||
.conn_super_to = NIMBLE_AUTOCONN_CONN_SVTO_MS, \
|
||||
.node_id = NIMBLE_AUTOCONN_NODE_ID, }
|
||||
{ .period_scan_ms = NIMBLE_AUTOCONN_PERIOD_SCAN_MS, \
|
||||
.period_adv_ms = NIMBLE_AUTOCONN_PERIOD_ADV_MS, \
|
||||
.period_jitter_ms = NIMBLE_AUTOCONN_PERIOD_JITTER_MS, \
|
||||
.adv_itvl_ms = NIMBLE_AUTOCONN_ADV_ITVL_MS, \
|
||||
.scan_itvl_ms = NIMBLE_AUTOCONN_SCAN_ITVL_MS, \
|
||||
.scan_win_ms = NIMBLE_AUTOCONN_SCAN_WIN_MS, \
|
||||
.conn_timeout_ms = NIMBLE_AUTOCONN_CONN_TIMEOUT_MS, \
|
||||
.conn_itvl_min_ms = NIMBLE_AUTOCONN_CONN_ITVL_MIN_MS, \
|
||||
.conn_itvl_max_ms = NIMBLE_AUTOCONN_CONN_ITVL_MAX_MS, \
|
||||
.conn_latency = NIMBLE_AUTOCONN_CONN_LATENCY, \
|
||||
.conn_super_to_ms = NIMBLE_AUTOCONN_CONN_SVTO_MS, \
|
||||
.phy_mode = NIMBLE_AUTOCONN_PHY_MODE, \
|
||||
.node_id = NIMBLE_AUTOCONN_NODE_ID, }
|
||||
#endif
|
||||
/**@}*/
|
||||
|
||||
|
||||
@ -55,9 +55,8 @@ static volatile uint8_t _enabled = 0;
|
||||
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 nimble_netif_accept_cfg_t _accept_params;
|
||||
static nimble_netif_connect_cfg_t _conn_params;
|
||||
|
||||
static struct ble_npl_callout _state_evt;
|
||||
static ble_npl_time_t _timeout_adv_period;
|
||||
@ -77,7 +76,7 @@ static void _on_state_change(struct ble_npl_event *ev)
|
||||
/* stop scanning */
|
||||
nimble_scanner_stop();
|
||||
/* start advertising/accepting */
|
||||
int res = nimble_netif_accept(_ad.buf, _ad.pos, &_adv_params);
|
||||
int res = nimble_netif_accept(_ad.buf, _ad.pos, &_accept_params);
|
||||
assert((res == 0) || (res == -ENOMEM));
|
||||
(void)res;
|
||||
|
||||
@ -137,11 +136,18 @@ static void _on_scan_evt(uint8_t type, const ble_addr_t *addr,
|
||||
{
|
||||
(void)info;
|
||||
|
||||
#if IS_USED(MODULE_NIMBLE_AUTOCONN_EXT)
|
||||
if ((type != (NIMBLE_SCANNER_EXT_ADV | BLE_HCI_ADV_CONN_MASK)) ||
|
||||
(info->status != BLE_GAP_EXT_ADV_DATA_STATUS_COMPLETE)) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
/* we are only interested in ADV_IND packets, the rest can be dropped right
|
||||
* away */
|
||||
if (type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
bluetil_ad_t ad = {
|
||||
.buf = (uint8_t *)ad_buf,
|
||||
@ -157,7 +163,7 @@ static void _on_scan_evt(uint8_t type, const ble_addr_t *addr,
|
||||
nimble_scanner_stop();
|
||||
DEBUG("[autoconn] SCAN success, initiating connection\n");
|
||||
_state = STATE_CONN;
|
||||
int res = nimble_netif_connect(addr, &_conn_params, _conn_timeout);
|
||||
int res = nimble_netif_connect(addr, &_conn_params);
|
||||
assert(res >= 0);
|
||||
(void)res;
|
||||
}
|
||||
@ -271,47 +277,66 @@ int nimble_autoconn_update(const nimble_autoconn_params_t *params,
|
||||
}
|
||||
|
||||
/* 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);
|
||||
ble_npl_time_ms_to_ticks(params->period_adv_ms, &_timeout_adv_period);
|
||||
ble_npl_time_ms_to_ticks(params->period_scan_ms, &_timeout_scan_period);
|
||||
ble_npl_time_ms_to_ticks(params->period_jitter_ms, &_period_jitter);
|
||||
|
||||
/* populate the connection parameters */
|
||||
_conn_params.scan_itvl = BLE_GAP_SCAN_ITVL_MS(params->scan_win);
|
||||
_conn_params.scan_window = _conn_params.scan_itvl;
|
||||
_conn_params.itvl_min = BLE_GAP_CONN_ITVL_MS(params->conn_itvl_min);
|
||||
_conn_params.itvl_max = BLE_GAP_CONN_ITVL_MS(params->conn_itvl_max);
|
||||
_conn_params.latency = 0;
|
||||
_conn_params.supervision_timeout = BLE_GAP_SUPERVISION_TIMEOUT_MS(
|
||||
params->conn_super_to);
|
||||
_conn_params.min_ce_len = 0;
|
||||
_conn_params.max_ce_len = 0;
|
||||
_conn_timeout = params->conn_timeout;
|
||||
memset(&_conn_params, 0, sizeof(_conn_params));
|
||||
_conn_params.scan_itvl_ms = params->scan_itvl_ms;
|
||||
_conn_params.scan_window_ms = params->scan_win_ms;
|
||||
_conn_params.conn_itvl_min_ms = params->conn_itvl_min_ms;
|
||||
_conn_params.conn_itvl_max_ms = params->conn_itvl_max_ms;
|
||||
_conn_params.conn_supervision_timeout_ms = params->conn_super_to_ms;
|
||||
_conn_params.conn_slave_latency = params->conn_latency;
|
||||
_conn_params.timeout_ms = params->conn_timeout_ms;
|
||||
#if IS_USED(MODULE_NIMBLE_AUTOCONN_EXT)
|
||||
_conn_params.phy_mode = params->phy_mode;
|
||||
#else
|
||||
_conn_params.phy_mode = NIMBLE_PHY_1M;
|
||||
#endif
|
||||
_conn_params.own_addr_type = nimble_riot_own_addr_type;
|
||||
|
||||
/* 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.itvl_min = BLE_GAP_CONN_ITVL_MS(params->conn_itvl_min_ms);
|
||||
conn_update_params.itvl_max = BLE_GAP_CONN_ITVL_MS(params->conn_itvl_max_ms);
|
||||
conn_update_params.latency = params->conn_latency;
|
||||
conn_update_params.supervision_timeout =
|
||||
BLE_GAP_SUPERVISION_TIMEOUT_MS(params->conn_super_to_ms);
|
||||
conn_update_params.min_ce_len = 0;
|
||||
conn_update_params.max_ce_len = 0;
|
||||
|
||||
/* calculate the used scan parameters */
|
||||
nimble_scanner_cfg_t scan_params;
|
||||
scan_params.itvl_ms = params->scan_itvl;
|
||||
scan_params.win_ms = params->scan_win;
|
||||
scan_params.flags = NIMBLE_SCANNER_PASSIVE
|
||||
| NIMBLE_SCANNER_FILTER_DUPS
|
||||
| NIMBLE_SCANNER_PHY_1M;
|
||||
scan_params.itvl_ms = params->scan_itvl_ms;
|
||||
scan_params.win_ms = params->scan_win_ms;
|
||||
scan_params.flags = (NIMBLE_SCANNER_PASSIVE | NIMBLE_SCANNER_FILTER_DUPS);
|
||||
#if IS_USED(MODULE_NIMBLE_AUTOCONN_EXT) && IS_USED(MODULE_NIMBLE_PHY_CODED)
|
||||
if (params->phy_mode == NIMBLE_PHY_CODED) {
|
||||
scan_params.flags |= NIMBLE_SCANNER_PHY_CODED;
|
||||
}
|
||||
else {
|
||||
scan_params.flags |= NIMBLE_SCANNER_PHY_1M;
|
||||
}
|
||||
#else
|
||||
scan_params.flags |= NIMBLE_SCANNER_PHY_1M;
|
||||
#endif
|
||||
|
||||
/* 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 = BLE_GAP_ADV_ITVL_MS(params->adv_itvl);
|
||||
_adv_params.itvl_max = _adv_params.itvl_min;
|
||||
_adv_params.channel_map = 0;
|
||||
_adv_params.filter_policy = 0;
|
||||
_adv_params.high_duty_cycle = 0;
|
||||
memset(&_accept_params, 0, sizeof(_accept_params));
|
||||
#if IS_USED(MODULE_NIMBLE_AUTOCONN_EXT)
|
||||
_accept_params.flags = 0;
|
||||
_accept_params.primary_phy = params->phy_mode;
|
||||
_accept_params.secondary_phy = params->phy_mode;
|
||||
#else
|
||||
_accept_params.flags = NIMBLE_NETIF_FLAG_LEGACY;
|
||||
_accept_params.primary_phy = NIMBLE_PHY_1M;
|
||||
_accept_params.secondary_phy = NIMBLE_PHY_1M;
|
||||
#endif
|
||||
_accept_params.adv_itvl_ms = params->adv_itvl_ms;
|
||||
_accept_params.timeout_ms = BLE_HS_FOREVER;
|
||||
_accept_params.own_addr_type = nimble_riot_own_addr_type;
|
||||
|
||||
/* initialize the advertising data that will be used */
|
||||
if (adlen > 0) {
|
||||
|
||||
@ -69,6 +69,20 @@ extern "C" {
|
||||
#define NIMBLE_HOST_STACKSIZE (THREAD_STACKSIZE_DEFAULT)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief BLE PHY modes
|
||||
*/
|
||||
typedef enum {
|
||||
NIMBLE_PHY_INVALID, /**< PHY mode invalid */
|
||||
NIMBLE_PHY_1M, /**< legacy 1Mbit PHY mode (always supported) */
|
||||
#if IS_USED(MODULE_NIMBLE_PHY_2MBIT)
|
||||
NIMBLE_PHY_2M, /**< 2Mbit PHY mode */
|
||||
#endif
|
||||
#if IS_USED(MODULE_NIMBLE_PHY_CODED)
|
||||
NIMBLE_PHY_CODED, /**< Coded (long range) PHY mode */
|
||||
#endif
|
||||
} nimble_phy_t;
|
||||
|
||||
/**
|
||||
* @brief Export our own address type for later usage
|
||||
*/
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2019 Freie Universität Berlin
|
||||
* Copyright (C) 2018-2021 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
|
||||
@ -70,6 +70,7 @@
|
||||
#include <errno.h>
|
||||
|
||||
#include "net/ble.h"
|
||||
#include "nimble_riot.h"
|
||||
|
||||
#include "host/ble_hs.h"
|
||||
|
||||
@ -103,6 +104,46 @@ extern "C" {
|
||||
#define NIMBLE_NETIF_MTU (1280U)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Flags for enabling legacy advertisement and high-duty cycle mode
|
||||
* when accepting incoming connections
|
||||
*/
|
||||
enum {
|
||||
NIMBLE_NETIF_FLAG_LEGACY = 0x01, /**< use legacy advertising mode */
|
||||
NIMBLE_NETIF_FLAG_HD_MODE = 0x02, /**< use high duty cycle mode, only
|
||||
* valid for direct advertising */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Parameter set used to configure accepting connections (advertising)
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t flags; /**< flags */
|
||||
uint8_t channel_map; /**< specify custom channel map */
|
||||
uint8_t own_addr_type; /**< specify our own address type to use */
|
||||
int8_t tx_power; /**< specify TX power to be used */
|
||||
uint32_t adv_itvl_ms; /**< advertising interval [ms] */
|
||||
uint32_t timeout_ms; /**< stop accepting after this time [ms] */
|
||||
nimble_phy_t primary_phy; /**< primary PHY mode */
|
||||
nimble_phy_t secondary_phy; /**< secondary PHY mode */
|
||||
} nimble_netif_accept_cfg_t;
|
||||
|
||||
/**
|
||||
* @brief Parameter set used to configure connection initiation
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t scan_itvl_ms; /**< scan interval [ms] */
|
||||
uint16_t scan_window_ms; /**< scan window [ms] */
|
||||
uint16_t conn_itvl_min_ms; /**< connection interval, lower bound [ms] */
|
||||
uint16_t conn_itvl_max_ms; /**< connection interval, upper bound [ms] */
|
||||
uint16_t conn_supervision_timeout_ms; /**< supervision timeout [ms] */
|
||||
uint16_t conn_slave_latency;/**< slave latency */
|
||||
uint32_t timeout_ms; /**< abort connection initiation after this time
|
||||
* [ms] */
|
||||
uint8_t phy_mode; /**< PHY mode used for the connection */
|
||||
uint8_t own_addr_type; /**< specify our own address type to use */
|
||||
} nimble_netif_connect_cfg_t;
|
||||
|
||||
/**
|
||||
* @brief Set to > 0 to enforce different connection intervals for each of the
|
||||
* nodes BLE connections
|
||||
@ -197,19 +238,18 @@ void nimble_netif_eventcb(nimble_netif_eventcb_t cb);
|
||||
*
|
||||
* @param[in] addr address of the advertising BLE slave, in the NimBLE
|
||||
* addr format (little endian)
|
||||
* @param[in] conn_params connection (timing) parameters, set to NULL to use
|
||||
* NimBLEs default parameters
|
||||
* @param[in] timeout connect timeout [in ms]
|
||||
* @param[in] cfg connection parameters
|
||||
*
|
||||
* @return the used connection handle on success
|
||||
* @return -EBUSY if already connected to the given address or if
|
||||
* a connection setup procedure is in progress
|
||||
* @return -EBUSY if already connected to the given address or if a connection
|
||||
* setup procedure is in progress
|
||||
* @return -ENOMEM if no connection context memory is available
|
||||
* @return -ECANCELED if unable to find valid connection interval
|
||||
* @return -EINVAL if unable to apply given PHY mode
|
||||
* @return -EIO on all other NimBLE errors
|
||||
*/
|
||||
int nimble_netif_connect(const ble_addr_t *addr,
|
||||
struct ble_gap_conn_params *conn_params,
|
||||
uint32_t timeout);
|
||||
const nimble_netif_connect_cfg_t *cfg);
|
||||
|
||||
/**
|
||||
* @brief Close the connection with the given handle
|
||||
@ -219,6 +259,7 @@ int nimble_netif_connect(const ble_addr_t *addr,
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if the handle is invalid
|
||||
* @return -ENOTCONN if context for given handle is not connected
|
||||
* @return -EIO on all other NimBLE errors
|
||||
*/
|
||||
int nimble_netif_close(int handle);
|
||||
|
||||
@ -227,36 +268,39 @@ int nimble_netif_close(int handle);
|
||||
*
|
||||
* @param[in] ad advertising data (in BLE AD format)
|
||||
* @param[in] ad_len length of @p ad in bytes
|
||||
* @param[in] adv_params advertising (timing) parameters to use
|
||||
* @param[in] cfg advertising parameters to use
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return -EALREADY if already advertising
|
||||
* @return -ENOMEM on insufficient connection memory
|
||||
* @return -EINVAL on invalid configuration parameters
|
||||
* @return -ECANCELED on other errors
|
||||
*/
|
||||
int nimble_netif_accept(const uint8_t *ad, size_t ad_len,
|
||||
const struct ble_gap_adv_params *adv_params);
|
||||
const nimble_netif_accept_cfg_t *cfg);
|
||||
|
||||
/**
|
||||
* @brief Wait for an incoming connection from a specific peer, sending
|
||||
* directed advertisements (IND_DIR)
|
||||
* directed advertisements
|
||||
*
|
||||
* @param[in] addr BLE address of the target peer
|
||||
* @param[in] timeout_ms stop advertising after this time (in ms), set to
|
||||
* BLE_HS_FOREVER to disable timeout
|
||||
* @param[in] adv_params advertising (timing) parameters to use
|
||||
* @param[in] cfg advertising parameters to use
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return -EALREADY if already advertising
|
||||
* @return -ENOMEM on insufficient connection memory
|
||||
* @return -EINVAL on invalid configuration parameters
|
||||
* @return -ECANCELED on other errors
|
||||
*/
|
||||
int nimble_netif_accept_direct(const ble_addr_t *addr, uint32_t timeout_ms,
|
||||
const struct ble_gap_adv_params *adv_params);
|
||||
int nimble_netif_accept_direct(const ble_addr_t *addr,
|
||||
const nimble_netif_accept_cfg_t *cfg);
|
||||
|
||||
/**
|
||||
* @brief Stop accepting incoming connections (stop advertising)
|
||||
* *
|
||||
* @return 0 on success
|
||||
* @return -EALREADY if not currently advertising
|
||||
* @return -EIO on other NimBLE errors
|
||||
*/
|
||||
int nimble_netif_accept_stop(void);
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2019 Freie Universität Berlin
|
||||
* Copyright (C) 2018-2021 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
|
||||
@ -55,6 +55,8 @@
|
||||
#define NIMBLE_NETIF_PRIO GNRC_NETIF_PRIO
|
||||
#endif
|
||||
|
||||
#define EXT_ADV_INST 0
|
||||
|
||||
/* thread flag used for signaling transmit readiness */
|
||||
#define FLAG_TX_UNSTALLED (1u << 13)
|
||||
#define FLAG_TX_NOTCONN (1u << 12)
|
||||
@ -543,10 +545,14 @@ static int _on_gap_slave_evt(struct ble_gap_event *event, void *arg)
|
||||
/* nothing to do here */
|
||||
break;
|
||||
case BLE_GAP_EVENT_ADV_COMPLETE: {
|
||||
uint8_t addr[BLE_ADDR_LEN];
|
||||
nimble_netif_conn_free(handle, addr);
|
||||
_notify(handle, NIMBLE_NETIF_ACCEPT_STOP, addr);
|
||||
if (conn->state == NIMBLE_NETIF_ADV) {
|
||||
uint8_t addr[BLE_ADDR_LEN];
|
||||
nimble_netif_conn_free(handle, addr);
|
||||
_notify(handle, NIMBLE_NETIF_ACCEPT_STOP, addr);
|
||||
}
|
||||
}
|
||||
case BLE_GAP_EVENT_PHY_UPDATE_COMPLETE:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -577,14 +583,10 @@ void nimble_netif_eventcb(nimble_netif_eventcb_t cb)
|
||||
}
|
||||
|
||||
int nimble_netif_connect(const ble_addr_t *addr,
|
||||
struct ble_gap_conn_params *conn_params,
|
||||
uint32_t timeout)
|
||||
const nimble_netif_connect_cfg_t *params)
|
||||
{
|
||||
assert(addr);
|
||||
assert(_eventcb);
|
||||
|
||||
uint16_t itvl_min = 0;
|
||||
uint16_t itvl_max = 0;
|
||||
assert(params);
|
||||
|
||||
/* the netif_conn module expects addresses in network byte order */
|
||||
uint8_t addrn[BLE_ADDR_LEN];
|
||||
@ -602,33 +604,63 @@ int nimble_netif_connect(const ble_addr_t *addr,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if ((conn_params != NULL)
|
||||
&& (conn_params->itvl_min != conn_params->itvl_max)) {
|
||||
/* we need to save the min/max intervals in order to restore them
|
||||
* later on */
|
||||
itvl_min = conn_params->itvl_min;
|
||||
itvl_max = conn_params->itvl_max;
|
||||
|
||||
uint16_t itvl = nimble_netif_conn_gen_itvl(itvl_min, itvl_max);
|
||||
if (itvl == 0) {
|
||||
return -ECANCELED;
|
||||
}
|
||||
conn_params->itvl_min = itvl;
|
||||
conn_params->itvl_max = itvl;
|
||||
/* generate connection interval */
|
||||
uint16_t itvl = params->conn_itvl_min_ms;
|
||||
if (params->conn_itvl_min_ms < params->conn_itvl_max_ms) {
|
||||
itvl = nimble_netif_conn_gen_itvl(params->conn_itvl_min_ms,
|
||||
params->conn_itvl_max_ms);
|
||||
}
|
||||
if (itvl == 0) {
|
||||
nimble_netif_conn_free(handle, NULL);
|
||||
return -ECANCELED;
|
||||
}
|
||||
|
||||
int res = ble_gap_connect(nimble_riot_own_addr_type, addr, timeout,
|
||||
conn_params, _on_gap_master_evt, (void *)handle);
|
||||
assert(res == 0);
|
||||
(void)res;
|
||||
struct ble_gap_conn_params p = {
|
||||
.scan_itvl = BLE_GAP_SCAN_ITVL_MS(params->scan_itvl_ms),
|
||||
.scan_window = BLE_GAP_SCAN_WIN_MS(params->scan_window_ms),
|
||||
.itvl_min = BLE_GAP_CONN_ITVL_MS(itvl),
|
||||
.itvl_max = BLE_GAP_CONN_ITVL_MS(itvl),
|
||||
.latency = params->conn_slave_latency,
|
||||
.supervision_timeout = BLE_GAP_SUPERVISION_TIMEOUT_MS(
|
||||
params->conn_supervision_timeout_ms),
|
||||
.min_ce_len = 0,
|
||||
.max_ce_len = 0,
|
||||
};
|
||||
|
||||
if (itvl_min != itvl_max) {
|
||||
conn_params->itvl_min = itvl_min;
|
||||
conn_params->itvl_max = itvl_max;
|
||||
#if MYNEWT_VAL_BLE_EXT_ADV
|
||||
uint8_t phy_mask;
|
||||
if (params->phy_mode == NIMBLE_PHY_1M) {
|
||||
phy_mask = BLE_GAP_LE_PHY_1M_MASK;
|
||||
}
|
||||
#if IS_USED(MODULE_NIMBLE_PHY_2MBIT)
|
||||
else if (params->phy_mode == NIMBLE_PHY_2M) {
|
||||
phy_mask = (BLE_GAP_LE_PHY_1M_MASK | BLE_GAP_LE_PHY_2M_MASK);
|
||||
}
|
||||
#endif
|
||||
#if IS_USED(MODULE_NIMBLE_PHY_CODED)
|
||||
else if (params->phy_mode == NIMBLE_PHY_CODED) {
|
||||
phy_mask = BLE_GAP_LE_PHY_CODED_MASK;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int res = ble_gap_ext_connect(params->own_addr_type, addr,
|
||||
params->timeout_ms, phy_mask, &p, &p, &p,
|
||||
_on_gap_master_evt, (void *)handle);
|
||||
#else
|
||||
uint32_t timeout = (params->timeout_ms == 0) ? BLE_HS_FOREVER
|
||||
: params->timeout_ms;
|
||||
int res = ble_gap_connect(params->own_addr_type, addr,
|
||||
timeout, &p,
|
||||
_on_gap_master_evt, (void *)handle);
|
||||
#endif
|
||||
if (res != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
_notify(handle, NIMBLE_NETIF_INIT_MASTER, addrn);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
@ -642,63 +674,168 @@ int nimble_netif_close(int handle)
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
int res = ble_gap_terminate(ble_l2cap_get_conn_handle(conn->coc),
|
||||
BLE_ERR_REM_USER_CONN_TERM);
|
||||
assert(res == 0);
|
||||
(void)res;
|
||||
int res = ble_gap_terminate(conn->gaphandle, BLE_ERR_REM_USER_CONN_TERM);
|
||||
if (res != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _accept(const uint8_t *ad, size_t ad_len, const ble_addr_t *addr,
|
||||
uint32_t timeout,
|
||||
const struct ble_gap_adv_params *adv_params)
|
||||
#if MYNEWT_VAL_BLE_EXT_ADV
|
||||
static int _get_phy_hci(uint8_t mode)
|
||||
{
|
||||
assert(adv_params);
|
||||
switch (mode) {
|
||||
case NIMBLE_PHY_1M:
|
||||
return BLE_HCI_LE_PHY_1M;
|
||||
#if IS_USED(MODULE_NIMBLE_PHY_2MBIT)
|
||||
case NIMBLE_PHY_2M:
|
||||
return BLE_HCI_LE_PHY_2M;
|
||||
#endif
|
||||
#if IS_USED(MODULE_NIMBLE_PHY_CODED)
|
||||
case NIMBLE_PHY_CODED:
|
||||
return BLE_HCI_LE_PHY_CODED;
|
||||
#endif
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int _accept(const uint8_t *ad, size_t ad_len, const ble_addr_t *addr,
|
||||
const nimble_netif_accept_cfg_t *params)
|
||||
{
|
||||
int handle;
|
||||
int res;
|
||||
(void)res;
|
||||
|
||||
assert(params);
|
||||
|
||||
/* allocate a connection context for incoming connections */
|
||||
handle = nimble_netif_conn_start_adv();
|
||||
if (handle < 0) {
|
||||
return handle;
|
||||
}
|
||||
|
||||
/* set advertisement data */
|
||||
if (ad != NULL) {
|
||||
res = ble_gap_adv_set_data(ad, (int)ad_len);
|
||||
assert(res == 0);
|
||||
}
|
||||
/* remember address if applicable */
|
||||
if (addr) {
|
||||
nimble_netif_conn_t *conn = nimble_netif_conn_get(handle);
|
||||
bluetil_addr_swapped_cp(addr->val, conn->addr);
|
||||
}
|
||||
|
||||
/* remember context and start advertising */
|
||||
res = ble_gap_adv_start(nimble_riot_own_addr_type, addr, timeout,
|
||||
adv_params, _on_gap_slave_evt, (void *)handle);
|
||||
assert(res == 0);
|
||||
#if MYNEWT_VAL_BLE_EXT_ADV
|
||||
struct ble_gap_ext_adv_params p;
|
||||
memset(&p, 0, sizeof(p));
|
||||
|
||||
/* figure out PHY modes */
|
||||
int phy_pri = _get_phy_hci(params->primary_phy);
|
||||
int phy_sec = _get_phy_hci(params->secondary_phy);
|
||||
if ((phy_pri < 0) || (phy_sec < 0)) {
|
||||
nimble_netif_conn_free(handle, NULL);
|
||||
return -EINVAL;
|
||||
}
|
||||
/* the 2M PHY is not allowed as primary phy, we need to used the 1M PHY
|
||||
* instead. This is for convenience so uses may define 2M as primary PHY */
|
||||
if (phy_pri == BLE_HCI_LE_PHY_2M) {
|
||||
phy_pri = BLE_HCI_LE_PHY_1M;
|
||||
}
|
||||
|
||||
if (addr != NULL) {
|
||||
p.directed = 1;
|
||||
memcpy(&p.peer, addr, sizeof(p.peer));
|
||||
if (params->flags & NIMBLE_NETIF_FLAG_HD_MODE) {
|
||||
p.high_duty_directed = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
p.connectable = 1;
|
||||
}
|
||||
if (params->flags & NIMBLE_NETIF_FLAG_LEGACY) {
|
||||
p.legacy_pdu = 1;
|
||||
/* legacy connectable PDUs are always scannable */
|
||||
p.scannable = 1;
|
||||
}
|
||||
p.itvl_min = BLE_GAP_ADV_ITVL_MS(params->adv_itvl_ms);
|
||||
p.itvl_max = BLE_GAP_ADV_ITVL_MS(params->adv_itvl_ms);
|
||||
p.channel_map = params->channel_map;
|
||||
p.own_addr_type = params->own_addr_type;
|
||||
p.primary_phy = (uint8_t)phy_pri;
|
||||
p.secondary_phy = (uint8_t)phy_sec;
|
||||
p.tx_power = params->tx_power;
|
||||
|
||||
res = ble_gap_ext_adv_configure(EXT_ADV_INST, &p, NULL,
|
||||
_on_gap_slave_evt, (void *)handle);
|
||||
if (res != 0) {
|
||||
nimble_netif_conn_free(handle, NULL);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ad != NULL) {
|
||||
struct os_mbuf *data = os_msys_get_pkthdr(ad_len, 0);
|
||||
if (data == NULL) {
|
||||
nimble_netif_conn_free(handle, NULL);
|
||||
return -ENOMEM;
|
||||
}
|
||||
res = os_mbuf_append(data, ad, ad_len);
|
||||
if (res != 0) {
|
||||
os_mbuf_free_chain(data);
|
||||
nimble_netif_conn_free(handle, NULL);
|
||||
return -ENOMEM;
|
||||
}
|
||||
res = ble_gap_ext_adv_set_data(EXT_ADV_INST, data);
|
||||
assert(res == 0);
|
||||
}
|
||||
res = ble_gap_ext_adv_start(EXT_ADV_INST, params->timeout_ms / 10, 0);
|
||||
#else
|
||||
uint8_t mode = (addr != NULL) ? BLE_GAP_CONN_MODE_DIR
|
||||
: BLE_GAP_CONN_MODE_UND;
|
||||
struct ble_gap_adv_params p = {
|
||||
.conn_mode = mode,
|
||||
.disc_mode = BLE_GAP_DISC_MODE_GEN,
|
||||
.itvl_min = BLE_GAP_ADV_ITVL_MS(params->adv_itvl_ms),
|
||||
.itvl_max = BLE_GAP_ADV_ITVL_MS(params->adv_itvl_ms),
|
||||
.channel_map = params->channel_map,
|
||||
.filter_policy = 0,
|
||||
.high_duty_cycle = (params->flags & NIMBLE_NETIF_FLAG_HD_MODE) ? 1 : 0,
|
||||
};
|
||||
|
||||
/* set advertisement data, if applicable */
|
||||
if (ad != NULL) {
|
||||
res = ble_gap_adv_set_data(ad, (int)ad_len);
|
||||
if (res != 0) {
|
||||
nimble_netif_conn_free(handle, NULL);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* start advertising */
|
||||
uint32_t timeout = (params->timeout_ms == 0) ? BLE_HS_FOREVER
|
||||
: params->timeout_ms;
|
||||
res = ble_gap_adv_start(params->own_addr_type, addr, timeout,
|
||||
&p, _on_gap_slave_evt, (void *)handle);
|
||||
#endif
|
||||
if (res != 0) {
|
||||
nimble_netif_conn_free(handle, NULL);
|
||||
return -ECANCELED;
|
||||
}
|
||||
|
||||
_notify(handle, NIMBLE_NETIF_ACCEPTING, _netif.l2addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nimble_netif_accept(const uint8_t *ad, size_t ad_len,
|
||||
const struct ble_gap_adv_params *adv_params)
|
||||
const nimble_netif_accept_cfg_t *params)
|
||||
{
|
||||
assert(ad != NULL);
|
||||
assert(ad_len > 0);
|
||||
return _accept(ad, ad_len, NULL, BLE_HS_FOREVER, adv_params);
|
||||
return _accept(ad, ad_len, NULL, params);
|
||||
}
|
||||
|
||||
int nimble_netif_accept_direct(const ble_addr_t *addr, uint32_t timeout,
|
||||
const struct ble_gap_adv_params *adv_params)
|
||||
int nimble_netif_accept_direct(const ble_addr_t *addr,
|
||||
const nimble_netif_accept_cfg_t *params)
|
||||
{
|
||||
return _accept(NULL, 0, addr, timeout, adv_params);
|
||||
assert(addr);
|
||||
return _accept(NULL, 0, addr, params);
|
||||
}
|
||||
|
||||
int nimble_netif_accept_stop(void)
|
||||
@ -708,9 +845,15 @@ int nimble_netif_accept_stop(void)
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
int res = ble_gap_adv_stop();
|
||||
assert(res == 0);
|
||||
(void)res;
|
||||
int res;
|
||||
#if MYNEWT_VAL_BLE_EXT_ADV
|
||||
res = ble_gap_ext_adv_stop(EXT_ADV_INST);
|
||||
#else
|
||||
res = ble_gap_adv_stop();
|
||||
#endif
|
||||
if (res != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
nimble_netif_conn_free(handle, NULL);
|
||||
_notify(handle, NIMBLE_NETIF_ACCEPT_STOP, _netif.l2addr);
|
||||
|
||||
|
||||
@ -113,6 +113,7 @@ typedef struct {
|
||||
uint16_t conn_latency; /**< used slave latency for parent connection */
|
||||
uint32_t conn_super_to_ms; /**< used supervision timeout for parent
|
||||
* connection, in ms */
|
||||
nimble_phy_t phy_mode; /**< BLE PHY mode to use */
|
||||
uint32_t eval_itvl_min_ms; /**< amount of time a node searches for
|
||||
* potential parents, lower bound in ms */
|
||||
uint32_t eval_itvl_max_ms; /**< amount of time a node searches for
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Freie Universität Berlin
|
||||
* Copyright (C) 2019-2021 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
|
||||
@ -69,6 +69,13 @@ extern "C" {
|
||||
#define NIMBLE_RPBLE_EVAL_ITVL_MAX_MS 13000U
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Default BLE PHY mode used by rpble
|
||||
*/
|
||||
#ifndef NIMBLE_RPBLE_PHY_MODE
|
||||
#define NIMBLE_RPBLE_PHY_MODE NIMBLE_PHY_1M
|
||||
#endif
|
||||
|
||||
#ifndef NIMBLE_RPBLE_PARAMS
|
||||
#define NIMBLE_RPBLE_PARAMS \
|
||||
{ .scan_itvl_ms = NIMBLE_RPBLE_SCAN_ITVL_MS, \
|
||||
@ -81,6 +88,7 @@ extern "C" {
|
||||
.conn_itvl_max_ms = NIMBLE_RPBLE_CONN_ITVL_MAX_MS, \
|
||||
.conn_latency = NIMBLE_RPBLE_CONN_LATENCY, \
|
||||
.conn_super_to_ms = NIMBLE_RPBLE_CONN_SUPER_TO_MS, \
|
||||
.phy_mode = NIMBLE_RPBLE_PHY_MODE, \
|
||||
.eval_itvl_min_ms = NIMBLE_RPBLE_EVAL_ITVL_MIN_MS, \
|
||||
.eval_itvl_max_ms = NIMBLE_RPBLE_EVAL_ITVL_MAX_MS }
|
||||
#endif
|
||||
|
||||
@ -50,9 +50,8 @@
|
||||
#define POS_FREE_SLOTS 22
|
||||
|
||||
/* keep the timing parameters for connections and advertisements */
|
||||
static struct ble_gap_adv_params _adv_params = { 0 };
|
||||
static struct ble_gap_conn_params _conn_params = { 0 };
|
||||
static uint32_t _conn_scan_to; /* in ms */
|
||||
static nimble_netif_accept_cfg_t _accept_params;
|
||||
static nimble_netif_connect_cfg_t _conn_params;
|
||||
|
||||
/* local RPL context */
|
||||
static nimble_rpble_ctx_t _local_rpl_ctx;
|
||||
@ -107,7 +106,7 @@ static void _children_accept(void)
|
||||
assert(res == BLUETIL_AD_OK);
|
||||
|
||||
/* start advertising this node */
|
||||
res = nimble_netif_accept(ad.buf, ad.pos, &_adv_params);
|
||||
res = nimble_netif_accept(ad.buf, ad.pos, &_accept_params);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
@ -118,10 +117,17 @@ static void _on_scan_evt(uint8_t type, const ble_addr_t *addr,
|
||||
int res;
|
||||
(void)info;
|
||||
|
||||
#if IS_USED(MODULE_NIMBLE_RPBLE_EXT)
|
||||
if ((type != (NIMBLE_SCANNER_EXT_ADV | BLE_HCI_ADV_CONN_MASK)) ||
|
||||
(info->status != BLE_GAP_EXT_ADV_DATA_STATUS_COMPLETE)) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
/* filter out all non-connectible advertisements */
|
||||
if (type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* check if scanned node does actually speak rpble */
|
||||
bluetil_ad_data_t sd_field;
|
||||
@ -199,7 +205,7 @@ static void _parent_connect(struct ble_npl_event *ev)
|
||||
}
|
||||
|
||||
/* try to connect to parent */
|
||||
int res = nimble_netif_connect(&_psel.addr, &_conn_params, _conn_scan_to);
|
||||
int res = nimble_netif_connect(&_psel.addr, &_conn_params);
|
||||
if (res < 0) {
|
||||
_parent_find();
|
||||
return;
|
||||
@ -283,19 +289,36 @@ int nimble_rpble_param_update(const nimble_rpble_cfg_t *cfg)
|
||||
cfg->eval_itvl_max_ms);
|
||||
ble_npl_time_ms_to_ticks(itvl, &_eval_itvl);
|
||||
|
||||
_adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
|
||||
_adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
|
||||
_adv_params.itvl_min = BLE_GAP_ADV_ITVL_MS(cfg->adv_itvl_ms);
|
||||
_adv_params.itvl_max = _adv_params.itvl_min;
|
||||
/* accept parameter extraction */
|
||||
memset(&_accept_params, 0, sizeof(_accept_params));
|
||||
#if IS_USED(MODULE_NIMBLE_RPBLE_EXT)
|
||||
_accept_params.flags = 0;
|
||||
_accept_params.primary_phy = cfg->phy_mode;
|
||||
_accept_params.secondary_phy = cfg->phy_mode;
|
||||
#else
|
||||
_accept_params.flags = NIMBLE_NETIF_FLAG_LEGACY;
|
||||
_accept_params.primary_phy = NIMBLE_PHY_1M;
|
||||
_accept_params.secondary_phy = NIMBLE_PHY_1M;
|
||||
#endif
|
||||
_accept_params.adv_itvl_ms = cfg->adv_itvl_ms;
|
||||
_accept_params.timeout_ms = BLE_HS_FOREVER;
|
||||
_accept_params.own_addr_type = nimble_riot_own_addr_type;
|
||||
|
||||
_conn_params.scan_itvl = BLE_GAP_SCAN_ITVL_MS(cfg->conn_scan_itvl_ms);
|
||||
_conn_params.scan_window = BLE_GAP_SCAN_WIN_MS(cfg->conn_scan_win_ms);
|
||||
_conn_params.latency = cfg->conn_latency;
|
||||
_conn_params.supervision_timeout =
|
||||
BLE_GAP_SUPERVISION_TIMEOUT_MS(cfg->conn_super_to_ms);
|
||||
_conn_params.itvl_min = BLE_GAP_CONN_ITVL_MS(cfg->conn_itvl_min_ms);
|
||||
_conn_params.itvl_max = BLE_GAP_CONN_ITVL_MS(cfg->conn_itvl_max_ms);
|
||||
_conn_scan_to = cfg->conn_scan_to_ms;
|
||||
/* connection parameter extraction */
|
||||
memset(&_conn_params, 0, sizeof(_conn_params));
|
||||
_conn_params.scan_itvl_ms = cfg->conn_scan_itvl_ms;
|
||||
_conn_params.scan_window_ms = cfg->conn_scan_win_ms;
|
||||
_conn_params.conn_itvl_min_ms = cfg->conn_itvl_min_ms;
|
||||
_conn_params.conn_itvl_max_ms = cfg->conn_itvl_max_ms;
|
||||
_conn_params.conn_supervision_timeout_ms = cfg->conn_super_to_ms;
|
||||
_conn_params.conn_slave_latency = cfg->conn_latency;
|
||||
_conn_params.timeout_ms = cfg->conn_scan_to_ms;
|
||||
#if IS_USED(MODULE_NIMBLE_RPBLE_EXT)
|
||||
_conn_params.phy_mode = cfg->phy_mode;
|
||||
#else
|
||||
_conn_params.phy_mode = NIMBLE_PHY_1M;
|
||||
#endif
|
||||
_conn_params.own_addr_type = nimble_riot_own_addr_type;
|
||||
|
||||
/* register event callback */
|
||||
nimble_netif_eventcb(_on_netif_evt);
|
||||
@ -304,9 +327,18 @@ int nimble_rpble_param_update(const nimble_rpble_cfg_t *cfg)
|
||||
nimble_scanner_cfg_t scan_params = { 0 };
|
||||
scan_params.itvl_ms = cfg->scan_itvl_ms;
|
||||
scan_params.win_ms = cfg->scan_win_ms;
|
||||
scan_params.flags = NIMBLE_SCANNER_PASSIVE
|
||||
| NIMBLE_SCANNER_FILTER_DUPS
|
||||
| NIMBLE_SCANNER_PHY_1M;
|
||||
scan_params.flags = (NIMBLE_SCANNER_PASSIVE | NIMBLE_SCANNER_FILTER_DUPS);
|
||||
|
||||
#if IS_USED(MODULE_NIMBLE_RPBLE_EXT) && IS_USED(MODULE_NIMBLE_PHY_CODED)
|
||||
if (cfg->phy_mode == NIMBLE_PHY_CODED) {
|
||||
scan_params.flags |= NIMBLE_SCANNER_PHY_CODED;
|
||||
}
|
||||
else {
|
||||
scan_params.flags |= NIMBLE_SCANNER_PHY_1M;
|
||||
}
|
||||
#else
|
||||
scan_params.flags |= NIMBLE_SCANNER_PHY_1M;
|
||||
#endif
|
||||
nimble_scanner_init(&scan_params, _on_scan_evt);
|
||||
|
||||
/* start to look for parents */
|
||||
|
||||
@ -44,7 +44,9 @@ enum {
|
||||
NIMBLE_SCANNER_LIMITED = 0x02, /**< do limited discovery */
|
||||
NIMBLE_SCANNER_FILTER_DUPS = 0x04, /**< filter duplicates */
|
||||
NIMBLE_SCANNER_PHY_1M = 0x10, /**< scan on 1Mbit PHY */
|
||||
#if IS_USED(MODULE_NIMBLE_PHY_CODED)
|
||||
NIMBLE_SCANNER_PHY_CODED = 0x20, /**< scan on CODED PHY */
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -100,9 +100,12 @@ int nimble_scanner_start(void)
|
||||
uint8_t limited = (_scan_flags & NIMBLE_SCANNER_LIMITED) ? 1 : 0;
|
||||
const struct ble_gap_ext_disc_params *uncoded =
|
||||
(_scan_flags & NIMBLE_SCANNER_PHY_1M) ? &_scan_params : NULL;
|
||||
#if IS_USED(MODULE_NIMBLE_PHY_CODED)
|
||||
const struct ble_gap_ext_disc_params *coded =
|
||||
(_scan_flags & NIMBLE_SCANNER_PHY_CODED) ? &_scan_params : NULL;
|
||||
|
||||
#else
|
||||
const struct ble_gap_ext_disc_params *coded = NULL;
|
||||
#endif
|
||||
int32_t dur = (_scan_duration == BLE_HS_FOREVER) ? 0
|
||||
: _scan_duration / 10;
|
||||
|
||||
|
||||
@ -113,6 +113,21 @@ extern "C" {
|
||||
#define NIMBLE_STATCONN_CONN_SUPERTO_MS (2500U)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief BLE PHY mode used by statconn. This value is only used if statconn
|
||||
* is used in its extended mode (module `nimble_statconn_ext`)
|
||||
*/
|
||||
#ifndef NIMBLE_STATCONN_PHY_MODE
|
||||
#define NIMBLE_STATCONN_PHY_MODE NIMBLE_PHY_1M
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Statconn connection parameters
|
||||
*/
|
||||
typedef struct {
|
||||
nimble_phy_t phy_mode; /**< BLE PHY mode used for the connection */
|
||||
} nimble_statconn_cfg_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize the statconn module
|
||||
*
|
||||
@ -138,23 +153,31 @@ void nimble_statconn_eventcb(nimble_netif_eventcb_t cb);
|
||||
* connection by that master.
|
||||
*
|
||||
* @param[in] addr BLE address of the peer
|
||||
* @param[in] cfg additional connection parameters, set to NULL to apply
|
||||
* default values
|
||||
*
|
||||
* @return 0 if peer was successfully added
|
||||
* @return -EALREADY if the peer address is already in use
|
||||
* @return -ENOMEM if no empty connection slot is available
|
||||
* @return -EINVAL if invalid configuration parameters are given
|
||||
*/
|
||||
int nimble_statconn_add_master(const uint8_t *addr);
|
||||
int nimble_statconn_add_master(const uint8_t *addr,
|
||||
const nimble_statconn_cfg_t *cfg);
|
||||
|
||||
/**
|
||||
* @brief Connect to a peer (slave) with a given address as master
|
||||
*
|
||||
* @param[in] addr BLE address of the peer
|
||||
* @param[in] cfg additional connection parameters, set to NULL to apply
|
||||
* default values
|
||||
*
|
||||
* @return 0 if peer was successfully added
|
||||
* @return -EALREADY if the peer address is already in use
|
||||
* @return -ENOMEM if no empty connection slot is available
|
||||
* @return -EINVAL if invalid configuration parameters are given
|
||||
*/
|
||||
int nimble_statconn_add_slave(const uint8_t *addr);
|
||||
int nimble_statconn_add_slave(const uint8_t *addr,
|
||||
const nimble_statconn_cfg_t *cfg);
|
||||
|
||||
/**
|
||||
* @brief Remove the connection to the given peer
|
||||
|
||||
@ -44,6 +44,9 @@
|
||||
typedef struct {
|
||||
uint8_t addr[BLE_ADDR_LEN]; /**< peer addr, network byte order */
|
||||
uint8_t state; /**< internal state */
|
||||
#if IS_USED(MODULE_NIMBLE_STATCONN_EXT)
|
||||
nimble_phy_t phy_mode; /**< PHY mode used by this slot */
|
||||
#endif
|
||||
} slot_t;
|
||||
|
||||
static const uint8_t _ad[2] = { BLE_GAP_AD_FLAGS, BLUETIL_AD_FLAGS_DEFAULT };
|
||||
@ -51,9 +54,8 @@ static const uint8_t _ad[2] = { BLE_GAP_AD_FLAGS, BLUETIL_AD_FLAGS_DEFAULT };
|
||||
static mutex_t _lock = MUTEX_INIT;
|
||||
static slot_t _slots[NIMBLE_NETIF_MAX_CONN];
|
||||
|
||||
static struct ble_gap_adv_params _adv_params;
|
||||
static struct ble_gap_conn_params _conn_params;
|
||||
static uint32_t _conn_timeout;
|
||||
static nimble_netif_accept_cfg_t _accept_params;
|
||||
static nimble_netif_connect_cfg_t _conn_params;
|
||||
|
||||
static nimble_netif_eventcb_t _eventcb = NULL;
|
||||
|
||||
@ -87,10 +89,17 @@ static void _activate(uint8_t role)
|
||||
peer.type = BLE_ADDR_RANDOM;
|
||||
bluetil_addr_swapped_cp(slot->addr, peer.val);
|
||||
/* try to (re)open the connection */
|
||||
nimble_netif_connect(&peer, &_conn_params, _conn_timeout);
|
||||
#if IS_USED(MODULE_NIMBLE_STATCONN_EXT)
|
||||
_conn_params.phy_mode = slot->phy_mode;
|
||||
#endif
|
||||
nimble_netif_connect(&peer, &_conn_params);
|
||||
}
|
||||
else if (slot && (role == ROLE_S)) {
|
||||
nimble_netif_accept(_ad, sizeof(_ad), &_adv_params);
|
||||
#if IS_USED(MODULE_NIMBLE_STATCONN_EXT)
|
||||
_accept_params.primary_phy = slot->phy_mode;
|
||||
_accept_params.secondary_phy = slot->phy_mode;
|
||||
#endif
|
||||
nimble_netif_accept(_ad, sizeof(_ad), &_accept_params);
|
||||
}
|
||||
mutex_unlock(&_lock);
|
||||
}
|
||||
@ -153,7 +162,8 @@ static void _on_netif_evt(int handle, nimble_netif_event_t event,
|
||||
}
|
||||
}
|
||||
|
||||
static int _be(uint8_t role, const uint8_t *addr)
|
||||
static int _be(uint8_t role, const uint8_t *addr,
|
||||
const nimble_statconn_cfg_t *cfg)
|
||||
{
|
||||
mutex_lock(&_lock);
|
||||
slot_t *s = _get_addr(addr);
|
||||
@ -170,6 +180,18 @@ static int _be(uint8_t role, const uint8_t *addr)
|
||||
s->state = (role | PENDING);
|
||||
memcpy(s->addr, addr, BLE_ADDR_LEN);
|
||||
mutex_unlock(&_lock);
|
||||
|
||||
#if IS_USED(MODULE_NIMBLE_STATCONN_EXT)
|
||||
if (cfg != NULL) {
|
||||
s->phy_mode = cfg->phy_mode;
|
||||
}
|
||||
else {
|
||||
s->phy_mode = NIMBLE_STATCONN_PHY_MODE;
|
||||
}
|
||||
#else
|
||||
(void)cfg;
|
||||
#endif
|
||||
|
||||
_activate(role);
|
||||
return 0;
|
||||
}
|
||||
@ -179,27 +201,31 @@ void nimble_statconn_init(void)
|
||||
memset(_slots, 0, sizeof(_slots));
|
||||
|
||||
/* 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 = BLE_GAP_ADV_ITVL_MS(NIMBLE_STATCONN_ADV_ITVL_MS);
|
||||
_adv_params.itvl_max = _adv_params.itvl_min;
|
||||
_adv_params.channel_map = 0;
|
||||
_adv_params.filter_policy = 0;
|
||||
_adv_params.high_duty_cycle = 0;
|
||||
memset(&_accept_params, 0, sizeof(_accept_params));
|
||||
#if IS_USED(MODULE_NIMBLE_STATCONN_EXT)
|
||||
_accept_params.flags = 0;
|
||||
#else
|
||||
_accept_params.flags = NIMBLE_NETIF_FLAG_LEGACY;
|
||||
_accept_params.primary_phy = NIMBLE_PHY_1M;
|
||||
_accept_params.secondary_phy = NIMBLE_PHY_1M;
|
||||
#endif
|
||||
_accept_params.adv_itvl_ms = NIMBLE_STATCONN_ADV_ITVL_MS;
|
||||
_accept_params.timeout_ms = BLE_HS_FOREVER;
|
||||
_accept_params.own_addr_type = nimble_riot_own_addr_type;
|
||||
|
||||
/* set connection parameters */
|
||||
_conn_params.scan_itvl = BLE_GAP_SCAN_ITVL_MS(NIMBLE_STATCONN_CONN_WIN_MS);
|
||||
_conn_params.scan_window = _conn_params.scan_itvl;
|
||||
_conn_params.latency = NIMBLE_STATCONN_CONN_LATENCY;
|
||||
_conn_params.supervision_timeout = BLE_GAP_SUPERVISION_TIMEOUT_MS(
|
||||
NIMBLE_STATCONN_CONN_SUPERTO_MS);
|
||||
_conn_params.itvl_min = BLE_GAP_CONN_ITVL_MS(
|
||||
NIMBLE_STATCONN_CONN_ITVL_MIN_MS);
|
||||
_conn_params.itvl_max = BLE_GAP_CONN_ITVL_MS(
|
||||
NIMBLE_STATCONN_CONN_ITVL_MAX_MS);
|
||||
_conn_params.min_ce_len = 0;
|
||||
_conn_params.max_ce_len = 0;
|
||||
_conn_timeout = NIMBLE_STATCONN_CONN_TIMEOUT_MS;
|
||||
memset(&_conn_params, 0, sizeof(_conn_params));
|
||||
#if !IS_USED(MODULE_NIMBLE_AUTOCONN_EXT)
|
||||
_conn_params.phy_mode = NIMBLE_PHY_1M;
|
||||
#endif
|
||||
_conn_params.scan_itvl_ms = NIMBLE_STATCONN_CONN_WIN_MS;
|
||||
_conn_params.scan_window_ms = NIMBLE_STATCONN_CONN_WIN_MS;
|
||||
_conn_params.conn_itvl_min_ms = NIMBLE_STATCONN_CONN_ITVL_MIN_MS;
|
||||
_conn_params.conn_itvl_max_ms = NIMBLE_STATCONN_CONN_ITVL_MAX_MS;
|
||||
_conn_params.conn_supervision_timeout_ms = NIMBLE_STATCONN_CONN_SUPERTO_MS;
|
||||
_conn_params.conn_slave_latency = NIMBLE_STATCONN_CONN_LATENCY;
|
||||
_conn_params.timeout_ms = NIMBLE_STATCONN_CONN_TIMEOUT_MS;
|
||||
_conn_params.own_addr_type = nimble_riot_own_addr_type;
|
||||
|
||||
/* register our event callback */
|
||||
nimble_netif_eventcb(_on_netif_evt);
|
||||
@ -210,14 +236,16 @@ void nimble_statconn_eventcb(nimble_netif_eventcb_t cb)
|
||||
_eventcb = cb;
|
||||
}
|
||||
|
||||
int nimble_statconn_add_master(const uint8_t *addr)
|
||||
int nimble_statconn_add_master(const uint8_t *addr,
|
||||
const nimble_statconn_cfg_t *cfg)
|
||||
{
|
||||
return _be(ROLE_S, addr);
|
||||
return _be(ROLE_S, addr, cfg);
|
||||
}
|
||||
|
||||
int nimble_statconn_add_slave(const uint8_t *addr)
|
||||
int nimble_statconn_add_slave(const uint8_t *addr,
|
||||
const nimble_statconn_cfg_t *cfg)
|
||||
{
|
||||
return _be(ROLE_M, addr);
|
||||
return _be(ROLE_M, addr, cfg);
|
||||
}
|
||||
|
||||
int nimble_statconn_rm(const uint8_t *addr)
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "fmt.h"
|
||||
#include "ztimer.h"
|
||||
@ -30,17 +31,37 @@
|
||||
#include "net/bluetil/ad.h"
|
||||
#include "net/bluetil/addr.h"
|
||||
|
||||
#if !IS_USED(MODULE_NIMBLE_AUTOCONN) && !IS_USED(MODULE_NIMBLE_STATCONN)
|
||||
#define FULL_CONTROL !IS_USED(MODULE_NIMBLE_AUTOCONN) && \
|
||||
!IS_USED(MODULE_NIMBLE_STATCONN) && \
|
||||
!IS_USED(MODULE_NIMBLE_RPBLE)
|
||||
|
||||
#if FULL_CONTROL
|
||||
#include "nimble_scanlist.h"
|
||||
#include "nimble_scanner.h"
|
||||
#endif
|
||||
|
||||
#define DEFAULT_NODE_NAME "bleRIOT"
|
||||
#define DEFAULT_SCAN_DURATION (500U) /* 500ms */
|
||||
#define DEFAULT_CONN_TIMEOUT (500U) /* 500ms */
|
||||
#define DEFAULT_SCAN_DURATION_MS 500U
|
||||
#define DEFAULT_CONN_TIMEOUT_MS 500U
|
||||
#define DEFAULT_SCAN_ITVL_MS 100U
|
||||
#define DEFAULT_CONN_ITVL_MS 75U
|
||||
#define DEFAULT_TX_POWER 0 /* 0dBm */
|
||||
#define DEFAULT_ADV_ITVL_MS 75U
|
||||
|
||||
#if !IS_USED(MODULE_NIMBLE_AUTOCONN) && !IS_USED(MODULE_NIMBLE_STATCONN)
|
||||
static const char *_phystr[] = { "N/A", "1M", "2M", "CODED" };
|
||||
|
||||
#if FULL_CONTROL
|
||||
static const char *_name_to_connect = NULL;
|
||||
static nimble_netif_connect_cfg_t _connect_params = {
|
||||
.scan_itvl_ms = DEFAULT_SCAN_ITVL_MS,
|
||||
.scan_window_ms = DEFAULT_SCAN_ITVL_MS,
|
||||
.conn_itvl_min_ms = DEFAULT_CONN_ITVL_MS,
|
||||
.conn_itvl_max_ms = DEFAULT_CONN_ITVL_MS,
|
||||
.conn_supervision_timeout_ms = DEFAULT_CONN_ITVL_MS * 20,
|
||||
.conn_slave_latency = 0,
|
||||
.timeout_ms = 0, /* will be filled later */
|
||||
.phy_mode = 0, /* will be filled later */
|
||||
.own_addr_type = 0 /* will be filled later */,
|
||||
};
|
||||
|
||||
static void _scan_for_name(uint8_t type, const ble_addr_t *addr,
|
||||
const nimble_scanner_info_t *info,
|
||||
@ -56,7 +77,7 @@ static void _scan_for_name(uint8_t type, const ble_addr_t *addr,
|
||||
_name_to_connect, strlen(_name_to_connect));
|
||||
if (res) {
|
||||
nimble_scanner_stop();
|
||||
nimble_netif_connect(addr, NULL, DEFAULT_CONN_TIMEOUT);
|
||||
nimble_netif_connect(addr, &_connect_params);
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,12 +111,34 @@ static void _on_ble_evt(int handle, nimble_netif_event_t event,
|
||||
case NIMBLE_NETIF_ABORT_SLAVE:
|
||||
_print_evt("CONNECTION ABORT", handle, addr);
|
||||
break;
|
||||
case NIMBLE_NETIF_ACCEPT_STOP:
|
||||
_print_evt("ACCEPT STOP", handle, addr);
|
||||
case NIMBLE_NETIF_CONN_UPDATED:
|
||||
default:
|
||||
/* do nothing */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t _parsephy(const char *phy_str)
|
||||
{
|
||||
if (memcmp(phy_str, "1M", 2) == 0) {
|
||||
return NIMBLE_PHY_1M;
|
||||
}
|
||||
#if IS_ACTIVE(MODULE_NIMBLE_PHY_2MBIT)
|
||||
else if (memcmp(phy_str, "2M", 2) == 0) {
|
||||
return NIMBLE_PHY_2M;
|
||||
}
|
||||
#endif
|
||||
#if IS_ACTIVE(MODULE_NIMBLE_PHY_CODED)
|
||||
else if (memcmp(phy_str, "CODED", 5) == 0) {
|
||||
return NIMBLE_PHY_CODED;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
return NIMBLE_PHY_INVALID;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int _conn_dump(nimble_netif_conn_t *conn, int handle, void *arg)
|
||||
@ -117,8 +160,20 @@ static int _conn_dump(nimble_netif_conn_t *conn, int handle, void *arg)
|
||||
printf(" ");
|
||||
bluetil_addr_ipv6_l2ll_print(conn->addr);
|
||||
#endif
|
||||
printf(" (%c,%ums,%ums,%i)", role, itvl, sto, (int)desc.conn_latency);
|
||||
puts("");
|
||||
|
||||
#if IS_USED(MODULE_NIMBLE_NETIF_EXT)
|
||||
uint8_t phy_rx, phy_tx;
|
||||
(void)phy_tx;
|
||||
res = ble_gap_read_le_phy(conn->gaphandle, &phy_tx, &phy_rx);
|
||||
if (res != 0) {
|
||||
phy_rx = 1;
|
||||
}
|
||||
#else
|
||||
/* when not using extended advertisements we always use the 1M phy mode */
|
||||
uint8_t phy_rx = 1;
|
||||
#endif
|
||||
printf(" (%c,%ums,%ums,%i,%s)\n",
|
||||
role, itvl, sto, (int)desc.conn_latency, _phystr[phy_rx]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -159,7 +214,7 @@ static void _conn_list(void)
|
||||
if (active > 0) {
|
||||
nimble_netif_conn_foreach(NIMBLE_NETIF_L2CAP_CONNECTED,
|
||||
_conn_dump, NULL);
|
||||
puts(" (role, conn itvl, superv. timeout, slave latency)");
|
||||
puts(" (role, conn itvl, superv. timeout, slave latency, PHY)");
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,6 +234,15 @@ static void _cmd_info(void)
|
||||
#endif
|
||||
puts("");
|
||||
|
||||
printf("Supported PHY modes: 1M");
|
||||
#if IS_USED(MODULE_NIMBLE_PHY_2MBIT)
|
||||
printf(" 2M");
|
||||
#endif
|
||||
#if IS_USED(MODULE_NIMBLE_PHY_CODED)
|
||||
printf(" CODED");
|
||||
#endif
|
||||
puts("");
|
||||
|
||||
printf(" Free slots: %u/%u\n", free, NIMBLE_NETIF_MAX_CONN);
|
||||
printf("Advertising: ");
|
||||
if (nimble_netif_conn_get_adv() != NIMBLE_NETIF_CONN_INVALID) {
|
||||
@ -196,99 +260,107 @@ static void _cmd_info(void)
|
||||
puts("");
|
||||
}
|
||||
|
||||
#if !IS_USED(MODULE_NIMBLE_AUTOCONN) && !IS_USED(MODULE_NIMBLE_STATCONN)
|
||||
static void _cmd_adv(const char *name)
|
||||
#if FULL_CONTROL
|
||||
static int _cmd_adv(int argc, char **argv, bool legacy)
|
||||
{
|
||||
int res;
|
||||
(void)res;
|
||||
uint8_t buf[BLE_HS_ADV_MAX_SZ];
|
||||
bluetil_ad_t ad;
|
||||
const struct ble_gap_adv_params _adv_params = {
|
||||
.conn_mode = BLE_GAP_CONN_MODE_UND,
|
||||
.disc_mode = BLE_GAP_DISC_MODE_LTD,
|
||||
.itvl_min = BLE_GAP_ADV_FAST_INTERVAL2_MIN,
|
||||
.itvl_max = BLE_GAP_ADV_FAST_INTERVAL2_MAX,
|
||||
};
|
||||
const char *name = NULL;
|
||||
uint8_t addrn[BLE_ADDR_LEN];
|
||||
ble_addr_t addr = { .type = nimble_riot_own_addr_type };
|
||||
|
||||
/* stop sub-command: stop advertising */
|
||||
if (memcmp(argv[2], "stop", 4) == 0) {
|
||||
res = nimble_netif_accept_stop();
|
||||
if (res == 0) {
|
||||
puts("advertising stopped");
|
||||
}
|
||||
else if (res == -EALREADY) {
|
||||
puts("no advertising in progress");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* make sure no advertising is in progress */
|
||||
if (nimble_netif_conn_is_adv()) {
|
||||
puts("err: advertising already in progress");
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* build advertising data */
|
||||
res = bluetil_ad_init_with_flags(&ad, buf, BLE_HS_ADV_MAX_SZ,
|
||||
BLUETIL_AD_FLAGS_DEFAULT);
|
||||
assert(res == BLUETIL_AD_OK);
|
||||
uint16_t ipss = BLE_GATT_SVC_IPSS;
|
||||
res = bluetil_ad_add(&ad, BLE_GAP_AD_UUID16_INCOMP, &ipss, sizeof(ipss));
|
||||
assert(res == BLUETIL_AD_OK);
|
||||
if (name == NULL) {
|
||||
name = DEFAULT_NODE_NAME;
|
||||
/* try if first parameter is a BLE address, if so, use directed
|
||||
* advertisement */
|
||||
if (bluetil_addr_from_str(addrn, argv[2]) != NULL) {
|
||||
/* NimBLE expects address in little endian, so swap */
|
||||
bluetil_addr_swapped_cp(addrn, addr.val);
|
||||
puts("Found BLE address: sending directed advertisements");
|
||||
}
|
||||
res = bluetil_ad_add(&ad, BLE_GAP_AD_NAME, name, strlen(name));
|
||||
if (res != BLUETIL_AD_OK) {
|
||||
puts("err: the given name is too long");
|
||||
return;
|
||||
else {
|
||||
name = argv[2];
|
||||
}
|
||||
|
||||
uint32_t timeout = 0;
|
||||
if (argc >= 4) {
|
||||
timeout = (uint32_t)atoi(argv[3]);
|
||||
}
|
||||
|
||||
uint8_t phy_sec = BLE_GAP_LE_PHY_1M;
|
||||
if (argc >= 5) {
|
||||
phy_sec = _parsephy(argv[4]);
|
||||
if (phy_sec == 0) {
|
||||
puts("err: PHY mode not supported\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
uint8_t phy_pri = (phy_sec == BLE_HCI_LE_PHY_2M) ? BLE_HCI_LE_PHY_1M
|
||||
: phy_sec;
|
||||
|
||||
nimble_netif_accept_cfg_t p = {
|
||||
.flags = (legacy) ? NIMBLE_NETIF_FLAG_LEGACY : 0,
|
||||
.adv_itvl_ms = DEFAULT_ADV_ITVL_MS,
|
||||
.primary_phy = phy_pri,
|
||||
.secondary_phy = phy_sec,
|
||||
.tx_power = DEFAULT_TX_POWER,
|
||||
.channel_map = 0,
|
||||
.timeout_ms = timeout,
|
||||
.own_addr_type = nimble_riot_own_addr_type,
|
||||
};
|
||||
|
||||
if (name != NULL) {
|
||||
uint8_t buf[BLE_HS_ADV_MAX_SZ];
|
||||
bluetil_ad_t ad;
|
||||
/* build advertising data */
|
||||
res = bluetil_ad_init_with_flags(&ad, buf, BLE_HS_ADV_MAX_SZ,
|
||||
BLUETIL_AD_FLAGS_DEFAULT);
|
||||
assert(res == BLUETIL_AD_OK);
|
||||
uint16_t ipss = BLE_GATT_SVC_IPSS;
|
||||
res = bluetil_ad_add(&ad, BLE_GAP_AD_UUID16_INCOMP, &ipss, sizeof(ipss));
|
||||
assert(res == BLUETIL_AD_OK);
|
||||
res = bluetil_ad_add(&ad, BLE_GAP_AD_NAME, name, strlen(name));
|
||||
if (res != BLUETIL_AD_OK) {
|
||||
puts("err: the given name is too long");
|
||||
return 1;
|
||||
}
|
||||
|
||||
res = nimble_netif_accept(ad.buf, ad.pos, &p);
|
||||
}
|
||||
else {
|
||||
res = nimble_netif_accept_direct(&addr, &p);
|
||||
}
|
||||
|
||||
/* start listening for incoming connections */
|
||||
res = nimble_netif_accept(ad.buf, ad.pos, &_adv_params);
|
||||
if (res != 0) {
|
||||
printf("err: unable to start advertising (%i)\n", res);
|
||||
}
|
||||
else {
|
||||
printf("success: advertising this node as '%s'\n", name);
|
||||
}
|
||||
}
|
||||
|
||||
static void _cmd_adv_direct(const char *addr_str)
|
||||
{
|
||||
int res;
|
||||
(void)res;
|
||||
uint8_t addrn[BLE_ADDR_LEN];
|
||||
ble_addr_t addr;
|
||||
const struct ble_gap_adv_params _adv_params = {
|
||||
.conn_mode = BLE_GAP_CONN_MODE_DIR,
|
||||
.disc_mode = BLE_GAP_DISC_MODE_GEN,
|
||||
.itvl_min = BLE_GAP_ADV_FAST_INTERVAL2_MIN,
|
||||
.itvl_max = BLE_GAP_ADV_FAST_INTERVAL2_MAX,
|
||||
};
|
||||
|
||||
/* make sure no advertising is in progress */
|
||||
if (nimble_netif_conn_is_adv()) {
|
||||
puts("err: advertising already in progress");
|
||||
return;
|
||||
}
|
||||
|
||||
/* parse and convert address -> RIOT uses big endian notation, NimBLE
|
||||
* expects little endian... */
|
||||
if (bluetil_addr_from_str(addrn, addr_str) == NULL) {
|
||||
puts("err: unable to parse BLE address");
|
||||
return;
|
||||
}
|
||||
addr.type = nimble_riot_own_addr_type;
|
||||
bluetil_addr_swapped_cp(addrn, addr.val);
|
||||
|
||||
/* start advertising directed advertising with the given BLE address */
|
||||
res = nimble_netif_accept_direct(&addr, BLE_HS_FOREVER, &_adv_params);
|
||||
if (res != 0) {
|
||||
printf("err: unable to start directed advertising (%i)\n", res);
|
||||
}
|
||||
else {
|
||||
puts("success: started to send directed advertisements");
|
||||
}
|
||||
}
|
||||
|
||||
static void _cmd_adv_stop(void)
|
||||
{
|
||||
int res = nimble_netif_accept_stop();
|
||||
if (res == 0) {
|
||||
puts("canceled advertising");
|
||||
}
|
||||
else {
|
||||
puts("no advertising in progress");
|
||||
if (name != NULL) {
|
||||
printf("success: advertising this node as '%s'\n", name);
|
||||
}
|
||||
else {
|
||||
printf("success: sending direct advertisements to ");
|
||||
bluetil_addr_print(addrn);
|
||||
puts("");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _do_scan(nimble_scanner_cb cb, unsigned duration)
|
||||
@ -301,7 +373,19 @@ static void _do_scan(nimble_scanner_cb cb, unsigned duration)
|
||||
printf("err: scanner already active\n");
|
||||
return;
|
||||
}
|
||||
nimble_scanner_init(NULL, cb);
|
||||
|
||||
nimble_scanner_cfg_t p = {
|
||||
.itvl_ms = DEFAULT_SCAN_ITVL_MS,
|
||||
.win_ms = DEFAULT_SCAN_ITVL_MS,
|
||||
#if IS_USED(MODULE_NIMBLE_PHY_CODED)
|
||||
.flags = (NIMBLE_SCANNER_PASSIVE | NIMBLE_SCANNER_PHY_1M |
|
||||
NIMBLE_SCANNER_PHY_CODED),
|
||||
#else
|
||||
.flags = (NIMBLE_SCANNER_PASSIVE | NIMBLE_SCANNER_PHY_1M),
|
||||
#endif
|
||||
};
|
||||
|
||||
nimble_scanner_init(&p, cb);
|
||||
nimble_scanlist_clear();
|
||||
nimble_scanner_start();
|
||||
ztimer_sleep(ZTIMER_MSEC, duration);
|
||||
@ -316,58 +400,73 @@ static void _cmd_scan(unsigned duration)
|
||||
nimble_scanlist_print();
|
||||
}
|
||||
|
||||
static void _cmd_connect_addr(ble_addr_t *addr)
|
||||
static void _cmd_connect(int argc, char **argv)
|
||||
{
|
||||
/* simply use NimBLEs default connection parameters */
|
||||
int res = nimble_netif_connect(addr, NULL, DEFAULT_CONN_TIMEOUT);
|
||||
if (res < 0) {
|
||||
printf("err: unable to trigger connection sequence (%i)\n", res);
|
||||
return;
|
||||
}
|
||||
ble_addr_t addr;
|
||||
int proceed = 0;
|
||||
|
||||
printf("initiated connection procedure with ");
|
||||
/* populate connection parameters */
|
||||
_connect_params.timeout_ms = DEFAULT_CONN_TIMEOUT_MS;
|
||||
if (argc >= 4) {
|
||||
_connect_params.timeout_ms = (uint32_t)atoi(argv[3]);
|
||||
}
|
||||
_connect_params.phy_mode = NIMBLE_PHY_1M;
|
||||
if (argc >= 5) {
|
||||
_connect_params.phy_mode = _parsephy(argv[4]);
|
||||
if (_connect_params.phy_mode == 0) {
|
||||
puts("err: PHY mode not supported\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
_connect_params.own_addr_type = nimble_riot_own_addr_type;
|
||||
|
||||
/* try to parse address directly */
|
||||
uint8_t addrn[BLE_ADDR_LEN];
|
||||
bluetil_addr_swapped_cp(addr->val, addrn);
|
||||
bluetil_addr_print(addrn);
|
||||
puts("");
|
||||
|
||||
}
|
||||
|
||||
static void _cmd_connect_addr_raw(const uint8_t *addr_in)
|
||||
{
|
||||
/* RANDOM is the most common type, has no noticeable effect when connecting
|
||||
anyhow... */
|
||||
ble_addr_t addr = { .type = BLE_ADDR_RANDOM };
|
||||
/* NimBLE expects address in little endian, so swap */
|
||||
bluetil_addr_swapped_cp(addr_in, addr.val);
|
||||
_cmd_connect_addr(&addr);
|
||||
}
|
||||
|
||||
static void _cmd_connect_name(const char *name, unsigned duration)
|
||||
{
|
||||
if (_name_to_connect != NULL) {
|
||||
printf("err: already trying to connect to '%s'\n", _name_to_connect);
|
||||
if (bluetil_addr_from_str(addrn, argv[2]) != NULL) {
|
||||
addr.type = nimble_riot_own_addr_type;
|
||||
/* NimBLE expects address in little endian, so swap */
|
||||
bluetil_addr_swapped_cp(addrn, addr.val);
|
||||
proceed = 1;
|
||||
}
|
||||
/* try if param is a number, if so use it as scanlist entry number */
|
||||
else if (fmt_is_number(argv[2])) {
|
||||
unsigned pos = atoi(argv[2]);
|
||||
nimble_scanlist_entry_t *sle = nimble_scanlist_get_by_pos(pos);
|
||||
if (sle == NULL) {
|
||||
puts("err: unable to find given entry in scanlist");
|
||||
return;
|
||||
}
|
||||
_connect_params.phy_mode = sle->phy_sec;
|
||||
memcpy(&addr, &sle->addr, sizeof(addr));
|
||||
proceed = 1;
|
||||
}
|
||||
/* else interpret value as name and search for that peer */
|
||||
else {
|
||||
unsigned duration = DEFAULT_SCAN_DURATION_MS;
|
||||
if (argc > 3) {
|
||||
duration = atoi(argv[3]);
|
||||
}
|
||||
_name_to_connect = argv[2];
|
||||
printf("trying to find and connect to a node with name '%s'\n", argv[2]);
|
||||
_do_scan(_scan_for_name, duration);
|
||||
if (_name_to_connect != NULL) {
|
||||
printf("fail: unable to connect to '%s'\n", _name_to_connect);
|
||||
_name_to_connect = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
_name_to_connect = name;
|
||||
printf("trying to find and connect to a node with name '%s'\n", name);
|
||||
_do_scan(_scan_for_name, duration);
|
||||
if (_name_to_connect != NULL) {
|
||||
printf("fail: unable to connect to '%s'\n", _name_to_connect);
|
||||
_name_to_connect = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void _cmd_connect_scanlist(unsigned pos)
|
||||
{
|
||||
nimble_scanlist_entry_t *sle = nimble_scanlist_get_by_pos(pos);
|
||||
if (sle == NULL) {
|
||||
puts("err: unable to find given entry in scanlist");
|
||||
return;
|
||||
if (proceed == 1) {
|
||||
int res = nimble_netif_connect(&addr, &_connect_params);
|
||||
if (res == 0) {
|
||||
puts("Successfully connected 123");
|
||||
}
|
||||
else {
|
||||
puts("err: unable to connect");
|
||||
}
|
||||
}
|
||||
_cmd_connect_addr(&sle->addr);
|
||||
}
|
||||
#endif /* MODULE_NIMBLE_AUTOCONN */
|
||||
#endif
|
||||
|
||||
static void _cmd_close(int handle)
|
||||
{
|
||||
@ -406,7 +505,7 @@ static int _ishelp(char *argv)
|
||||
|
||||
void sc_nimble_netif_init(void)
|
||||
{
|
||||
#if !IS_USED(MODULE_NIMBLE_AUTOCONN) && !IS_USED(MODULE_NIMBLE_STATCONN)
|
||||
#if FULL_CONTROL
|
||||
/* setup the scanning environment */
|
||||
nimble_scanlist_init();
|
||||
|
||||
@ -418,8 +517,9 @@ void sc_nimble_netif_init(void)
|
||||
int _nimble_netif_handler(int argc, char **argv)
|
||||
{
|
||||
if ((argc == 1) || _ishelp(argv[1])) {
|
||||
#if !IS_USED(MODULE_NIMBLE_AUTOCONN) && !IS_USED(MODULE_NIMBLE_STATCONN)
|
||||
printf("usage: %s [help|info|adv|scan|connect|close|update|chanmap]\n", argv[0]);
|
||||
#if FULL_CONTROL
|
||||
printf("usage: %s [help|info|adv|adv_ext|adv_dir|"
|
||||
"scan|connect|close|update|chanmap]\n", argv[0]);
|
||||
#else
|
||||
printf("usage: %s [help|info|close|update|chanmap]\n", argv[0]);
|
||||
#endif
|
||||
@ -429,34 +529,26 @@ int _nimble_netif_handler(int argc, char **argv)
|
||||
_cmd_info();
|
||||
}
|
||||
|
||||
#if !IS_USED(MODULE_NIMBLE_AUTOCONN) && !IS_USED(MODULE_NIMBLE_STATCONN)
|
||||
else if (memcmp(argv[1], "adv", 3) == 0) {
|
||||
char *name = NULL;
|
||||
if (argc > 2) {
|
||||
if (_ishelp(argv[2])) {
|
||||
printf("usage: %s adv [help|stop|direct <addr>|<name>]\n",
|
||||
argv[0]);
|
||||
return 0;
|
||||
}
|
||||
if (memcmp(argv[2], "stop", 4) == 0) {
|
||||
_cmd_adv_stop();
|
||||
return 0;
|
||||
}
|
||||
if (memcmp(argv[2], "direct", 6) == 0) {
|
||||
puts("DBG: direct adv");
|
||||
if (argc < 4) {
|
||||
printf("error, no BLE address given\n");
|
||||
return 0;
|
||||
}
|
||||
_cmd_adv_direct(argv[3]);
|
||||
return 0;
|
||||
}
|
||||
name = argv[2];
|
||||
#if FULL_CONTROL
|
||||
else if (memcmp(argv[1], "adv_ext", 7) == 0) {
|
||||
if (argc <= 2 || _ishelp(argv[2])) {
|
||||
printf("usage: %s adv_ext <help|stop|addr|name> [timeout] [phy mode]\n"
|
||||
" timeout in ms, 0 for no timeout\n"
|
||||
" phy mode: [1M|2M|CODED]\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
_cmd_adv(name);
|
||||
return _cmd_adv(argc, argv, false);
|
||||
}
|
||||
else if (memcmp(argv[1], "adv", 3) == 0) {
|
||||
if (argc <= 2 || _ishelp(argv[2])) {
|
||||
printf("usage: %s adv <help|stop|addr|name> [timeout]\n"
|
||||
" timeout in ms, 0 for no timeout\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
return _cmd_adv(argc, argv, true);
|
||||
}
|
||||
else if (memcmp(argv[1], "scan", 4) == 0) {
|
||||
uint32_t duration = DEFAULT_SCAN_DURATION;
|
||||
uint32_t duration = DEFAULT_SCAN_DURATION_MS;
|
||||
if (argc > 2) {
|
||||
if (_ishelp(argv[2])) {
|
||||
printf("usage: %s scan [help|list|[duration in ms]]\n", argv[0]);
|
||||
@ -472,32 +564,16 @@ int _nimble_netif_handler(int argc, char **argv)
|
||||
}
|
||||
else if (memcmp(argv[1], "connect", 7) == 0) {
|
||||
if ((argc < 3) || _ishelp(argv[2])) {
|
||||
printf("usage: %s connect [help|list|<scanlist entry #>|<BLE addr>|<name>]\n",
|
||||
argv[0]);
|
||||
printf("usage: %s %s [help|list|<scanlist #>|<BLE addr>|<name>] "
|
||||
"[timeout ms] [phy mode]\n"
|
||||
" phy mode: [1M|2M|CODED]\n", argv[0], argv[1]);
|
||||
return 0;
|
||||
}
|
||||
if (memcmp(argv[2], "list", 4) == 0) {
|
||||
_conn_list();
|
||||
return 0;
|
||||
}
|
||||
/* try if param is an BLE address */
|
||||
uint8_t addr[BLE_ADDR_LEN];
|
||||
if (bluetil_addr_from_str(addr, argv[2]) != NULL) {
|
||||
_cmd_connect_addr_raw(addr);
|
||||
return 0;
|
||||
}
|
||||
/* try if param is a name (contains non-number chars) */
|
||||
if (!fmt_is_number(argv[2])) {
|
||||
unsigned duration = DEFAULT_SCAN_DURATION;
|
||||
if (argc > 3) {
|
||||
duration = atoi(argv[3]);
|
||||
}
|
||||
_cmd_connect_name(argv[2], duration);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned pos = atoi(argv[2]);
|
||||
_cmd_connect_scanlist(pos);
|
||||
_cmd_connect(argc, argv);
|
||||
}
|
||||
#endif
|
||||
else if (memcmp(argv[1], "close", 5) == 0) {
|
||||
|
||||
@ -24,13 +24,48 @@
|
||||
#include "net/bluetil/addr.h"
|
||||
#include "nimble_statconn.h"
|
||||
|
||||
|
||||
static uint8_t _parsephy(const char *phy_str)
|
||||
{
|
||||
if (memcmp(phy_str, "1M", 2) == 0) {
|
||||
return NIMBLE_PHY_1M;
|
||||
}
|
||||
#if IS_ACTIVE(MODULE_NIMBLE_PHY_2MBIT)
|
||||
else if (memcmp(phy_str, "2M", 2) == 0) {
|
||||
return NIMBLE_PHY_2M;
|
||||
}
|
||||
#endif
|
||||
#if IS_ACTIVE(MODULE_NIMBLE_PHY_CODED)
|
||||
else if (memcmp(phy_str, "CODED", 5) == 0) {
|
||||
return NIMBLE_PHY_CODED;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
return NIMBLE_PHY_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
int _nimble_statconn_handler(int argc, char **argv)
|
||||
{
|
||||
nimble_statconn_cfg_t cfg;
|
||||
|
||||
if ((argc < 3)) {
|
||||
printf("usage: %s <addm|adds|rm> <BLE addr>\n", argv[0]);
|
||||
printf("usage: %s <addm|adds|rm> <BLE addr> [phy mode]\n"
|
||||
" phy_mode := [1M, 2M, CODED]\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc >= 4) {
|
||||
cfg.phy_mode = _parsephy(argv[3]);
|
||||
if (cfg.phy_mode == NIMBLE_PHY_INVALID) {
|
||||
puts("err: PHY mode not supported");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
cfg.phy_mode = NIMBLE_STATCONN_PHY_MODE;
|
||||
}
|
||||
|
||||
/* parse address */
|
||||
uint8_t addr[BLE_ADDR_LEN];
|
||||
if (bluetil_addr_from_str(addr, argv[2]) == NULL) {
|
||||
@ -39,7 +74,7 @@ int _nimble_statconn_handler(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (strncmp(argv[1], "addm", 4) == 0) {
|
||||
if (nimble_statconn_add_master(addr) == 0) {
|
||||
if (nimble_statconn_add_master(addr, &cfg) == 0) {
|
||||
puts("success: connecting to peer as slave");
|
||||
}
|
||||
else {
|
||||
@ -47,7 +82,7 @@ int _nimble_statconn_handler(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
else if (strncmp(argv[1], "adds", 4) == 0) {
|
||||
if (nimble_statconn_add_slave(addr) == 0) {
|
||||
if (nimble_statconn_add_slave(addr, &cfg) == 0) {
|
||||
puts("success: connecting to peer as master");
|
||||
}
|
||||
else {
|
||||
|
||||
24
tests/nimble_autoconn_gnrc_ext/Makefile
Normal file
24
tests/nimble_autoconn_gnrc_ext/Makefile
Normal file
@ -0,0 +1,24 @@
|
||||
BOARD ?= nrf52dk
|
||||
include ../Makefile.tests_common
|
||||
|
||||
# include shell support
|
||||
USEMODULE += shell
|
||||
USEMODULE += shell_commands
|
||||
USEMODULE += ps
|
||||
|
||||
# Include GNRC and RPL
|
||||
USEMODULE += auto_init_gnrc_netif
|
||||
USEMODULE += gnrc_ipv6_router_default
|
||||
USEMODULE += gnrc_icmpv6_echo
|
||||
USEMODULE += auto_init_gnrc_rpl
|
||||
USEMODULE += gnrc_rpl
|
||||
|
||||
# Setup Nimble
|
||||
USEMODULE += nimble_autoconn_ipsp
|
||||
USEMODULE += nimble_autoconn_ext
|
||||
FEATURES_OPTIONAL += ble_phy_2mbit
|
||||
FEATURES_OPTIONAL += ble_phy_coded
|
||||
|
||||
TEST_ON_CI_WHITELIST += nrf52dk nrf52840dk
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
||||
4
tests/nimble_autoconn_gnrc_ext/Makefile.ci
Normal file
4
tests/nimble_autoconn_gnrc_ext/Makefile.ci
Normal file
@ -0,0 +1,4 @@
|
||||
BOARD_INSUFFICIENT_MEMORY := \
|
||||
e104-bt5010a-tb \
|
||||
e104-bt5011a-tb \
|
||||
#
|
||||
43
tests/nimble_autoconn_gnrc_ext/main.c
Normal file
43
tests/nimble_autoconn_gnrc_ext/main.c
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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 examples
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Run IP-over-BLE using the 'autoconn' BLE connection manager
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "msg.h"
|
||||
|
||||
#define MAIN_QUEUE_SIZE (8)
|
||||
static msg_t _main_msg_queue[MAIN_QUEUE_SIZE];
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* we need a message queue for the thread running the shell in order to
|
||||
* receive potentially fast incoming networking packets */
|
||||
msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE);
|
||||
puts("IPv6-over-BLE with autoconn BLE connection manager");
|
||||
|
||||
/* start shell */
|
||||
puts("All up, running the shell now");
|
||||
char line_buf[SHELL_DEFAULT_BUFSIZE];
|
||||
shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE);
|
||||
|
||||
/* should never be reached */
|
||||
return 0;
|
||||
}
|
||||
@ -8,11 +8,8 @@ USEMODULE += shell_commands
|
||||
USEMODULE += nimble_scanner
|
||||
USEMODULE += nimble_scanlist
|
||||
USEMODULE += nimble_adv_ext
|
||||
USEMODULE += nimble_phy_2mbit
|
||||
|
||||
ifneq (,$(filter nrf52840dk nrf52840dongle,$(BOARD)))
|
||||
USEMODULE += nimble_phy_coded
|
||||
endif
|
||||
FEATURES_OPTIONAL += ble_phy_2mbit
|
||||
FEATURES_OPTIONAL += ble_phy_coded
|
||||
|
||||
# Comment this out to disable code in RIOT that does safety checking
|
||||
# which is not needed in a production environment but helps in the
|
||||
|
||||
24
tests/nimble_netif_ext/Makefile
Normal file
24
tests/nimble_netif_ext/Makefile
Normal file
@ -0,0 +1,24 @@
|
||||
BOARD ?= nrf52dk
|
||||
include ../Makefile.tests_common
|
||||
|
||||
# include shell support
|
||||
USEMODULE += shell
|
||||
USEMODULE += shell_commands
|
||||
USEMODULE += ps
|
||||
|
||||
# Include GNRC and RPL
|
||||
USEMODULE += netdev_default
|
||||
USEMODULE += auto_init_gnrc_netif
|
||||
USEMODULE += gnrc_ipv6_router_default
|
||||
USEMODULE += auto_init_gnrc_rpl
|
||||
USEMODULE += gnrc_rpl
|
||||
USEMODULE += gnrc_icmpv6_echo
|
||||
|
||||
# Setup Nimble
|
||||
USEMODULE += nimble_netif_ext
|
||||
FEATURES_OPTIONAL += ble_phy_2mbit
|
||||
FEATURES_OPTIONAL += ble_phy_coded
|
||||
|
||||
TEST_ON_CI_WHITELIST += nrf52dk nrf52840dk
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
||||
4
tests/nimble_netif_ext/Makefile.ci
Normal file
4
tests/nimble_netif_ext/Makefile.ci
Normal file
@ -0,0 +1,4 @@
|
||||
BOARD_INSUFFICIENT_MEMORY := \
|
||||
e104-bt5010a-tb \
|
||||
e104-bt5011a-tb \
|
||||
#
|
||||
45
tests/nimble_netif_ext/main.c
Normal file
45
tests/nimble_netif_ext/main.c
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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 Test extended advertising and additional PHY modes with
|
||||
* nimble_netif
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "msg.h"
|
||||
|
||||
#define MAIN_QUEUE_SIZE (8)
|
||||
static msg_t _main_msg_queue[MAIN_QUEUE_SIZE];
|
||||
|
||||
int main(void)
|
||||
{
|
||||
puts("Extended PHY mode test for IP over BLE");
|
||||
|
||||
/* we need a message queue for the thread running the shell in order to
|
||||
* receive potentially fast incoming networking packets */
|
||||
msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE);
|
||||
|
||||
/* start shell */
|
||||
puts("All up, running the shell now");
|
||||
char line_buf[SHELL_DEFAULT_BUFSIZE];
|
||||
shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE);
|
||||
|
||||
/* should never be reached */
|
||||
return 0;
|
||||
}
|
||||
@ -17,7 +17,7 @@ USEMODULE += auto_init_gnrc_rpl
|
||||
# configure and use Nimble
|
||||
USEMODULE += bluetil_addr
|
||||
USEMODULE += nimble_rpble
|
||||
NIMBLE_MAX_CONN := 3
|
||||
NIMBLE_MAX_CONN = 3
|
||||
|
||||
DEVELHELP = 0
|
||||
|
||||
|
||||
30
tests/nimble_rpble_gnrc_ext/Makefile
Normal file
30
tests/nimble_rpble_gnrc_ext/Makefile
Normal file
@ -0,0 +1,30 @@
|
||||
BOARD ?= nrf52dk
|
||||
include ../Makefile.tests_common
|
||||
|
||||
# include shell support
|
||||
USEMODULE += shell
|
||||
USEMODULE += shell_commands
|
||||
USEMODULE += ps
|
||||
|
||||
# Enable single interface optimization.
|
||||
# Remove this if more than one interface is present
|
||||
USEMODULE += gnrc_netif_single
|
||||
# Include GNRC and RPL
|
||||
USEMODULE += auto_init_gnrc_netif
|
||||
USEMODULE += gnrc_ipv6_router_default
|
||||
USEMODULE += gnrc_icmpv6_echo
|
||||
USEMODULE += gnrc_rpl
|
||||
USEMODULE += auto_init_gnrc_rpl
|
||||
|
||||
# configure and use Nimble
|
||||
USEMODULE += bluetil_addr
|
||||
USEMODULE += nimble_rpble_ext
|
||||
FEATURES_OPTIONAL += ble_phy_2mbit
|
||||
FEATURES_OPTIONAL += ble_phy_coded
|
||||
NIMBLE_MAX_CONN = 3
|
||||
|
||||
DEVELHELP = 0
|
||||
|
||||
TEST_ON_CI_WHITELIST += nrf52dk nrf52840dk
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
||||
4
tests/nimble_rpble_gnrc_ext/Makefile.ci
Normal file
4
tests/nimble_rpble_gnrc_ext/Makefile.ci
Normal file
@ -0,0 +1,4 @@
|
||||
BOARD_INSUFFICIENT_MEMORY := \
|
||||
e104-bt5010a-tb \
|
||||
e104-bt5011a-tb \
|
||||
#
|
||||
80
tests/nimble_rpble_gnrc_ext/main.c
Normal file
80
tests/nimble_rpble_gnrc_ext/main.c
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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 Test for using rpble in its extended mode
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "msg.h"
|
||||
#include "shell.h"
|
||||
#include "nimble_rpble.h"
|
||||
#include "net/bluetil/addr.h"
|
||||
|
||||
#define MAIN_QUEUE_SIZE (8)
|
||||
static msg_t _main_msg_queue[MAIN_QUEUE_SIZE];
|
||||
|
||||
static void _dump_evt(const char *text, const uint8_t *addr)
|
||||
{
|
||||
printf("[ble_event] %s (", text);
|
||||
bluetil_addr_print(addr);
|
||||
printf(")\n");
|
||||
}
|
||||
|
||||
static void _on_rpble_event(int handle, nimble_netif_event_t event,
|
||||
const uint8_t *addr)
|
||||
{
|
||||
(void)handle;
|
||||
|
||||
switch (event) {
|
||||
case NIMBLE_NETIF_CONNECTED_MASTER:
|
||||
_dump_evt("parent selected", addr);
|
||||
break;
|
||||
case NIMBLE_NETIF_CONNECTED_SLAVE:
|
||||
_dump_evt("child added", addr);
|
||||
break;
|
||||
case NIMBLE_NETIF_CLOSED_MASTER:
|
||||
_dump_evt("parent lost", addr);
|
||||
break;
|
||||
case NIMBLE_NETIF_CLOSED_SLAVE:
|
||||
_dump_evt("child lost", addr);
|
||||
break;
|
||||
default:
|
||||
/* not interested in any other BLE events here */
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
puts("RPL-over-BLE Example Application");
|
||||
|
||||
/* register the custom event handler */
|
||||
nimble_rpble_eventcb(_on_rpble_event);
|
||||
|
||||
/* we need a message queue for the thread running the shell in order to
|
||||
* receive potentially fast incoming networking packets (ping) */
|
||||
msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE);
|
||||
|
||||
/* start shell */
|
||||
char line_buf[SHELL_DEFAULT_BUFSIZE];
|
||||
shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
23
tests/nimble_statconn_gnrc_ext/Makefile
Normal file
23
tests/nimble_statconn_gnrc_ext/Makefile
Normal file
@ -0,0 +1,23 @@
|
||||
BOARD ?= nrf52dk
|
||||
include ../Makefile.tests_common
|
||||
|
||||
# include shell support
|
||||
USEMODULE += shell
|
||||
USEMODULE += shell_commands
|
||||
USEMODULE += ps
|
||||
|
||||
# Include GNRC and RPL
|
||||
USEMODULE += auto_init_gnrc_netif
|
||||
USEMODULE += gnrc_ipv6_router_default
|
||||
USEMODULE += auto_init_gnrc_rpl
|
||||
USEMODULE += gnrc_rpl
|
||||
USEMODULE += gnrc_icmpv6_echo
|
||||
|
||||
# Setup Nimble
|
||||
USEMODULE += nimble_statconn_ext
|
||||
FEATURES_OPTIONAL += ble_phy_2mbit
|
||||
FEATURES_OPTIONAL += ble_phy_coded
|
||||
|
||||
TEST_ON_CI_WHITELIST += nrf52dk nrf52840dk
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
||||
4
tests/nimble_statconn_gnrc_ext/Makefile.ci
Normal file
4
tests/nimble_statconn_gnrc_ext/Makefile.ci
Normal file
@ -0,0 +1,4 @@
|
||||
BOARD_INSUFFICIENT_MEMORY := \
|
||||
e104-bt5010a-tb \
|
||||
e104-bt5011a-tb \
|
||||
#
|
||||
86
tests/nimble_statconn_gnrc_ext/main.c
Normal file
86
tests/nimble_statconn_gnrc_ext/main.c
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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 Run IP-over-BLE using the 'statconn' BLE connection manager
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "msg.h"
|
||||
#include "nimble_statconn.h"
|
||||
#include "net/bluetil/addr.h"
|
||||
|
||||
#define MAIN_QUEUE_SIZE (8)
|
||||
static msg_t _main_msg_queue[MAIN_QUEUE_SIZE];
|
||||
|
||||
static void _print_evt(const char *msg, int handle, const uint8_t *addr)
|
||||
{
|
||||
printf("[ble] %s (%i|", msg, handle);
|
||||
if (addr) {
|
||||
bluetil_addr_print(addr);
|
||||
}
|
||||
else {
|
||||
printf("n/a");
|
||||
}
|
||||
puts(")");
|
||||
}
|
||||
|
||||
static void _on_ble_evt(int handle, nimble_netif_event_t event,
|
||||
const uint8_t *addr)
|
||||
{
|
||||
switch (event) {
|
||||
case NIMBLE_NETIF_CONNECTED_MASTER:
|
||||
_print_evt("CONNECTED master", handle, addr);
|
||||
break;
|
||||
case NIMBLE_NETIF_CONNECTED_SLAVE:
|
||||
_print_evt("CONNECTED slave", handle, addr);
|
||||
break;
|
||||
case NIMBLE_NETIF_CLOSED_MASTER:
|
||||
_print_evt("CLOSED master", handle, addr);
|
||||
break;
|
||||
case NIMBLE_NETIF_CLOSED_SLAVE:
|
||||
_print_evt("CLOSED slave", handle, addr);
|
||||
break;
|
||||
case NIMBLE_NETIF_CONN_UPDATED:
|
||||
_print_evt("UPDATED", handle, addr);
|
||||
break;
|
||||
default:
|
||||
/* do nothing */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
puts("IPv6-over-BLE with statconn BLE connection manager");
|
||||
|
||||
/* we need a message queue for the thread running the shell in order to
|
||||
* receive potentially fast incoming networking packets */
|
||||
msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE);
|
||||
|
||||
/* register for BLE events */
|
||||
nimble_statconn_eventcb(_on_ble_evt);
|
||||
|
||||
/* start shell */
|
||||
puts("All up, running the shell now");
|
||||
char line_buf[SHELL_DEFAULT_BUFSIZE];
|
||||
shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE);
|
||||
|
||||
/* should never be reached */
|
||||
return 0;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user