in nimble/host/mesh/src/lpn.c [687:757]
static bool sub_update(uint8_t op)
{
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
int added_count = group_popcount(lpn->added);
struct bt_mesh_msg_ctx ctx = {
.net_idx = lpn->sub->net_idx,
.app_idx = BT_MESH_KEY_UNUSED,
.addr = lpn->frnd,
.send_ttl = 0,
};
struct bt_mesh_net_tx tx = {
.sub = lpn->sub,
.ctx = &ctx,
.src = bt_mesh_primary_addr(),
.xmit = POLL_XMIT,
.friend_cred = true,
};
struct bt_mesh_ctl_friend_sub req;
size_t i, g;
BT_DBG("op 0x%02x sent_req 0x%02x", op, lpn->sent_req);
if (lpn->sent_req) {
return false;
}
for (i = 0, g = 0; i < ARRAY_SIZE(lpn->groups); i++) {
if (lpn->groups[i] == BT_MESH_ADDR_UNASSIGNED) {
continue;
}
if (op == TRANS_CTL_OP_FRIEND_SUB_ADD) {
if (atomic_test_bit(lpn->added, i)) {
continue;
}
} else {
if (!atomic_test_bit(lpn->to_remove, i)) {
continue;
}
}
if (added_count + g >= lpn->queue_size) {
BT_WARN("Friend Queue Size exceeded");
break;
}
req.addr_list[g++] = sys_cpu_to_be16(lpn->groups[i]);
atomic_set_bit(lpn->pending, i);
if (g == ARRAY_SIZE(req.addr_list)) {
break;
}
}
if (g == 0) {
group_zero(lpn->pending);
return false;
}
req.xact = lpn->xact_next++;
if (bt_mesh_ctl_send(&tx, op, &req, 1 + g * 2,
&req_sent_cb, NULL) < 0) {
group_zero(lpn->pending);
return false;
}
lpn->xact_pending = req.xact;
lpn->sent_req = op;
return true;
}