Bluetooth: Mesh: Use more accurate timing for LPN functions
Update the advertising callback to include the exact duration that we will be sending out the packet. This is useful since sometimes we want to use the end point of the advertising as the reference time to count when some other action should take place. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
parent
e74f4a6c39
commit
1d86ef0955
9 changed files with 43 additions and 33 deletions
|
@ -63,13 +63,13 @@ static const u8_t adv_type[] = {
|
|||
NET_BUF_POOL_DEFINE(adv_buf_pool, CONFIG_BT_MESH_ADV_BUF_COUNT,
|
||||
BT_MESH_ADV_DATA_SIZE, sizeof(struct bt_mesh_adv), NULL);
|
||||
|
||||
static inline void adv_sent(struct net_buf *buf, int err)
|
||||
static inline void adv_sent(struct net_buf *buf, u16_t duration, int err)
|
||||
{
|
||||
if (BT_MESH_ADV(buf)->busy) {
|
||||
BT_MESH_ADV(buf)->busy = 0;
|
||||
|
||||
if (BT_MESH_ADV(buf)->sent) {
|
||||
BT_MESH_ADV(buf)->sent(buf, err);
|
||||
BT_MESH_ADV(buf)->sent(buf, duration, err);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ static inline void adv_send(struct net_buf *buf)
|
|||
param.own_addr = NULL;
|
||||
|
||||
err = bt_le_adv_start(¶m, &ad, 1, NULL, 0);
|
||||
adv_sent(buf, err);
|
||||
adv_sent(buf, duration, err);
|
||||
if (err) {
|
||||
BT_ERR("Advertising failed: err %d", err);
|
||||
return;
|
||||
|
|
|
@ -17,7 +17,8 @@ enum bt_mesh_adv_type {
|
|||
BT_MESH_ADV_BEACON,
|
||||
};
|
||||
|
||||
typedef void (*bt_mesh_adv_func_t)(struct net_buf *buf, int err);
|
||||
typedef void (*bt_mesh_adv_func_t)(struct net_buf *buf, u16_t duration,
|
||||
int err);
|
||||
|
||||
struct bt_mesh_adv {
|
||||
bt_mesh_adv_func_t sent;
|
||||
|
|
|
@ -73,14 +73,14 @@ 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, int err)
|
||||
static void beacon_complete(struct net_buf *buf, u16_t duration, int err)
|
||||
{
|
||||
struct bt_mesh_subnet *sub;
|
||||
|
||||
BT_DBG("err %d", err);
|
||||
|
||||
sub = &bt_mesh.sub[BT_MESH_ADV(buf)->user_data[0]];
|
||||
sub->beacon_sent = k_uptime_get_32();
|
||||
sub->beacon_sent = k_uptime_get_32() + duration;
|
||||
}
|
||||
|
||||
void bt_mesh_beacon_create(struct bt_mesh_subnet *sub,
|
||||
|
|
|
@ -780,7 +780,7 @@ static void enqueue_friend_pdu(struct bt_mesh_friend *frnd,
|
|||
}
|
||||
}
|
||||
|
||||
static void buf_sent(struct net_buf *buf, int err)
|
||||
static void buf_sent(struct net_buf *buf, u16_t duration, int err)
|
||||
{
|
||||
struct bt_mesh_friend *frnd = NULL;
|
||||
int i;
|
||||
|
@ -801,11 +801,11 @@ static void buf_sent(struct net_buf *buf, int err)
|
|||
frnd->pending_buf = 0;
|
||||
|
||||
if (frnd->established) {
|
||||
k_delayed_work_submit(&frnd->timer, frnd->poll_to);
|
||||
k_delayed_work_submit(&frnd->timer, duration + 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, K_SECONDS(1));
|
||||
k_delayed_work_submit(&frnd->timer, duration + K_SECONDS(1));
|
||||
BT_DBG("Waiting for first poll");
|
||||
|
||||
/* Friend Offer doesn't follow the re-sending semantics */
|
||||
|
|
|
@ -44,14 +44,13 @@
|
|||
|
||||
#define POLL_RETRY_TIMEOUT K_MSEC(100)
|
||||
|
||||
#define REQ_ATTEMPTS(lpn) ((lpn)->poll_timeout < K_SECONDS(3) ? 2 : 4)
|
||||
#define REQ_RETRY_DURATION(lpn) (4 * (LPN_RECV_DELAY + (lpn)->adv_duration + \
|
||||
(lpn)->recv_win + POLL_RETRY_TIMEOUT))
|
||||
|
||||
#define REQ_RETRY_DURATION(lpn) (REQ_ATTEMPTS(lpn) * \
|
||||
(LPN_RECV_DELAY + (lpn)->recv_win + \
|
||||
POLL_RETRY_TIMEOUT))
|
||||
#define POLL_TIMEOUT_MAX(lpn) ((CONFIG_BT_MESH_LPN_POLL_TIMEOUT * 100) - \
|
||||
REQ_RETRY_DURATION(lpn))
|
||||
|
||||
#define POLL_TIMEOUT(lpn) ((CONFIG_BT_MESH_LPN_POLL_TIMEOUT * 100) - \
|
||||
REQ_RETRY_DURATION(lpn))
|
||||
#define REQ_ATTEMPTS(lpn) (POLL_TIMEOUT_MAX(lpn) < K_SECONDS(3) ? 2 : 4)
|
||||
|
||||
#define CLEAR_ATTEMPTS 2
|
||||
|
||||
|
@ -100,7 +99,7 @@ static inline void lpn_set_state(int state)
|
|||
|
||||
static void clear_friendship(bool disable);
|
||||
|
||||
static void friend_clear_sent(struct net_buf *buf, int err)
|
||||
static void friend_clear_sent(struct net_buf *buf, u16_t duration, int err)
|
||||
{
|
||||
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
|
||||
|
||||
|
@ -119,7 +118,7 @@ static void friend_clear_sent(struct net_buf *buf, int err)
|
|||
}
|
||||
|
||||
lpn_set_state(BT_MESH_LPN_CLEAR);
|
||||
k_delayed_work_submit(&bt_mesh.lpn.timer, FRIEND_REQ_TIMEOUT);
|
||||
k_delayed_work_submit(&lpn->timer, duration + FRIEND_REQ_TIMEOUT);
|
||||
}
|
||||
|
||||
static int send_friend_clear(void)
|
||||
|
@ -194,7 +193,7 @@ static void clear_friendship(bool disable)
|
|||
k_delayed_work_submit(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT);
|
||||
}
|
||||
|
||||
static void friend_req_sent(struct net_buf *buf, int err)
|
||||
static void friend_req_sent(struct net_buf *buf, u16_t duration, int err)
|
||||
{
|
||||
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
|
||||
|
||||
|
@ -283,7 +282,7 @@ static inline void group_clear(atomic_t *target, atomic_t *source)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void req_sent(struct net_buf *buf, int err)
|
||||
static void req_sent(struct net_buf *buf, u16_t duration, int err)
|
||||
{
|
||||
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
|
||||
|
||||
|
@ -299,6 +298,7 @@ static void req_sent(struct net_buf *buf, int err)
|
|||
}
|
||||
|
||||
lpn->req_attempts++;
|
||||
lpn->adv_duration = duration;
|
||||
|
||||
if (lpn->established || IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
|
||||
lpn_set_state(BT_MESH_LPN_RECV_DELAY);
|
||||
|
@ -309,7 +309,8 @@ static void req_sent(struct net_buf *buf, int err)
|
|||
LPN_RECV_DELAY - SCAN_LATENCY);
|
||||
} else {
|
||||
k_delayed_work_submit(&lpn->timer,
|
||||
LPN_RECV_DELAY + lpn->recv_win);
|
||||
LPN_RECV_DELAY + duration +
|
||||
lpn->recv_win);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -722,7 +723,8 @@ static void lpn_timeout(struct k_work *work)
|
|||
break;
|
||||
case BT_MESH_LPN_REQ_WAIT:
|
||||
bt_mesh_scan_enable();
|
||||
k_delayed_work_submit(&lpn->timer, FRIEND_REQ_SCAN);
|
||||
k_delayed_work_submit(&lpn->timer,
|
||||
lpn->adv_duration + FRIEND_REQ_SCAN);
|
||||
lpn_set_state(BT_MESH_LPN_WAIT_OFFER);
|
||||
break;
|
||||
case BT_MESH_LPN_WAIT_OFFER:
|
||||
|
@ -755,10 +757,11 @@ static void lpn_timeout(struct k_work *work)
|
|||
clear_friendship(false);
|
||||
break;
|
||||
case BT_MESH_LPN_RECV_DELAY:
|
||||
k_delayed_work_submit(&lpn->timer,
|
||||
lpn->adv_duration + SCAN_LATENCY +
|
||||
lpn->recv_win);
|
||||
bt_mesh_scan_enable();
|
||||
lpn_set_state(BT_MESH_LPN_WAIT_UPDATE);
|
||||
k_delayed_work_submit(&lpn->timer,
|
||||
lpn->recv_win + SCAN_LATENCY);
|
||||
break;
|
||||
case BT_MESH_LPN_WAIT_UPDATE:
|
||||
update_timeout(lpn);
|
||||
|
@ -804,12 +807,13 @@ static s32_t poll_timeout(struct bt_mesh_lpn *lpn)
|
|||
{
|
||||
/* If we're waiting for segment acks keep polling at high freq */
|
||||
if (bt_mesh_tx_in_progress()) {
|
||||
return min(POLL_TIMEOUT(lpn), K_SECONDS(1));
|
||||
return min(POLL_TIMEOUT_MAX(lpn), K_SECONDS(1));
|
||||
}
|
||||
|
||||
if (lpn->poll_timeout < POLL_TIMEOUT(lpn)) {
|
||||
if (lpn->poll_timeout < POLL_TIMEOUT_MAX(lpn)) {
|
||||
lpn->poll_timeout *= 2;
|
||||
lpn->poll_timeout = min(lpn->poll_timeout, POLL_TIMEOUT(lpn));
|
||||
lpn->poll_timeout = min(lpn->poll_timeout,
|
||||
POLL_TIMEOUT_MAX(lpn));
|
||||
}
|
||||
|
||||
BT_DBG("Poll Timeout is %ums", lpn->poll_timeout);
|
||||
|
@ -926,7 +930,7 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
|
|||
BT_INFO("Friendship established with 0x%04x", lpn->frnd);
|
||||
|
||||
/* Set initial poll timeout */
|
||||
lpn->poll_timeout = min(POLL_TIMEOUT(lpn), K_SECONDS(1));
|
||||
lpn->poll_timeout = min(POLL_TIMEOUT_MAX(lpn), K_SECONDS(1));
|
||||
}
|
||||
|
||||
friend_response_received(lpn);
|
||||
|
|
|
@ -841,7 +841,7 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf,
|
|||
bt_mesh_elem_find(tx->ctx->addr)) {
|
||||
net_buf_put(&bt_mesh.local_queue, net_buf_ref(buf));
|
||||
if (cb) {
|
||||
cb(buf, 0);
|
||||
cb(buf, 0, 0);
|
||||
}
|
||||
k_work_submit(&bt_mesh.local_work);
|
||||
} else {
|
||||
|
|
|
@ -168,6 +168,9 @@ struct bt_mesh_lpn {
|
|||
/* Previous Friend of this LPN */
|
||||
u16_t old_friend;
|
||||
|
||||
/* Duration reported for last advertising packet */
|
||||
u16_t adv_duration;
|
||||
|
||||
/* Next LPN related action timer */
|
||||
struct k_delayed_work timer;
|
||||
|
||||
|
|
|
@ -188,13 +188,14 @@ 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, int err)
|
||||
static void buf_sent(struct net_buf *buf, u16_t duration, int err)
|
||||
{
|
||||
if (!link.tx.buf[0]) {
|
||||
return;
|
||||
}
|
||||
|
||||
k_delayed_work_submit(&link.tx.retransmit, RETRANSMIT_TIMEOUT);
|
||||
k_delayed_work_submit(&link.tx.retransmit,
|
||||
duration + RETRANSMIT_TIMEOUT);
|
||||
}
|
||||
|
||||
static void free_segments(void)
|
||||
|
@ -266,7 +267,7 @@ static struct net_buf *adv_buf_create(void)
|
|||
|
||||
static u8_t pending_ack = XACT_NVAL;
|
||||
|
||||
static void ack_complete(struct net_buf *buf, int err)
|
||||
static void ack_complete(struct net_buf *buf, u16_t duration, int err)
|
||||
{
|
||||
BT_DBG("xact %u complete", (u8_t)pending_ack);
|
||||
pending_ack = XACT_NVAL;
|
||||
|
|
|
@ -200,11 +200,12 @@ static inline void seg_tx_complete(struct seg_tx *tx, int err)
|
|||
seg_tx_reset(tx);
|
||||
}
|
||||
|
||||
static void seg_sent(struct net_buf *buf, int err)
|
||||
static void seg_sent(struct net_buf *buf, u16_t duration, int err)
|
||||
{
|
||||
struct seg_tx *tx = &seg_tx[BT_MESH_ADV(buf)->seg.tx_id];
|
||||
|
||||
k_delayed_work_submit(&tx->retransmit, SEG_RETRANSMIT_TIMEOUT);
|
||||
k_delayed_work_submit(&tx->retransmit,
|
||||
duration + SEG_RETRANSMIT_TIMEOUT);
|
||||
}
|
||||
|
||||
static void seg_tx_send_unacked(struct seg_tx *tx)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue