Bluetooth: Mesh: Add Multi Advertising Sets Support

This PR add multi advertising sets for bluetooth mesh adv bearer.
At the present, the local mesh network occupy single advertising.
And GATT Services Advertising use a single advertising, if support.

One or more advertising sets maybe used by relay node.

Signed-off-by: Lingao Meng <menglingao@xiaomi.com>
This commit is contained in:
Lingao Meng 2021-11-03 17:05:10 +08:00 committed by Johan Hedberg
commit 56785c173b
5 changed files with 358 additions and 103 deletions

View file

@ -301,6 +301,26 @@ config BT_MESH_ADV_EXT
endchoice endchoice
if BT_MESH_ADV_EXT
config BT_MESH_RELAY_ADV_SETS
int "Maximum of simultaneous relay message support"
default 0
range 0 BT_EXT_ADV_MAX_ADV_SET
depends on BT_MESH_RELAY
help
Maximum of simultaneous relay message support. Requires controller support
multiple advertising sets.
config BT_MESH_ADV_EXT_GATT_SEPARATE
bool "Use a separate extended advertising set for GATT Server Advertising"
depends on BT_MESH_GATT_SERVER
help
Use a separate extended advertising set for GATT Server Advertising,
otherwise will be used a shared advertising set.
endif # BT_MESH_ADV_EXT
config BT_MESH_ADV_STACK_SIZE config BT_MESH_ADV_STACK_SIZE
int "Mesh advertiser thread stack size" int "Mesh advertiser thread stack size"
depends on BT_MESH_ADV_LEGACY depends on BT_MESH_ADV_LEGACY

View file

@ -40,7 +40,8 @@ const uint8_t bt_mesh_adv_type[BT_MESH_ADV_TYPES] = {
[BT_MESH_ADV_URI] = BT_DATA_URI, [BT_MESH_ADV_URI] = BT_DATA_URI,
}; };
K_FIFO_DEFINE(bt_mesh_adv_queue); static K_FIFO_DEFINE(bt_mesh_adv_queue);
static K_FIFO_DEFINE(bt_mesh_relay_queue);
static void adv_buf_destroy(struct net_buf *buf) static void adv_buf_destroy(struct net_buf *buf)
{ {
@ -101,6 +102,67 @@ struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type,
tag, xmit, timeout); tag, xmit, timeout);
} }
static struct net_buf *process_events(struct k_poll_event *ev, int count)
{
for (; count; ev++, count--) {
BT_DBG("ev->state %u", ev->state);
switch (ev->state) {
case K_POLL_STATE_FIFO_DATA_AVAILABLE:
return net_buf_get(ev->fifo, K_NO_WAIT);
case K_POLL_STATE_NOT_READY:
case K_POLL_STATE_CANCELLED:
break;
default:
BT_WARN("Unexpected k_poll event state %u", ev->state);
break;
}
}
return NULL;
}
struct net_buf *bt_mesh_adv_buf_get(k_timeout_t timeout)
{
int err;
struct k_poll_event events[] = {
K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE,
K_POLL_MODE_NOTIFY_ONLY,
&bt_mesh_adv_queue,
0),
#if defined(CONFIG_BT_MESH_RELAY)
K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE,
K_POLL_MODE_NOTIFY_ONLY,
&bt_mesh_relay_queue,
0),
#endif /* CONFIG_BT_MESH_RELAY */
};
err = k_poll(events, ARRAY_SIZE(events), timeout);
if (err) {
return NULL;
}
return process_events(events, ARRAY_SIZE(events));
}
struct net_buf *bt_mesh_adv_buf_relay_get(k_timeout_t timeout)
{
return net_buf_get(&bt_mesh_relay_queue, timeout);
}
void bt_mesh_adv_buf_get_cancel(void)
{
BT_DBG("");
k_fifo_cancel_wait(&bt_mesh_adv_queue);
#if defined(CONFIG_BT_MESH_RELAY)
k_fifo_cancel_wait(&bt_mesh_relay_queue);
#endif /* CONFIG_BT_MESH_RELAY */
}
void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb, void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb,
void *cb_data) void *cb_data)
{ {
@ -111,8 +173,13 @@ void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb,
BT_MESH_ADV(buf)->cb_data = cb_data; BT_MESH_ADV(buf)->cb_data = cb_data;
BT_MESH_ADV(buf)->busy = 1U; BT_MESH_ADV(buf)->busy = 1U;
if (BT_MESH_ADV(buf)->tag == BT_MESH_LOCAL_ADV) {
net_buf_put(&bt_mesh_adv_queue, net_buf_ref(buf)); net_buf_put(&bt_mesh_adv_queue, net_buf_ref(buf));
bt_mesh_adv_buf_ready(); bt_mesh_adv_buf_local_ready();
} else {
net_buf_put(&bt_mesh_relay_queue, net_buf_ref(buf));
bt_mesh_adv_buf_relay_ready();
}
} }
static void bt_mesh_scan_cb(const bt_addr_le_t *addr, int8_t rssi, static void bt_mesh_scan_cb(const bt_addr_le_t *addr, int8_t rssi,

View file

@ -42,8 +42,6 @@ struct bt_mesh_adv {
uint8_t xmit; uint8_t xmit;
}; };
extern struct k_fifo bt_mesh_adv_queue;
/* Lookup table for Advertising data types for bt_mesh_adv_type: */ /* Lookup table for Advertising data types for bt_mesh_adv_type: */
extern const uint8_t bt_mesh_adv_type[BT_MESH_ADV_TYPES]; extern const uint8_t bt_mesh_adv_type[BT_MESH_ADV_TYPES];
@ -55,8 +53,14 @@ struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type,
void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb, void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb,
void *cb_data); void *cb_data);
struct net_buf *bt_mesh_adv_buf_get(k_timeout_t timeout);
struct net_buf *bt_mesh_adv_buf_relay_get(k_timeout_t timeout);
void bt_mesh_adv_update(void); void bt_mesh_adv_update(void);
void bt_mesh_adv_buf_get_cancel(void);
void bt_mesh_adv_init(void); void bt_mesh_adv_init(void);
int bt_mesh_scan_enable(void); int bt_mesh_scan_enable(void);
@ -65,7 +69,9 @@ int bt_mesh_scan_disable(void);
int bt_mesh_adv_enable(void); int bt_mesh_adv_enable(void);
void bt_mesh_adv_buf_ready(void); void bt_mesh_adv_buf_local_ready(void);
void bt_mesh_adv_buf_relay_ready(void);
int bt_mesh_adv_start(const struct bt_le_adv_param *param, int32_t duration, int bt_mesh_adv_start(const struct bt_le_adv_param *param, int32_t duration,
const struct bt_data *ad, size_t ad_len, const struct bt_data *ad, size_t ad_len,

View file

@ -1,4 +1,5 @@
/* /*
* Copyright (c) 2021 Xiaomi Corporation
* Copyright (c) 2018 Nordic Semiconductor ASA * Copyright (c) 2018 Nordic Semiconductor ASA
* Copyright (c) 2017 Intel Corporation * Copyright (c) 2017 Intel Corporation
* *
@ -26,15 +27,6 @@
/* Convert from ms to 0.625ms units */ /* Convert from ms to 0.625ms units */
#define ADV_INT_FAST_MS 20 #define ADV_INT_FAST_MS 20
static struct bt_le_adv_param adv_param = {
.id = BT_ID_DEFAULT,
.interval_min = BT_MESH_ADV_SCAN_UNIT(ADV_INT_FAST_MS),
.interval_max = BT_MESH_ADV_SCAN_UNIT(ADV_INT_FAST_MS),
#if defined(CONFIG_BT_MESH_DEBUG_USE_ID_ADDR)
.options = BT_LE_ADV_OPT_USE_IDENTITY,
#endif
};
enum { enum {
/** Controller is currently advertising */ /** Controller is currently advertising */
ADV_FLAG_ACTIVE, ADV_FLAG_ACTIVE,
@ -51,62 +43,133 @@ enum {
ADV_FLAGS_NUM ADV_FLAGS_NUM
}; };
static struct { typedef struct net_buf* (*adv_buf_handler_t)(k_timeout_t timeout);
struct ext_adv {
ATOMIC_DEFINE(flags, ADV_FLAGS_NUM); ATOMIC_DEFINE(flags, ADV_FLAGS_NUM);
struct bt_le_ext_adv *instance; struct bt_le_ext_adv *instance;
struct net_buf *buf; struct net_buf *buf;
uint64_t timestamp; uint64_t timestamp;
struct k_work_delayable work; struct k_work_delayable work;
} adv; adv_buf_handler_t handler;
struct bt_le_adv_param adv_param;
};
static int adv_start(const struct bt_le_adv_param *param, static void send_pending_adv(struct k_work *work);
static struct ext_adv adv_main = {
.work = Z_WORK_DELAYABLE_INITIALIZER(send_pending_adv),
.handler = bt_mesh_adv_buf_get,
.adv_param = {
.id = BT_ID_DEFAULT,
.interval_min = BT_MESH_ADV_SCAN_UNIT(ADV_INT_FAST_MS),
.interval_max = BT_MESH_ADV_SCAN_UNIT(ADV_INT_FAST_MS),
#if defined(CONFIG_BT_MESH_DEBUG_USE_ID_ADDR)
.options = BT_LE_ADV_OPT_USE_IDENTITY,
#endif
}
};
#if defined(CONFIG_BT_MESH_RELAY)
#define RELAY_ADV_COUNT CONFIG_BT_MESH_RELAY_ADV_SETS
#if RELAY_ADV_COUNT
static struct ext_adv adv_relay[RELAY_ADV_COUNT] = {
[0 ... RELAY_ADV_COUNT - 1] = {
.work = Z_WORK_DELAYABLE_INITIALIZER(send_pending_adv),
.handler = bt_mesh_adv_buf_relay_get,
.adv_param = {
.id = BT_ID_DEFAULT,
.interval_min = BT_MESH_ADV_SCAN_UNIT(ADV_INT_FAST_MS),
.interval_max = BT_MESH_ADV_SCAN_UNIT(ADV_INT_FAST_MS),
#if defined(CONFIG_BT_MESH_DEBUG_USE_ID_ADDR)
.options = BT_LE_ADV_OPT_USE_IDENTITY,
#endif
}
}
};
#define BT_MESH_RELAY_ADV_INS (adv_relay)
#else /* !RELAY_ADV_COUNT */
#define BT_MESH_RELAY_ADV_INS (&adv_main)
#endif /* RELAY_ADV_COUNT */
#else /* !CONFIG_BT_MESH_RELAY */
#define RELAY_ADV_COUNT 0
#define BT_MESH_RELAY_ADV_INS (struct ext_adv)NULL
#endif /* CONFIG_BT_MESH_RELAY */
#if defined(CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE)
#define BT_MESH_ADV_COUNT (1 + RELAY_ADV_COUNT + 1)
static void send_pending_adv_gatt_handler(struct k_work *work);
static struct ext_adv adv_gatt = {
.work = Z_WORK_DELAYABLE_INITIALIZER(send_pending_adv_gatt_handler),
.adv_param = {
.id = BT_ID_DEFAULT,
.interval_min = BT_MESH_ADV_SCAN_UNIT(ADV_INT_FAST_MS),
.interval_max = BT_MESH_ADV_SCAN_UNIT(ADV_INT_FAST_MS),
#if defined(CONFIG_BT_MESH_DEBUG_USE_ID_ADDR)
.options = BT_LE_ADV_OPT_USE_IDENTITY,
#endif
}
};
#define BT_MESH_ADV_EXT_GATT_SEPARATE_INS (&adv_gatt)
#elif defined(CONFIG_BT_MESH_GATT_SERVER)
#define BT_MESH_ADV_COUNT (1 + RELAY_ADV_COUNT)
#define BT_MESH_ADV_EXT_GATT_SEPARATE_INS (&adv_main)
#else /* !CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE */
#define BT_MESH_ADV_COUNT (1 + RELAY_ADV_COUNT)
#define BT_MESH_ADV_EXT_GATT_SEPARATE_INS (struct ext_adv)NULL
#endif /* CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE */
BUILD_ASSERT(CONFIG_BT_EXT_ADV_MAX_ADV_SET >= BT_MESH_ADV_COUNT,
"Insufficient adv instances");
static int adv_start(struct ext_adv *adv,
const struct bt_le_adv_param *param,
struct bt_le_ext_adv_start_param *start, struct bt_le_ext_adv_start_param *start,
const struct bt_data *ad, size_t ad_len, const struct bt_data *ad, size_t ad_len,
const struct bt_data *sd, size_t sd_len) const struct bt_data *sd, size_t sd_len)
{ {
int err; int err;
if (!adv.instance) { if (!adv->instance) {
BT_ERR("Mesh advertiser not enabled"); BT_ERR("Mesh advertiser not enabled");
return -ENODEV; return -ENODEV;
} }
if (atomic_test_and_set_bit(adv.flags, ADV_FLAG_ACTIVE)) { if (atomic_test_and_set_bit(adv->flags, ADV_FLAG_ACTIVE)) {
BT_ERR("Advertiser is busy"); BT_ERR("Advertiser is busy");
return -EBUSY; return -EBUSY;
} }
if (atomic_test_bit(adv.flags, ADV_FLAG_UPDATE_PARAMS)) { if (atomic_test_bit(adv->flags, ADV_FLAG_UPDATE_PARAMS)) {
err = bt_le_ext_adv_update_param(adv.instance, param); err = bt_le_ext_adv_update_param(adv->instance, param);
if (err) { if (err) {
BT_ERR("Failed updating adv params: %d", err); BT_ERR("Failed updating adv params: %d", err);
atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE); atomic_clear_bit(adv->flags, ADV_FLAG_ACTIVE);
return err; return err;
} }
atomic_set_bit_to(adv.flags, ADV_FLAG_UPDATE_PARAMS, atomic_set_bit_to(adv->flags, ADV_FLAG_UPDATE_PARAMS,
param != &adv_param); param != &adv->adv_param);
} }
err = bt_le_ext_adv_set_data(adv.instance, ad, ad_len, sd, sd_len); err = bt_le_ext_adv_set_data(adv->instance, ad, ad_len, sd, sd_len);
if (err) { if (err) {
BT_ERR("Failed setting adv data: %d", err); BT_ERR("Failed setting adv data: %d", err);
atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE); atomic_clear_bit(adv->flags, ADV_FLAG_ACTIVE);
return err; return err;
} }
adv.timestamp = k_uptime_get(); adv->timestamp = k_uptime_get();
err = bt_le_ext_adv_start(adv.instance, start); err = bt_le_ext_adv_start(adv->instance, start);
if (err) { if (err) {
BT_ERR("Advertising failed: err %d", err); BT_ERR("Advertising failed: err %d", err);
atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE); atomic_clear_bit(adv->flags, ADV_FLAG_ACTIVE);
} }
return err; return err;
} }
static int buf_send(struct net_buf *buf) static int buf_send(struct ext_adv *adv, struct net_buf *buf)
{ {
struct bt_le_ext_adv_start_param start = { struct bt_le_ext_adv_start_param start = {
.num_events = .num_events =
@ -132,15 +195,15 @@ static int buf_send(struct net_buf *buf)
ad.data = buf->data; ad.data = buf->data;
/* Only update advertising parameters if they're different */ /* Only update advertising parameters if they're different */
if (adv_param.interval_min != BT_MESH_ADV_SCAN_UNIT(adv_int)) { if (adv->adv_param.interval_min != BT_MESH_ADV_SCAN_UNIT(adv_int)) {
adv_param.interval_min = BT_MESH_ADV_SCAN_UNIT(adv_int); adv->adv_param.interval_min = BT_MESH_ADV_SCAN_UNIT(adv_int);
adv_param.interval_max = adv_param.interval_min; adv->adv_param.interval_max = adv->adv_param.interval_min;
atomic_set_bit(adv.flags, ADV_FLAG_UPDATE_PARAMS); atomic_set_bit(adv->flags, ADV_FLAG_UPDATE_PARAMS);
} }
err = adv_start(&adv_param, &start, &ad, 1, NULL, 0); err = adv_start(adv, &adv->adv_param, &start, &ad, 1, NULL, 0);
if (!err) { if (!err) {
adv.buf = net_buf_ref(buf); adv->buf = net_buf_ref(buf);
} }
bt_mesh_adv_send_start(duration, err, BT_MESH_ADV(buf)); bt_mesh_adv_send_start(duration, err, BT_MESH_ADV(buf));
@ -148,35 +211,11 @@ static int buf_send(struct net_buf *buf)
return err; return err;
} }
static void send_pending_adv(struct k_work *work) #if defined(CONFIG_BT_MESH_GATT_SERVER)
static void gatt_server_adv_send(struct ext_adv *adv)
{ {
struct net_buf *buf;
int err; int err;
atomic_clear_bit(adv.flags, ADV_FLAG_SCHEDULED);
while ((buf = net_buf_get(&bt_mesh_adv_queue, K_NO_WAIT))) {
/* busy == 0 means this was canceled */
if (!BT_MESH_ADV(buf)->busy) {
net_buf_unref(buf);
continue;
}
BT_MESH_ADV(buf)->busy = 0U;
err = buf_send(buf);
net_buf_unref(buf);
if (!err) {
return; /* Wait for advertising to finish */
}
}
if (!IS_ENABLED(CONFIG_BT_MESH_GATT_SERVER)) {
return;
}
/* No more pending buffers */
if (bt_mesh_is_provisioned()) { if (bt_mesh_is_provisioned()) {
if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) { if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
err = bt_mesh_proxy_adv_start(); err = bt_mesh_proxy_adv_start();
@ -188,23 +227,70 @@ static void send_pending_adv(struct k_work *work)
} }
if (!err) { if (!err) {
atomic_set_bit(adv.flags, ADV_FLAG_PROXY); atomic_set_bit(adv->flags, ADV_FLAG_PROXY);
}
}
#endif /* CONFIG_BT_MESH_GATT_SERVER */
static void send_pending_adv(struct k_work *work)
{
struct ext_adv *adv = CONTAINER_OF(work, struct ext_adv, work.work);
struct net_buf *buf;
int err;
atomic_clear_bit(adv->flags, ADV_FLAG_SCHEDULED);
while ((buf = adv->handler(K_NO_WAIT))) {
/* busy == 0 means this was canceled */
if (!BT_MESH_ADV(buf)->busy) {
net_buf_unref(buf);
continue;
}
BT_MESH_ADV(buf)->busy = 0U;
err = buf_send(adv, buf);
net_buf_unref(buf);
if (!err) {
return; /* Wait for advertising to finish */
} }
} }
static void schedule_send(void) if (IS_ENABLED(CONFIG_BT_MESH_GATT_SERVER) &&
adv == BT_MESH_ADV_EXT_GATT_SEPARATE_INS) {
gatt_server_adv_send(adv);
}
}
#if defined(CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE)
static void send_pending_adv_gatt_handler(struct k_work *work)
{ {
uint64_t timestamp = adv.timestamp; struct ext_adv *adv = CONTAINER_OF(work, struct ext_adv, work.work);
gatt_server_adv_send(adv);
}
#endif /* CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE */
static bool schedule_send(struct ext_adv *adv)
{
uint64_t timestamp;
int64_t delta; int64_t delta;
if (atomic_test_and_clear_bit(adv.flags, ADV_FLAG_PROXY)) { if (!adv) {
bt_le_ext_adv_stop(adv.instance); return false;
atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE);
} }
if (atomic_test_bit(adv.flags, ADV_FLAG_ACTIVE) || timestamp = adv->timestamp;
atomic_test_and_set_bit(adv.flags, ADV_FLAG_SCHEDULED)) {
return; if (atomic_test_and_clear_bit(adv->flags, ADV_FLAG_PROXY)) {
(void)bt_le_ext_adv_stop(adv->instance);
atomic_clear_bit(adv->flags, ADV_FLAG_ACTIVE);
}
if (atomic_test_bit(adv->flags, ADV_FLAG_ACTIVE) ||
atomic_test_and_set_bit(adv->flags, ADV_FLAG_SCHEDULED)) {
return false;
} }
/* The controller will send the next advertisement immediately. /* The controller will send the next advertisement immediately.
@ -212,74 +298,148 @@ static void schedule_send(void)
* to the previous packet than what's permitted by the specification. * to the previous packet than what's permitted by the specification.
*/ */
delta = k_uptime_delta(&timestamp); delta = k_uptime_delta(&timestamp);
k_work_reschedule(&adv.work, K_MSEC(ADV_INT_FAST_MS - delta)); k_work_reschedule(&adv->work, K_MSEC(ADV_INT_FAST_MS - delta));
return true;
} }
void bt_mesh_adv_update(void) void bt_mesh_adv_update(void)
{ {
BT_DBG(""); (void)schedule_send(BT_MESH_ADV_EXT_GATT_SEPARATE_INS);
schedule_send();
} }
void bt_mesh_adv_buf_ready(void) void bt_mesh_adv_buf_local_ready(void)
{ {
schedule_send(); (void)schedule_send(&adv_main);
}
void bt_mesh_adv_buf_relay_ready(void)
{
struct bt_mesh_ext_adv *adv = relay_adv_get();
for (int i = 0; i < RELAY_ADV_COUNT; i++) {
if (schedule_send(&adv[i])) {
return;
}
}
} }
void bt_mesh_adv_init(void) void bt_mesh_adv_init(void)
{ {
k_work_init_delayable(&adv.work, send_pending_adv); }
static struct ext_adv *adv_instance_find(struct bt_le_ext_adv *instance)
{
if (adv_main.instance == instance) {
return &adv_main;
}
#if RELAY_ADV_COUNT
for (int i = 0; i < ARRAY_SIZE(adv_relay); i++) {
if (adv_relay[i].instance == instance) {
return &adv_relay[i];
}
}
#endif /* RELAY_ADV_COUNT */
#if defined(CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE)
if (adv_gatt.instance == instance) {
return &adv_gatt;
}
#endif
return NULL;
} }
static void adv_sent(struct bt_le_ext_adv *instance, static void adv_sent(struct bt_le_ext_adv *instance,
struct bt_le_ext_adv_sent_info *info) struct bt_le_ext_adv_sent_info *info)
{ {
struct ext_adv *adv = adv_instance_find(instance);
if (!adv) {
BT_WARN("Unexpected adv instance");
return;
}
/* Calling k_uptime_delta on a timestamp moves it to the current time. /* Calling k_uptime_delta on a timestamp moves it to the current time.
* This is essential here, as schedule_send() uses the end of the event * This is essential here, as schedule_send() uses the end of the event
* as a reference to avoid sending the next advertisement too soon. * as a reference to avoid sending the next advertisement too soon.
*/ */
int64_t duration = k_uptime_delta(&adv.timestamp); int64_t duration = k_uptime_delta(&adv->timestamp);
BT_DBG("Advertising stopped after %u ms", (uint32_t)duration); BT_DBG("Advertising stopped after %u ms", (uint32_t)duration);
atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE); atomic_clear_bit(adv->flags, ADV_FLAG_ACTIVE);
if (!atomic_test_and_clear_bit(adv.flags, ADV_FLAG_PROXY)) { if (!atomic_test_and_clear_bit(adv->flags, ADV_FLAG_PROXY)) {
net_buf_unref(adv.buf); net_buf_unref(adv->buf);
} }
schedule_send(); (void)schedule_send(adv);
} }
#if defined(CONFIG_BT_MESH_GATT_SERVER)
static void connected(struct bt_le_ext_adv *instance, static void connected(struct bt_le_ext_adv *instance,
struct bt_le_ext_adv_connected_info *info) struct bt_le_ext_adv_connected_info *info)
{ {
if (atomic_test_and_clear_bit(adv.flags, ADV_FLAG_PROXY)) { struct ext_adv *adv = BT_MESH_ADV_EXT_GATT_SEPARATE_INS;
atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE);
schedule_send(); if (atomic_test_and_clear_bit(adv->flags, ADV_FLAG_PROXY)) {
atomic_clear_bit(adv->flags, ADV_FLAG_ACTIVE);
(void)schedule_send(adv);
} }
} }
#endif /* CONFIG_BT_MESH_GATT_SERVER */
int bt_mesh_adv_enable(void) int bt_mesh_adv_enable(void)
{ {
int err;
static const struct bt_le_ext_adv_cb adv_cb = { static const struct bt_le_ext_adv_cb adv_cb = {
.sent = adv_sent, .sent = adv_sent,
#if defined(CONFIG_BT_MESH_GATT_SERVER)
.connected = connected, .connected = connected,
#endif /* CONFIG_BT_MESH_GATT_SERVER */
}; };
if (adv.instance) { if (adv_main.instance) {
/* Already initialized */ /* Already initialized */
return 0; return 0;
} }
return bt_le_ext_adv_create(&adv_param, &adv_cb, &adv.instance);
err = bt_le_ext_adv_create(&adv_main.adv_param, &adv_cb,
&adv_main.instance);
if (err) {
return err;
}
#if RELAY_ADV_COUNT
for (int i = 0; i < RELAY_ADV_COUNT; i++) {
err = bt_le_ext_adv_create(&adv_relay[i].adv_param, &adv_cb,
&adv_relay[i].instance);
if (err) {
return err;
}
}
#endif /* RELAY_ADV_COUNT */
#if defined(CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE)
err = bt_le_ext_adv_create(&adv_gatt.adv_param, &adv_cb,
&adv_gatt.instance);
if (err) {
return err;
}
#endif /* CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE */
return 0;
} }
int bt_mesh_adv_start(const struct bt_le_adv_param *param, int32_t duration, int bt_mesh_adv_start(const struct bt_le_adv_param *param, int32_t duration,
const struct bt_data *ad, size_t ad_len, const struct bt_data *ad, size_t ad_len,
const struct bt_data *sd, size_t sd_len) const struct bt_data *sd, size_t sd_len)
{ {
struct ext_adv *adv = BT_MESH_ADV_EXT_GATT_SEPARATE_INS;
struct bt_le_ext_adv_start_param start = { struct bt_le_ext_adv_start_param start = {
/* Timeout is set in 10 ms steps, with 0 indicating "forever" */ /* Timeout is set in 10 ms steps, with 0 indicating "forever" */
.timeout = (duration == SYS_FOREVER_MS) ? 0 : (duration / 10), .timeout = (duration == SYS_FOREVER_MS) ? 0 : (duration / 10),
@ -287,7 +447,7 @@ int bt_mesh_adv_start(const struct bt_le_adv_param *param, int32_t duration,
BT_DBG("Start advertising %d ms", duration); BT_DBG("Start advertising %d ms", duration);
atomic_set_bit(adv.flags, ADV_FLAG_UPDATE_PARAMS); atomic_set_bit(adv->flags, ADV_FLAG_UPDATE_PARAMS);
return adv_start(param, &start, ad, ad_len, sd, sd_len); return adv_start(adv, param, &start, ad, ad_len, sd, sd_len);
} }

View file

@ -131,7 +131,7 @@ static void adv_thread(void *p1, void *p2, void *p3)
struct net_buf *buf; struct net_buf *buf;
if (IS_ENABLED(CONFIG_BT_MESH_GATT_SERVER)) { if (IS_ENABLED(CONFIG_BT_MESH_GATT_SERVER)) {
buf = net_buf_get(&bt_mesh_adv_queue, K_NO_WAIT); buf = bt_mesh_adv_buf_get(K_NO_WAIT);
while (!buf) { while (!buf) {
/* Adv timeout may be set by a call from proxy /* Adv timeout may be set by a call from proxy
@ -148,12 +148,11 @@ static void adv_thread(void *p1, void *p2, void *p3)
BT_DBG("PB-GATT Advertising"); BT_DBG("PB-GATT Advertising");
} }
buf = net_buf_get(&bt_mesh_adv_queue, buf = bt_mesh_adv_buf_get(SYS_TIMEOUT_MS(adv_timeout));
SYS_TIMEOUT_MS(adv_timeout));
bt_le_adv_stop(); bt_le_adv_stop();
} }
} else { } else {
buf = net_buf_get(&bt_mesh_adv_queue, K_FOREVER); buf = bt_mesh_adv_buf_get(K_FOREVER);
} }
if (!buf) { if (!buf) {
@ -173,18 +172,21 @@ static void adv_thread(void *p1, void *p2, void *p3)
} }
} }
void bt_mesh_adv_update(void) void bt_mesh_adv_buf_local_ready(void)
{
BT_DBG("");
k_fifo_cancel_wait(&bt_mesh_adv_queue);
}
void bt_mesh_adv_buf_ready(void)
{ {
/* Will be handled automatically */ /* Will be handled automatically */
} }
void bt_mesh_adv_buf_relay_ready(void)
{
/* Will be handled automatically */
}
void bt_mesh_adv_update(void)
{
bt_mesh_adv_buf_get_cancel();
}
void bt_mesh_adv_init(void) void bt_mesh_adv_init(void)
{ {
k_thread_create(&adv_thread_data, adv_thread_stack, k_thread_create(&adv_thread_data, adv_thread_stack,