
Used NIMBLE_SCAN_STATUS_SCANNING and NIMBLE_SCAN_STATUS_STOPPED instead of magic number '0', '1'.
314 lines
7.7 KiB
C
314 lines
7.7 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "nimble/nimble_port_tencentos_tiny.h"
|
|
|
|
#include "nimble/ble.h"
|
|
#include "host/ble_gap.h"
|
|
|
|
#define BLE_RAW_ADV_DATA_LEN (31U)
|
|
|
|
typedef enum nimble_scan_status_en {
|
|
NIMBLE_SCAN_STATUS_STOPPED = 0,
|
|
NIMBLE_SCAN_STATUS_SCANNING = 1,
|
|
} nimble_scan_status_t;
|
|
|
|
typedef struct nimble_scan_item_st {
|
|
k_list_t list;
|
|
ble_addr_t addr; /* ble address */
|
|
uint8_t adv_data[BLE_RAW_ADV_DATA_LEN]; /* advertising data received */
|
|
uint8_t adv_data_len; /* length of the advertising data */
|
|
int8_t rssi; /* last RSSI of a scanned node */
|
|
uint8_t type; /* advertising packet type */
|
|
} nimble_scan_item_t;
|
|
|
|
/*
|
|
type: type of advertising packet, e.g BLE_HCI_ADV_TYPE_ADV_IND
|
|
disc_addr: advertising address of the source node
|
|
disc_rssi: RSSI value for the received packet
|
|
disc_adv_data: received advertising data
|
|
disc_adv_data_len: length of disc_adv_data in bytes
|
|
*/
|
|
typedef void(*nimble_scan_cb_t)(uint8_t type,
|
|
const ble_addr_t *disc_addr, int8_t disc_rssi,
|
|
const uint8_t *disc_adv_data, size_t disc_adv_data_len);
|
|
|
|
static uint8_t ble_addr_type;
|
|
static nimble_scan_cb_t scan_disc_cb = NULL;
|
|
static struct ble_gap_disc_params scan_params = { 0 };
|
|
|
|
static nimble_scan_item_t entry_pool[200];
|
|
TOS_LIST_DEFINE(free_entry);
|
|
TOS_LIST_DEFINE(scan_entry);
|
|
|
|
void nimble_scan_info_list_init(void)
|
|
{
|
|
int i = 0;
|
|
|
|
for (i = 0; i < sizeof(entry_pool) / sizeof(entry_pool[0]); ++i) {
|
|
tos_list_init(&entry_pool[i].list);
|
|
tos_list_add(&entry_pool[i].list, &free_entry);
|
|
}
|
|
}
|
|
|
|
void nimble_scan_item_addr_display(ble_addr_t *addr)
|
|
{
|
|
int i = 0;
|
|
|
|
printf("%02x", (int)addr->val[5]);
|
|
|
|
for (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_scan_item_type_display(uint8_t type)
|
|
{
|
|
switch (type) {
|
|
case BLE_HCI_ADV_TYPE_ADV_IND:
|
|
printf(" [IND]");
|
|
break;
|
|
|
|
case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD:
|
|
printf(" [DIRECT_IND_HD]");
|
|
break;
|
|
|
|
case BLE_HCI_ADV_TYPE_ADV_SCAN_IND:
|
|
printf(" [SCAN_IND]");
|
|
break;
|
|
|
|
case BLE_HCI_ADV_TYPE_ADV_NONCONN_IND:
|
|
printf(" [NONCONN_IND]");
|
|
break;
|
|
|
|
case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD:
|
|
printf(" [DIRECT_IND_LD]");
|
|
break;
|
|
|
|
default:
|
|
printf(" [INVALID]");
|
|
break;
|
|
}
|
|
}
|
|
|
|
void nimble_scan_item_display(nimble_scan_item_t *item)
|
|
{
|
|
nimble_scan_item_addr_display(&item->addr);
|
|
nimble_scan_item_type_display(item->type);
|
|
printf(", rssi: %d\n", item->rssi);
|
|
printf("\n");
|
|
}
|
|
|
|
void nimble_scan_info_list_display(void)
|
|
{
|
|
nimble_scan_item_t *iter;
|
|
|
|
TOS_LIST_FOR_EACH_ENTRY(iter, nimble_scan_item_t, list, &scan_entry) {
|
|
nimble_scan_item_display(iter);
|
|
}
|
|
}
|
|
|
|
nimble_scan_item_t *nimble_scan_item_alloc(void)
|
|
{
|
|
return TOS_LIST_FIRST_ENTRY_OR_NULL(&free_entry, nimble_scan_item_t, list);
|
|
}
|
|
|
|
int nimble_scan_item_is_exist(ble_addr_t *addr)
|
|
{
|
|
nimble_scan_item_t *iter;
|
|
|
|
TOS_LIST_FOR_EACH_ENTRY(iter, nimble_scan_item_t, list, &free_entry) {
|
|
if (ble_addr_cmp(&addr, &iter->addr) == 0) {
|
|
return K_TRUE;
|
|
}
|
|
}
|
|
return K_FALSE;
|
|
}
|
|
|
|
void nimble_scan_info_save(uint8_t type, const ble_addr_t *disc_addr, int8_t disc_rssi,
|
|
const uint8_t *disc_adv_data, size_t disc_adv_data_len)
|
|
{
|
|
int i = 0;
|
|
nimble_scan_item_t *item;
|
|
|
|
if (nimble_scan_item_is_exist(disc_addr)) {
|
|
return;
|
|
}
|
|
|
|
item = nimble_scan_item_alloc();
|
|
if (!item) {
|
|
return;
|
|
}
|
|
|
|
memcpy(&item->addr, disc_addr, sizeof(ble_addr_t));
|
|
if (disc_adv_data) {
|
|
memcpy(&item->adv_data, disc_adv_data, disc_adv_data_len);
|
|
}
|
|
item->adv_data_len = disc_adv_data_len;
|
|
item->rssi = disc_rssi;
|
|
item->type = type;
|
|
|
|
tos_list_del(&item->list);
|
|
tos_list_add(&item->list, &scan_entry);
|
|
}
|
|
|
|
static int blescan_gap_event(struct ble_gap_event *event, void *arg)
|
|
{
|
|
/* only interested in the DISC event */
|
|
switch (event->type) {
|
|
case BLE_GAP_EVENT_DISC:
|
|
scan_disc_cb(event->disc.event_type, &event->disc.addr, event->disc.rssi,
|
|
event->disc.data, (size_t)event->disc.length_data);
|
|
break;
|
|
|
|
default:
|
|
/* should never happen */
|
|
MODLOG_DFLT(DEBUG, "unexpected event: (%d)\n", (int)event->type);
|
|
assert(0);
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int nimble_scan_start(void)
|
|
{
|
|
int rc;
|
|
|
|
if (ble_gap_disc_active() != NIMBLE_SCAN_STATUS_STOPPED) {
|
|
return 0;
|
|
}
|
|
|
|
rc = ble_gap_disc(ble_addr_type, BLE_HS_FOREVER,
|
|
&scan_params, blescan_gap_event, NULL);
|
|
if (rc != 0) {
|
|
MODLOG_DFLT(DEBUG, "[scanner] err: start failed (%i)\n", rc);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void nimble_scan_stop(void)
|
|
{
|
|
int rc;
|
|
|
|
if (ble_gap_disc_active() != NIMBLE_SCAN_STATUS_SCANNING) {
|
|
return;
|
|
}
|
|
|
|
rc = ble_gap_disc_cancel();
|
|
assert(rc == 0);
|
|
}
|
|
|
|
nimble_scan_status_t nimble_scan_status(void)
|
|
{
|
|
return ble_gap_disc_active() == 1 ? NIMBLE_SCAN_STATUS_SCANNING : NIMBLE_SCAN_STATUS_STOPPED;
|
|
}
|
|
|
|
int nimble_scan_init(const struct ble_gap_disc_params *params, nimble_scan_cb_t disc_cb)
|
|
{
|
|
assert(disc_cb);
|
|
|
|
if (params) {
|
|
memcpy(&scan_params, params, sizeof(scan_params));
|
|
} else {
|
|
memset(&scan_params, 0, sizeof(scan_params));
|
|
}
|
|
scan_disc_cb = disc_cb;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int ble_boot(void)
|
|
{
|
|
int rc;
|
|
|
|
extern void nimble_port_run(void);
|
|
nimble_port_tencentos_tiny_init(nimble_port_run);
|
|
|
|
/* make sure synchronization of host and controller is done */
|
|
while (!ble_hs_synced()) {
|
|
;
|
|
}
|
|
|
|
rc = ble_hs_util_ensure_addr(0);
|
|
assert(rc == 0);
|
|
rc = ble_hs_id_infer_auto(0, &ble_addr_type);
|
|
assert(rc == 0);
|
|
|
|
/* do a 'full time' scan, set the window equal the interval */
|
|
struct ble_gap_disc_params scan_params = {
|
|
.itvl = BLE_GAP_LIM_DISC_SCAN_INT,
|
|
.window = BLE_GAP_LIM_DISC_SCAN_WINDOW,
|
|
.filter_policy = 0, /* dummy */
|
|
.limited = 0, /* no limited discovery */
|
|
.passive = 0, /* no passive scanning */
|
|
.filter_duplicates = 0, /* no duplicate filtering */
|
|
};
|
|
|
|
nimble_scan_info_list_init();
|
|
|
|
/* initialize the nimble scanner */
|
|
nimble_scan_init(&scan_params, nimble_scan_info_save);
|
|
|
|
rc = nimble_scan_start();
|
|
assert(rc == 0);
|
|
|
|
tos_task_delay(2000);
|
|
|
|
nimble_scan_stop();
|
|
|
|
nimble_scan_info_list_display();
|
|
|
|
return 0;
|
|
}
|
|
|
|
k_task_t ble_boot_task;
|
|
k_stack_t ble_boot_stack[2048];
|
|
|
|
int main(void)
|
|
{
|
|
board_init();
|
|
|
|
/* Initialize OS */
|
|
tos_knl_init();
|
|
|
|
nimble_port_init();
|
|
|
|
/*
|
|
in this case, ble_boot_task's priority must lower than MYNEWT_VAL_BLE_HOST_TASK_PRIORITY && MYNEWT_VAL_BLE_LL_TASK_PRIORITY,
|
|
numerically bigger
|
|
to give the host and ll task a chance to run first just after the nimble_port_tencentos_tiny_init.
|
|
*/
|
|
tos_task_create(&ble_boot_task, "ble_boot", ble_boot, NULL,
|
|
6,
|
|
ble_boot_stack, sizeof(ble_boot_stack),
|
|
0);
|
|
tos_knl_start();
|
|
}
|
|
|