1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

pkg/nimble/scanner: rework to enable BLE5 scanning

This commit is contained in:
Hauke Petersen 2021-09-13 21:57:14 +02:00
parent 34b009fcc1
commit 586ba70c5b
2 changed files with 152 additions and 24 deletions

View File

@ -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
@ -31,31 +31,100 @@
extern "C" {
#endif
/**
* @brief Flag to mark type for extended advertisements
*/
#define NIMBLE_SCANNER_EXT_ADV 0x80
/**
* @brief Scan procedure configuration flags
*/
enum {
NIMBLE_SCANNER_PASSIVE = 0x01, /**< do a passive scan */
NIMBLE_SCANNER_LIMITED = 0x02, /**< do limited discovery */
NIMBLE_SCANNER_FILTER_DUPS = 0x04, /**< filter duplicates */
NIMBLE_SCANNER_PHY_1M = 0x10, /**< scan on 1Mbit PHY */
NIMBLE_SCANNER_PHY_CODED = 0x20, /**< scan on CODED PHY */
};
/**
* @brief Status flags for received advertising packets
*/
enum {
/**
* All fragments of a advertising message were received
*/
NIMBLE_SCANNER_COMPLETE = BLE_HCI_ADV_DATA_STATUS_COMPLETE,
/**
* The advertising message is incomplete
*/
NIMBLE_SCANNER_INCOMPLETE = BLE_HCI_ADV_DATA_STATUS_INCOMPLETE,
/**
* Advertising message is truncated
*/
NIMBLE_SCANNER_TRUNCATED = BLE_HCI_ADV_DATA_STATUS_TRUNCATED,
};
/**
* @brief Scanner configuration parameters
*/
typedef struct {
uint16_t itvl_ms; /**< scan interval [ms] */
uint16_t win_ms; /**< scan window [ms] */
uint8_t flags; /**< scan configuration flags */
} nimble_scanner_cfg_t;
/**
* @brief Additional information about received advertising packets
*/
typedef struct {
/**
* Status of received packet. Possible values:
* - NIMBLE_SCANNER_COMPLETE
* - NIMBLE_SCANNER_INCOMPLETE
* - NIMBLE_SCANNER_TRUNCATED
*/
uint8_t status;
uint8_t phy_pri; /**< PHY used on primary advertisement channels */
uint8_t phy_sec; /**< PHY used on secondary advertisement channels */
int8_t rssi; /**< RSSI value of received advertisement */
} nimble_scanner_info_t;
/**
* @brief Callback signature triggered by this module for each discovered
* advertising packet
*
* @param[in] type type of advertising packet, e.g
* BLE_HCI_ADV_RPT_EVTYPE_ADV_IND
* @param[in] type type of advertising packet.
* For legacy advertisements on of the following:
* - BLE_HCI_ADV_RPT_EVTYPE_ADV_IND
* - BLE_HCI_ADV_RPT_EVTYPE_DIR_IND
* - BLE_HCI_ADV_RPT_EVTYPE_SCAN_IND
* - BLE_HCI_ADV_RPT_EVTYPE_NONCONN_IND
* - BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP
* For extended advertisements NIMBLE_SCANNER_EXT_ADV ORed
* with any set out of the following:
* - BLE_HCI_ADV_CONN_MASK
* - BLE_HCI_ADV_SCAN_MASK
* - BLE_HCI_ADV_DIRECT_MASK
* - BLE_HCI_ADV_SCAN_RSP_MASK
* @param[in] addr advertising address of the source node
* @param[in] rssi RSSI value for the received packet
* @param[in] info additional information about the advertiser
* @param[in] ad advertising data
* @param[in] ad_len length of @p ad in bytes
*/
typedef void(*nimble_scanner_cb)(uint8_t type,
const ble_addr_t *addr, int8_t rssi,
typedef void(*nimble_scanner_cb)(uint8_t type, const ble_addr_t *addr,
const nimble_scanner_info_t *info,
const uint8_t *ad, size_t ad_len);
/**
* @brief Initialize the scanner module
*
* @param[in] params scan parameters to use, pass NULL to use NimBLE's
* default parameters
* @param[in] params scan parameters to use
* @param[in] disc_cb callback triggered of each received advertising packet
*
* @return 0 on success
*/
int nimble_scanner_init(const struct ble_gap_disc_params *params,
int nimble_scanner_init(const nimble_scanner_cfg_t *params,
nimble_scanner_cb disc_cb);
/**

View File

@ -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
@ -30,22 +30,60 @@
#include "debug.h"
static nimble_scanner_cb _disc_cb = NULL;
#if MYNEWT_VAL_BLE_EXT_ADV
static struct ble_gap_ext_disc_params _scan_params = { 0 };
static uint8_t _scan_flags = 0;
#else
static struct ble_gap_disc_params _scan_params = { 0 };
#endif
/* duration of the scanning procedure */
static int32_t _scan_duration = BLE_HS_FOREVER;
static int _on_scan_evt(struct ble_gap_event *event, void *arg)
{
/* only interested in the DISC event */
if (event->type == BLE_GAP_EVENT_DISC) {
_disc_cb(event->disc.event_type, &event->disc.addr, event->disc.rssi,
switch (event->type) {
#if MYNEWT_VAL_BLE_EXT_ADV
case BLE_GAP_EVENT_EXT_DISC: {
uint8_t type;
nimble_scanner_info_t info;
info.rssi = event->ext_disc.rssi;
if (event->ext_disc.props & BLE_HCI_ADV_LEGACY_MASK) {
type = event->ext_disc.legacy_event_type;
info.status = NIMBLE_SCANNER_COMPLETE;
info.phy_pri = BLE_HCI_LE_PHY_1M;
info.phy_sec = BLE_HCI_LE_PHY_1M;
}
else {
type = (event->ext_disc.props | NIMBLE_SCANNER_EXT_ADV);
info.status = event->ext_disc.data_status;
info.phy_pri = event->ext_disc.prim_phy;
info.phy_sec = event->ext_disc.sec_phy;
}
_disc_cb(type, &event->ext_disc.addr, &info,
event->ext_disc.data, event->ext_disc.length_data);
break;
}
#else
case BLE_GAP_EVENT_DISC: {
nimble_scanner_info_t info = {
.status = NIMBLE_SCANNER_COMPLETE,
.phy_pri = BLE_HCI_LE_PHY_1M,
.phy_sec = BLE_HCI_LE_PHY_1M,
.rssi = event->disc.rssi,
};
_disc_cb(event->disc.event_type, &event->disc.addr, &info,
event->disc.data, (size_t)event->disc.length_data);
break;
}
else if (event->type == BLE_GAP_EVENT_DISC_COMPLETE) {
#endif
case BLE_GAP_EVENT_DISC_COMPLETE:
DEBUG("[scanner] scan cycle completed\n");
}
else {
break;
default:
/* this should never happen */
DEBUG("[scanner] unknown event triggered (%i)\n", (int)event->type);
assert(0);
@ -57,8 +95,23 @@ static int _on_scan_evt(struct ble_gap_event *event, void *arg)
int nimble_scanner_start(void)
{
if (ble_gap_disc_active() == 0) {
int res = ble_gap_disc(nimble_riot_own_addr_type, _scan_duration,
#if MYNEWT_VAL_BLE_EXT_ADV
uint8_t dups = (_scan_flags & NIMBLE_SCANNER_FILTER_DUPS) ? 1 : 0;
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;
const struct ble_gap_ext_disc_params *coded =
(_scan_flags & NIMBLE_SCANNER_PHY_CODED) ? &_scan_params : NULL;
int res = ble_gap_ext_disc(nimble_riot_own_addr_type,
_scan_duration / 10, 0, dups,
BLE_HCI_SCAN_FILT_NO_WL, limited,
uncoded, coded,
_on_scan_evt, NULL);
#else
int res = ble_gap_disc(nimble_riot_own_addr_type, 0,
&_scan_params, _on_scan_evt, NULL);
#endif
if (res != 0) {
DEBUG("[scanner] err: start failed (%i)\n", res);
return -ECANCELED;
@ -87,17 +140,23 @@ void nimble_scanner_set_scan_duration(int32_t duration_ms)
}
}
int nimble_scanner_init(const struct ble_gap_disc_params *params,
int nimble_scanner_init(const nimble_scanner_cfg_t *params,
nimble_scanner_cb disc_cb)
{
assert(params);
assert(disc_cb);
if (params) {
memcpy(&_scan_params, params, sizeof(_scan_params));
}
else {
memset(&_scan_params, 0, sizeof(_scan_params));
}
_scan_params.itvl = BLE_GAP_SCAN_ITVL_MS(params->itvl_ms);
_scan_params.window = BLE_GAP_SCAN_WIN_MS(params->win_ms);
_scan_params.passive = (params->flags & NIMBLE_SCANNER_PASSIVE) ? 1 : 0;
#if MYNEWT_VAL_BLE_EXT_ADV
_scan_flags = params->flags;
#else
_scan_params.limited = (params->flags & NIMBLE_SCANNER_LIMITED) ? 1 : 0;
_scan_params.filter_duplicates =
(params->flags & NIMBLE_SCANNER_FILTER_DUPS) ? 1 : 0;
#endif
_disc_cb = disc_cb;
return 0;