Bluetooth: Mesh: Introduce a second advertising callback

Some places of the code are interested in when the first advertising
event goes out. Others, on the other hand, are interested when the
last advertising event goes out. Some are even interested in both of
these. Instead of providing a single callback, provide a struct with
two possible callbacks for sending advertising PDUs.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
Johan Hedberg 2017-11-17 12:40:18 +02:00 committed by Johan Hedberg
commit c3ad883872
10 changed files with 123 additions and 74 deletions

View file

@ -70,24 +70,29 @@ static struct bt_mesh_adv *adv_alloc(int id)
return &adv_pool[id];
}
static inline void adv_sent(struct net_buf *buf, u16_t duration, int err)
static inline void adv_send_start(u16_t duration, int err,
const struct bt_mesh_adv_cb *cb,
void *cb_data)
{
if (BT_MESH_ADV(buf)->busy) {
BT_MESH_ADV(buf)->busy = 0;
if (BT_MESH_ADV(buf)->sent) {
BT_MESH_ADV(buf)->sent(buf, duration, err,
BT_MESH_ADV(buf)->user_data);
}
if (cb && cb->send_start) {
cb->send_start(duration, err, cb_data);
}
}
net_buf_unref(buf);
static inline void adv_send_end(int err, const struct bt_mesh_adv_cb *cb,
void *cb_data)
{
if (cb && cb->send_end) {
cb->send_end(err, cb_data);
}
}
static inline void adv_send(struct net_buf *buf)
{
const s32_t adv_int_min = ((bt_dev.hci_version >= BT_HCI_VERSION_5_0) ?
ADV_INT_FAST : ADV_INT_DEFAULT);
const struct bt_mesh_adv_cb *cb = BT_MESH_ADV(buf)->cb;
void *cb_data = BT_MESH_ADV(buf)->cb_data;
struct bt_le_adv_param param;
u16_t duration, adv_int;
struct bt_data ad;
@ -111,7 +116,8 @@ static inline void adv_send(struct net_buf *buf)
param.own_addr = NULL;
err = bt_le_adv_start(&param, &ad, 1, NULL, 0);
adv_sent(buf, duration, err);
net_buf_unref(buf);
adv_send_start(duration, err, cb, cb_data);
if (err) {
BT_ERR("Advertising failed: err %d", err);
return;
@ -122,6 +128,7 @@ static inline void adv_send(struct net_buf *buf)
k_sleep(duration);
err = bt_le_adv_stop();
adv_send_end(err, cb, cb_data);
if (err) {
BT_ERR("Stopping advertising failed: err %d", err);
return;
@ -158,6 +165,7 @@ static void adv_thread(void *p1, void *p2, void *p3)
/* busy == 0 means this was canceled */
if (BT_MESH_ADV(buf)->busy) {
BT_MESH_ADV(buf)->busy = 0;
adv_send(buf);
}
@ -209,14 +217,14 @@ struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, u8_t xmit_count,
xmit_count, xmit_int, timeout);
}
void bt_mesh_adv_send(struct net_buf *buf, bt_mesh_adv_func_t sent,
void *user_data)
void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_adv_cb *cb,
void *cb_data)
{
BT_DBG("type 0x%02x len %u: %s", BT_MESH_ADV(buf)->type, buf->len,
bt_hex(buf->data, buf->len));
BT_MESH_ADV(buf)->sent = sent;
BT_MESH_ADV(buf)->user_data = user_data;
BT_MESH_ADV(buf)->cb = cb;
BT_MESH_ADV(buf)->cb_data = cb_data;
BT_MESH_ADV(buf)->busy = 1;
net_buf_put(&adv_queue, net_buf_ref(buf));

View file

@ -23,9 +23,14 @@ enum bt_mesh_adv_type {
typedef void (*bt_mesh_adv_func_t)(struct net_buf *buf, u16_t duration,
int err, void *user_data);
struct bt_mesh_adv_cb {
void (*send_start)(u16_t duration, int err, void *user_data);
void (*send_end)(int err, void *user_data);
};
struct bt_mesh_adv {
bt_mesh_adv_func_t sent;
void *user_data;
const struct bt_mesh_adv_cb *cb;
void *cb_data;
u8_t type:2,
busy:1;
@ -54,8 +59,8 @@ struct net_buf *bt_mesh_adv_create_from_pool(struct net_buf_pool *pool,
u8_t xmit_count, u8_t xmit_int,
s32_t timeout);
void bt_mesh_adv_send(struct net_buf *buf, bt_mesh_adv_func_t sent,
void *user_data);
void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_adv_cb *cb,
void *cb_data);
void bt_mesh_adv_update(void);

View file

@ -73,14 +73,13 @@ static void cache_add(u8_t data[21], u16_t net_idx)
memcpy(beacon_cache[net_idx].data, data, 21);
}
static void beacon_complete(struct net_buf *buf, u16_t duration, int err,
void *user_data)
static void beacon_complete(int err, void *user_data)
{
struct bt_mesh_subnet *sub = user_data;
BT_DBG("err %d", err);
sub->beacon_sent = k_uptime_get_32() + duration;
sub->beacon_sent = k_uptime_get_32();
}
void bt_mesh_beacon_create(struct bt_mesh_subnet *sub,
@ -119,6 +118,9 @@ void bt_mesh_beacon_create(struct bt_mesh_subnet *sub,
static int secure_beacon_send(void)
{
static const struct bt_mesh_adv_cb send_cb = {
.send_end = beacon_complete,
};
u32_t now = k_uptime_get_32();
int i;
@ -153,7 +155,7 @@ static int secure_beacon_send(void)
bt_mesh_beacon_create(sub, &buf->b);
bt_mesh_adv_send(buf, beacon_complete, sub);
bt_mesh_adv_send(buf, &send_cb, sub);
net_buf_unref(buf);
}

View file

@ -604,16 +604,19 @@ static struct bt_mesh_friend *find_clear(u16_t prev_friend)
return NULL;
}
static void friend_clear_sent(struct net_buf *buf, u16_t duration, int err,
void *user_data)
static void friend_clear_sent(int err, void *user_data)
{
struct bt_mesh_friend *frnd = user_data;
k_delayed_work_submit(&frnd->clear.timer,
duration + K_SECONDS(frnd->clear.repeat_sec));
K_SECONDS(frnd->clear.repeat_sec));
frnd->clear.repeat_sec *= 2;
}
static const struct bt_mesh_adv_cb clear_sent_cb = {
.send_end = friend_clear_sent,
};
static void send_friend_clear(struct bt_mesh_friend *frnd)
{
struct bt_mesh_msg_ctx ctx = {
@ -636,7 +639,7 @@ static void send_friend_clear(struct bt_mesh_friend *frnd)
BT_DBG("");
bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR, &req,
sizeof(req), NULL, friend_clear_sent, frnd);
sizeof(req), NULL, &clear_sent_cb, frnd);
}
static void clear_timeout(struct k_work *work)
@ -945,21 +948,27 @@ static void enqueue_friend_pdu(struct bt_mesh_friend *frnd,
}
}
static void buf_sent(struct net_buf *buf, u16_t duration, int err,
void *user_data)
static void buf_send_start(u16_t duration, int err, void *user_data)
{
struct bt_mesh_friend *frnd = user_data;
BT_DBG("buf %p err %d", buf, err);
BT_DBG("err %d", err);
frnd->pending_buf = 0;
}
static void buf_send_end(int err, void *user_data)
{
struct bt_mesh_friend *frnd = user_data;
BT_DBG("err %d", err);
if (frnd->established) {
k_delayed_work_submit(&frnd->timer, duration + frnd->poll_to);
k_delayed_work_submit(&frnd->timer, frnd->poll_to);
BT_DBG("Waiting %u ms for next poll", frnd->poll_to);
} else {
/* Friend offer timeout is 1 second */
k_delayed_work_submit(&frnd->timer, duration + K_SECONDS(1));
k_delayed_work_submit(&frnd->timer, K_SECONDS(1));
BT_DBG("Waiting for first poll");
/* Friend Offer doesn't follow the re-sending semantics */
@ -972,6 +981,10 @@ static void friend_timeout(struct k_work *work)
{
struct bt_mesh_friend *frnd = CONTAINER_OF(work, struct bt_mesh_friend,
timer.work);
static const struct bt_mesh_adv_cb buf_sent_cb = {
.send_start = buf_send_start,
.send_end = buf_send_end,
};
__ASSERT_NO_MSG(frnd->pending_buf == 0);
@ -1005,7 +1018,7 @@ static void friend_timeout(struct k_work *work)
send_last:
frnd->pending_buf = 1;
bt_mesh_adv_send(frnd->last, buf_sent, frnd);
bt_mesh_adv_send(frnd->last, &buf_sent_cb, frnd);
}
int bt_mesh_friend_init(void)

View file

@ -103,8 +103,7 @@ static inline void lpn_set_state(int state)
static void clear_friendship(bool force, bool disable);
static void friend_clear_sent(struct net_buf *buf, u16_t duration, int err,
void *user_data)
static void friend_clear_sent(int err, void *user_data)
{
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
@ -123,9 +122,13 @@ static void friend_clear_sent(struct net_buf *buf, u16_t duration, int err,
}
lpn_set_state(BT_MESH_LPN_CLEAR);
k_delayed_work_submit(&lpn->timer, duration + FRIEND_REQ_TIMEOUT);
k_delayed_work_submit(&lpn->timer, FRIEND_REQ_TIMEOUT);
}
static const struct bt_mesh_adv_cb clear_sent_cb = {
.send_end = friend_clear_sent,
};
static int send_friend_clear(void)
{
struct bt_mesh_msg_ctx ctx = {
@ -148,7 +151,7 @@ static int send_friend_clear(void)
BT_DBG("");
return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR, &req,
sizeof(req), NULL, friend_clear_sent, NULL);
sizeof(req), NULL, &clear_sent_cb, NULL);
}
static void clear_friendship(bool force, bool disable)
@ -199,8 +202,7 @@ static void clear_friendship(bool force, bool disable)
k_delayed_work_submit(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT);
}
static void friend_req_sent(struct net_buf *buf, u16_t duration, int err,
void *user_data)
static void friend_req_sent(u16_t duration, int err, void *user_data)
{
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
@ -221,6 +223,10 @@ static void friend_req_sent(struct net_buf *buf, u16_t duration, int err,
}
}
static const struct bt_mesh_adv_cb friend_req_sent_cb = {
.send_start = friend_req_sent,
};
static int send_friend_req(struct bt_mesh_lpn *lpn)
{
const struct bt_mesh_comp *comp = bt_mesh_comp_get();
@ -248,7 +254,7 @@ static int send_friend_req(struct bt_mesh_lpn *lpn)
BT_DBG("");
return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_REQ, &req,
sizeof(req), NULL, friend_req_sent, NULL);
sizeof(req), NULL, &friend_req_sent_cb, NULL);
}
static inline void group_zero(atomic_t *target)
@ -290,13 +296,13 @@ static inline void group_clear(atomic_t *target, atomic_t *source)
#endif
}
static void req_sent(struct net_buf *buf, u16_t duration, int err,
void *user_data)
static void req_sent(u16_t duration, int err, void *user_data)
{
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
#if defined(CONFIG_BT_MESH_DEBUG_LOW_POWER)
BT_DBG("buf %p err %d state %s", buf, err, state2str(lpn->state));
BT_DBG("duration %u err %d state %s",
duration, err, state2str(lpn->state));
#endif
if (err) {
@ -323,6 +329,10 @@ static void req_sent(struct net_buf *buf, u16_t duration, int err,
}
}
static const struct bt_mesh_adv_cb req_sent_cb = {
.send_start = req_sent,
};
static int send_friend_poll(void)
{
struct bt_mesh_msg_ctx ctx = {
@ -353,7 +363,7 @@ static int send_friend_poll(void)
}
err = bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_POLL, &fsn, 1,
NULL, req_sent, NULL);
NULL, &req_sent_cb, NULL);
if (err == 0) {
lpn->pending_poll = 0;
lpn->sent_req = TRANS_CTL_OP_FRIEND_POLL;
@ -673,7 +683,7 @@ static bool sub_update(u8_t op)
req.xact = lpn->xact_next++;
if (bt_mesh_ctl_send(&tx, op, &req, 1 + g * 2, NULL,
req_sent, NULL) < 0) {
&req_sent_cb, NULL) < 0) {
group_zero(lpn->pending);
return false;
}

View file

@ -670,7 +670,8 @@ do_update:
}
int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct net_buf *buf,
bool new_key, bt_mesh_adv_func_t cb, void *user_data)
bool new_key, const struct bt_mesh_adv_cb *cb,
void *cb_data)
{
const u8_t *enc, *priv;
int err;
@ -710,7 +711,7 @@ int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct net_buf *buf,
return err;
}
bt_mesh_adv_send(buf, cb, user_data);
bt_mesh_adv_send(buf, cb, cb_data);
if (!bt_mesh.iv_update && bt_mesh.seq > IV_UPDATE_SEQ_LIMIT) {
bt_mesh_beacon_ivu_initiator(true);
@ -799,7 +800,7 @@ int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct net_buf_simple *buf,
}
int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf,
bt_mesh_adv_func_t cb, void *user_data)
const struct bt_mesh_adv_cb *cb, void *cb_data)
{
int err;
@ -830,13 +831,16 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf,
/* Deliver to local network interface if necessary */
if (bt_mesh_fixed_group_match(tx->ctx->addr) ||
bt_mesh_elem_find(tx->ctx->addr)) {
if (cb && cb->send_start) {
cb->send_start(0, 0, cb_data);
}
net_buf_slist_put(&bt_mesh.local_queue, net_buf_ref(buf));
if (cb) {
cb(buf, 0, 0, user_data);
if (cb && cb->send_end) {
cb->send_end(0, cb_data);
}
k_work_submit(&bt_mesh.local_work);
} else {
bt_mesh_adv_send(buf, cb, user_data);
bt_mesh_adv_send(buf, cb, cb_data);
}
done:

View file

@ -310,10 +310,11 @@ int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct net_buf_simple *buf,
bool proxy);
int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf,
bt_mesh_adv_func_t cb, void *user_data);
const struct bt_mesh_adv_cb *cb, void *cb_data);
int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct net_buf *buf,
bool new_key, bt_mesh_adv_func_t cb, void *user_data);
bool new_key, const struct bt_mesh_adv_cb *cb,
void *cb_data);
int bt_mesh_net_decode(struct net_buf_simple *data, enum bt_mesh_net_if net_if,
struct bt_mesh_net_rx *rx, struct net_buf_simple *buf);

View file

@ -188,17 +188,19 @@ static const struct bt_mesh_prov *prov;
static void close_link(u8_t err, u8_t reason);
#if defined(CONFIG_BT_MESH_PB_ADV)
static void buf_sent(struct net_buf *buf, u16_t duration, int err,
void *user_data)
static void buf_sent(int err, void *user_data)
{
if (!link.tx.buf[0]) {
return;
}
k_delayed_work_submit(&link.tx.retransmit,
duration + RETRANSMIT_TIMEOUT);
k_delayed_work_submit(&link.tx.retransmit, RETRANSMIT_TIMEOUT);
}
static struct bt_mesh_adv_cb buf_sent_cb = {
.send_end = buf_sent,
};
static void free_segments(void)
{
int i;
@ -272,8 +274,7 @@ static struct net_buf *adv_buf_create(void)
static u8_t pending_ack = XACT_NVAL;
static void ack_complete(struct net_buf *buf, u16_t duration, int err,
void *user_data)
static void ack_complete(u16_t duration, int err, void *user_data)
{
BT_DBG("xact %u complete", (u8_t)pending_ack);
pending_ack = XACT_NVAL;
@ -281,7 +282,10 @@ static void ack_complete(struct net_buf *buf, u16_t duration, int err,
static void gen_prov_ack_send(u8_t xact_id)
{
bt_mesh_adv_func_t complete;
static const struct bt_mesh_adv_cb cb = {
.send_start = ack_complete,
};
const struct bt_mesh_adv_cb *complete;
struct net_buf *buf;
BT_DBG("xact_id %u", xact_id);
@ -298,7 +302,7 @@ static void gen_prov_ack_send(u8_t xact_id)
if (pending_ack == XACT_NVAL) {
pending_ack = xact_id;
complete = ack_complete;
complete = &cb;
} else {
complete = NULL;
}
@ -327,7 +331,7 @@ static void send_reliable(void)
if (i + 1 < ARRAY_SIZE(link.tx.buf) && link.tx.buf[i + 1]) {
bt_mesh_adv_send(buf, NULL, NULL);
} else {
bt_mesh_adv_send(buf, buf_sent, NULL);
bt_mesh_adv_send(buf, &buf_sent_cb, NULL);
}
}
}
@ -1139,7 +1143,7 @@ static void prov_retransmit(struct k_work *work)
if (i + 1 < ARRAY_SIZE(link.tx.buf) && link.tx.buf[i + 1]) {
bt_mesh_adv_send(buf, NULL, NULL);
} else {
bt_mesh_adv_send(buf, buf_sent, NULL);
bt_mesh_adv_send(buf, &buf_sent_cb, NULL);
}
}

View file

@ -198,15 +198,17 @@ static inline void seg_tx_complete(struct seg_tx *tx, int err)
seg_tx_reset(tx);
}
static void seg_sent(struct net_buf *buf, u16_t duration, int err,
void *user_data)
static void seg_sent(int err, void *user_data)
{
struct seg_tx *tx = user_data;
k_delayed_work_submit(&tx->retransmit,
duration + SEG_RETRANSMIT_TIMEOUT);
k_delayed_work_submit(&tx->retransmit, SEG_RETRANSMIT_TIMEOUT);
}
static const struct bt_mesh_adv_cb seg_sent_cb = {
.send_end = seg_sent,
};
static void seg_tx_send_unacked(struct seg_tx *tx)
{
int i, err;
@ -231,8 +233,8 @@ static void seg_tx_send_unacked(struct seg_tx *tx)
BT_DBG("resending %u/%u", i, tx->seg_n);
err = bt_mesh_net_resend(tx->sub, seg, tx->new_key, seg_sent,
tx);
err = bt_mesh_net_resend(tx->sub, seg, tx->new_key,
&seg_sent_cb, tx);
if (err) {
BT_ERR("Sending segment failed");
seg_tx_complete(tx, -EIO);
@ -357,7 +359,7 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, u8_t aid,
BT_DBG("Sending %u/%u", seg_o, tx->seg_n);
err = bt_mesh_net_send(net_tx, seg, seg_sent, tx);
err = bt_mesh_net_send(net_tx, seg, &seg_sent_cb, tx);
if (err) {
BT_ERR("Sending segment failed");
seg_tx_reset(tx);
@ -823,8 +825,8 @@ static inline s32_t ack_timeout(struct seg_rx *rx)
}
int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, u8_t ctl_op, void *data,
size_t data_len, u64_t *seq_auth, bt_mesh_adv_func_t cb,
void *user_data)
size_t data_len, u64_t *seq_auth,
const struct bt_mesh_adv_cb *cb, void *cb_data)
{
struct net_buf *buf;
@ -858,7 +860,7 @@ int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, u8_t ctl_op, void *data,
}
}
return bt_mesh_net_send(tx, buf, cb, user_data);
return bt_mesh_net_send(tx, buf, cb, cb_data);
}
static int send_ack(struct bt_mesh_subnet *sub, u16_t src, u16_t dst,

View file

@ -83,8 +83,8 @@ bool bt_mesh_tx_in_progress(void);
void bt_mesh_rx_reset(void);
int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, u8_t ctl_op, void *data,
size_t data_len, u64_t *seq_auth, bt_mesh_adv_func_t cb,
void *user_data);
size_t data_len, u64_t *seq_auth,
const struct bt_mesh_adv_cb *cb, void *cb_data);
int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg,
bt_mesh_cb_t cb, void *cb_data);