mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
ble/nimble: add scanlist submodule
This commit is contained in:
parent
e5c5beaf40
commit
bce0381c6f
@ -67,4 +67,8 @@ nimble_drivers_nrf52:
|
||||
# additional, RIOT specific nimble modules
|
||||
nimble_addr:
|
||||
"$(MAKE)" -C $(TDIR)/addr/
|
||||
|
||||
nimble_scanlist:
|
||||
"$(MAKE)" -C $(TDIR)/scanlist
|
||||
|
||||
include $(RIOTBASE)/pkg/pkg.mk
|
||||
|
@ -34,3 +34,8 @@ endif
|
||||
ifneq (,$(filter nimble_addr,$(USEMODULE)))
|
||||
USEMODULE += bluetil_addr
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_scanlist,$(USEMODULE)))
|
||||
USEMODULE += nimble_addr
|
||||
USEMODULE += bluetil_ad
|
||||
endif
|
||||
|
@ -73,3 +73,6 @@ endif
|
||||
ifneq (,$(filter nimble_addr,$(USEMODULE)))
|
||||
INCLUDES += -I$(RIOTPKG)/nimble/addr/include
|
||||
endif
|
||||
ifneq (,$(filter nimble_scanlist,$(USEMODULE)))
|
||||
INCLUDES += -I$(RIOTPKG)/nimble/scanlist/include
|
||||
endif
|
||||
|
3
pkg/nimble/scanlist/Makefile
Normal file
3
pkg/nimble/scanlist/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE = nimble_scanlist
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
119
pkg/nimble/scanlist/include/nimble_scanlist.h
Normal file
119
pkg/nimble/scanlist/include/nimble_scanlist.h
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* 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 ble_nimble_scanlist Scan Result List
|
||||
* @ingroup ble_nimble
|
||||
* @brief List for storing and printing BLE scan results
|
||||
*
|
||||
* @note This scanlist implementation is not thread safe. So calling
|
||||
* nimble_scanlist_update() in between nimble_scanlist_get*()
|
||||
* calls is not a good idea.
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief List for keeping scanned BLE devices
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef NIMBLE_SCANLIST_H
|
||||
#define NIMBLE_SCANLIST_H
|
||||
|
||||
#include "clist.h"
|
||||
#include "net/ble.h"
|
||||
#include "nimble/ble.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Default number of list entries that are allocated in RAM
|
||||
*/
|
||||
#ifndef NIMBLE_SCANLIST_SIZE
|
||||
#define NIMBLE_SCANLIST_SIZE (20U)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Data structure for holding a single scanlist entry
|
||||
*/
|
||||
typedef struct {
|
||||
clist_node_t node; /**< list node */
|
||||
ble_addr_t addr; /**< a node's BLE address */
|
||||
uint8_t ad[BLE_ADV_PDU_LEN]; /**< the received raw advertising data */
|
||||
uint8_t ad_len; /**< length of the advertising data */
|
||||
int8_t last_rssi; /**< last RSSI of a scanned node */
|
||||
uint32_t adv_msg_cnt; /**< number of adv packets by a node */
|
||||
uint32_t first_update; /**< first packet timestamp */
|
||||
uint32_t last_update; /**< last packet timestamp */
|
||||
} nimble_scanlist_entry_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize the scanlist
|
||||
*/
|
||||
void nimble_scanlist_init(void);
|
||||
|
||||
/**
|
||||
* @brief Add/update the entry for the a scanned node
|
||||
*
|
||||
* If the list is already full, the scanned node is simply ignored.
|
||||
*
|
||||
* @param[in] addr BLE address of the scanned node
|
||||
* @param[in] rssi RSSI of the received advertising packet
|
||||
* @param[in] ad the payload of the advertising packet
|
||||
* @param[in] len length of @p ad
|
||||
*/
|
||||
void nimble_scanlist_update(const ble_addr_t *addr, int8_t rssi,
|
||||
const uint8_t *ad, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Get an entry of the scanlist by its position
|
||||
*
|
||||
* @param[in] pos position in the list
|
||||
*
|
||||
* @return the scanlist entry at position @p pos
|
||||
* @return NULL if there is no entry a the given position
|
||||
*/
|
||||
nimble_scanlist_entry_t *nimble_scanlist_get_by_pos(unsigned pos);
|
||||
|
||||
/**
|
||||
* @brief Get the next entry from the list, pass NULL for getting the first
|
||||
* entry
|
||||
*
|
||||
* @param[in] e any entry in the list
|
||||
*
|
||||
* @return the entry following @p e
|
||||
* @return NULL if @p e was the last entry
|
||||
*/
|
||||
nimble_scanlist_entry_t *nimble_scanlist_get_next(nimble_scanlist_entry_t *e);
|
||||
|
||||
/**
|
||||
* @brief Clear all entries in the list
|
||||
*/
|
||||
void nimble_scanlist_clear(void);
|
||||
|
||||
/**
|
||||
* @brief Dump the entire scanlist to STDIO using nimble_scanlist_print_entry()
|
||||
*/
|
||||
void nimble_scanlist_print(void);
|
||||
|
||||
/**
|
||||
* @brief Dump a single scanlist entry to STDIO
|
||||
*
|
||||
* @param[in] e entry to dump
|
||||
*/
|
||||
void nimble_scanlist_print_entry(nimble_scanlist_entry_t *e);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NIMBLE_SCANLIST_H */
|
||||
/** @} */
|
121
pkg/nimble/scanlist/nimble_scanlist.c
Normal file
121
pkg/nimble/scanlist/nimble_scanlist.c
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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 ble_nimble_scanlist
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Implementation of a list for NimBLE scan results
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
#include <limits.h>
|
||||
|
||||
#include "xtimer.h"
|
||||
#include "net/bluetil/ad.h"
|
||||
|
||||
#include "nimble_scanlist.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
static nimble_scanlist_entry_t _mem[NIMBLE_SCANLIST_SIZE];
|
||||
|
||||
static clist_node_t _pool;
|
||||
static clist_node_t _list;
|
||||
|
||||
static int _finder(clist_node_t *node, void *arg)
|
||||
{
|
||||
const ble_addr_t *addr = (const ble_addr_t *)arg;
|
||||
nimble_scanlist_entry_t *e = (nimble_scanlist_entry_t *)node;
|
||||
if (ble_addr_cmp(&e->addr, addr) == 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static nimble_scanlist_entry_t *_find(const ble_addr_t *addr)
|
||||
{
|
||||
return (nimble_scanlist_entry_t *)clist_foreach(&_list, _finder,
|
||||
(void *)addr);
|
||||
}
|
||||
|
||||
void nimble_scanlist_init(void)
|
||||
{
|
||||
for (unsigned i = 0; i < (sizeof(_mem) / sizeof(_mem[0])); i++) {
|
||||
clist_rpush(&_pool, &_mem[i].node);
|
||||
}
|
||||
}
|
||||
|
||||
void nimble_scanlist_update(const ble_addr_t *addr, int8_t rssi,
|
||||
const uint8_t *ad, size_t len)
|
||||
{
|
||||
assert(addr);
|
||||
assert(len <= BLE_ADV_PDU_LEN);
|
||||
|
||||
uint32_t now = xtimer_now_usec();
|
||||
nimble_scanlist_entry_t *e = _find(addr);
|
||||
|
||||
if (!e) {
|
||||
e = (nimble_scanlist_entry_t *)clist_lpop(&_pool);
|
||||
if (!e) {
|
||||
/* no space available, dropping newly discovered node */
|
||||
return;
|
||||
}
|
||||
memcpy(&e->addr, addr, sizeof(ble_addr_t));
|
||||
if (ad) {
|
||||
memcpy(e->ad, ad, len);
|
||||
}
|
||||
e->ad_len = len;
|
||||
e->last_rssi = rssi;
|
||||
e->first_update = now;
|
||||
e->adv_msg_cnt = 1;
|
||||
clist_rpush(&_list, (clist_node_t *)e);
|
||||
}
|
||||
else {
|
||||
e->adv_msg_cnt++;
|
||||
}
|
||||
|
||||
e->last_update = now;
|
||||
}
|
||||
|
||||
nimble_scanlist_entry_t *nimble_scanlist_get_next(nimble_scanlist_entry_t *e)
|
||||
{
|
||||
if (e == NULL) {
|
||||
return (nimble_scanlist_entry_t *)_list.next;
|
||||
}
|
||||
else {
|
||||
e = (nimble_scanlist_entry_t *)e->node.next;
|
||||
if (e == (nimble_scanlist_entry_t *)_list.next) {
|
||||
/* end of list */
|
||||
return NULL;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
nimble_scanlist_entry_t *nimble_scanlist_get(unsigned pos)
|
||||
{
|
||||
nimble_scanlist_entry_t *cur = nimble_scanlist_get_next(NULL);
|
||||
for (unsigned i = 0; i < pos; i++) {
|
||||
cur = nimble_scanlist_get_next(cur);
|
||||
}
|
||||
return cur;
|
||||
}
|
||||
|
||||
void nimble_scanlist_clear(void)
|
||||
{
|
||||
clist_node_t *node = clist_lpop(&_list);
|
||||
while (node) {
|
||||
clist_rpush(&_pool, node);
|
||||
node = clist_lpop(&_list);
|
||||
}
|
||||
}
|
71
pkg/nimble/scanlist/nimble_scanlist_print.c
Normal file
71
pkg/nimble/scanlist/nimble_scanlist_print.c
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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 ble_nimble_scanlist
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Print functions for printing a scanlist or selected entries to
|
||||
* STDIO
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "net/bluetil/ad.h"
|
||||
#include "nimble_scanlist.h"
|
||||
|
||||
static void _print_addr(const ble_addr_t *addr)
|
||||
{
|
||||
printf("%02x", (int)addr->val[5]);
|
||||
for (int i = 4; i >= 0; i--) {
|
||||
printf(":%02x", addr->val[i]);
|
||||
}
|
||||
switch (addr->type) {
|
||||
case BLE_ADDR_PUBLIC: printf(" (PUBLIC) "); break;
|
||||
case BLE_ADDR_RANDOM: printf(" (RANDOM) "); break;
|
||||
case BLE_ADDR_PUBLIC_ID: printf(" (PUB_ID) "); break;
|
||||
case BLE_ADDR_RANDOM_ID: printf(" (RAND_ID)"); break;
|
||||
default: printf(" (UNKNOWN)"); break;
|
||||
}
|
||||
}
|
||||
|
||||
void nimble_scanlist_print(void)
|
||||
{
|
||||
unsigned i = 0;
|
||||
|
||||
nimble_scanlist_entry_t *e = nimble_scanlist_get_next(NULL);
|
||||
while (e) {
|
||||
printf("[%2u] ", i++);
|
||||
nimble_scanlist_print_entry(e);
|
||||
e = nimble_scanlist_get_next(e);
|
||||
}
|
||||
}
|
||||
|
||||
void nimble_scanlist_print_entry(nimble_scanlist_entry_t *e)
|
||||
{
|
||||
assert(e);
|
||||
|
||||
/* try to find a device name */
|
||||
char name[(BLE_ADV_PDU_LEN + 1)] = { 0 };
|
||||
bluetil_ad_t ad = BLUETIL_AD_INIT(e->ad, e->ad_len, e->ad_len);
|
||||
int res = bluetil_ad_find_str(&ad, BLE_GAP_AD_NAME, name, sizeof(name));
|
||||
if (res != BLUETIL_AD_OK) {
|
||||
res = bluetil_ad_find_str(&ad, BLE_GAP_AD_NAME_SHORT, name, sizeof(name));
|
||||
}
|
||||
if (res != BLUETIL_AD_OK) {
|
||||
strncpy(name, "undefined", sizeof(name));
|
||||
}
|
||||
|
||||
_print_addr(&e->addr);
|
||||
unsigned adv_int = ((e->last_update - e->first_update) / e->adv_msg_cnt);
|
||||
printf(" \"%s\", adv_msg_cnt: %u, adv_int: %uus, last_rssi: %i\n",
|
||||
name, (unsigned)e->adv_msg_cnt, adv_int, (int)e->last_rssi);
|
||||
}
|
Loading…
Reference in New Issue
Block a user