in nimble/host/mesh/src/lpn.c [786:860]
static void lpn_timeout(struct ble_npl_event *work)
{
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
#if MYNEWT_VAL(BLE_MESH_LOW_POWER_LOG_LVL) == LOG_LEVEL_DEBUG
BT_DBG("state: %s", state2str(lpn->state));
#endif
switch (lpn->state) {
case BT_MESH_LPN_DISABLED:
break;
case BT_MESH_LPN_CLEAR:
clear_friendship(false, bt_mesh.lpn.disable);
break;
case BT_MESH_LPN_TIMER:
BT_DBG("Starting to look for Friend nodes");
lpn_set_state(BT_MESH_LPN_ENABLED);
if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
bt_mesh_scan_disable();
}
/* fall through */
case BT_MESH_LPN_ENABLED:
send_friend_req(lpn);
break;
case BT_MESH_LPN_REQ_WAIT:
bt_mesh_scan_enable();
k_work_reschedule(&lpn->timer,
lpn->adv_duration + FRIEND_REQ_SCAN);
lpn_set_state(BT_MESH_LPN_WAIT_OFFER);
break;
case BT_MESH_LPN_WAIT_OFFER:
BT_WARN("No acceptable Friend Offers received");
if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
bt_mesh_scan_disable();
}
lpn->lpn_counter++;
lpn_set_state(BT_MESH_LPN_ENABLED);
lpn->sent_req = 0U;
k_work_reschedule(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT);
break;
case BT_MESH_LPN_ESTABLISHED:
if (lpn->req_attempts < REQ_ATTEMPTS(lpn)) {
uint8_t req = lpn->sent_req;
lpn->sent_req = 0U;
if (!req || req == TRANS_CTL_OP_FRIEND_POLL) {
send_friend_poll();
} else {
sub_update(req);
}
break;
}
BT_ERR("No response from Friend after %u retries",
lpn->req_attempts);
lpn->req_attempts = 0;
clear_friendship(false, false);
break;
case BT_MESH_LPN_RECV_DELAY:
k_work_reschedule(&lpn->timer,
lpn->adv_duration + SCAN_LATENCY +
lpn->recv_win);
bt_mesh_scan_enable();
lpn_set_state(BT_MESH_LPN_WAIT_UPDATE);
break;
case BT_MESH_LPN_WAIT_UPDATE:
update_timeout(lpn);
break;
default:
__ASSERT(0, "Unhandled LPN state");
break;
}
}