Bluetooth: Mesh: Add support for suspend/resume
In some cases the Friendship & Low Power Node features aren't available or feasible, however power saving is nevertheless required. This patch introduces two new APIs to suspend and resume the Mesh network. Currently, what this impacts is the LE scanning, the ability to allocate new outgoing buffers, as well as the model publishing, beacon and heartbeat timers. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
parent
3e11177a06
commit
e5b8f60bb6
6 changed files with 114 additions and 0 deletions
|
@ -279,6 +279,27 @@ int bt_mesh_init(const struct bt_mesh_prov *prov,
|
|||
*/
|
||||
void bt_mesh_reset(void);
|
||||
|
||||
/** @brief Suspend the Mesh network temporarily.
|
||||
*
|
||||
* This API can be used for power saving purposes, but the user should be
|
||||
* aware that leaving the local node suspended for a long period of time
|
||||
* may cause it to become permanently disconnected from the Mesh network.
|
||||
* If at all possible, the Friendship feature should be used instead, to
|
||||
* make the node into a Low Power Node.
|
||||
*
|
||||
* @return 0 on success, or (negative) error code on failure.
|
||||
*/
|
||||
int bt_mesh_suspend(void);
|
||||
|
||||
/** @brief Resume a suspended Mesh network.
|
||||
*
|
||||
* This API resumes the local node, after it has been suspended using the
|
||||
* bt_mesh_suspend() API.
|
||||
*
|
||||
* @return 0 on success, or (negative) error code on failure.
|
||||
*/
|
||||
int bt_mesh_resume(void);
|
||||
|
||||
/** @brief Provision the local Mesh Node.
|
||||
*
|
||||
* This API should normally not be used directly by the application. The
|
||||
|
|
|
@ -214,6 +214,11 @@ struct net_buf *bt_mesh_adv_create_from_pool(struct net_buf_pool *pool,
|
|||
struct bt_mesh_adv *adv;
|
||||
struct net_buf *buf;
|
||||
|
||||
if (atomic_test_bit(bt_mesh.flags, BT_MESH_SUSPENDED)) {
|
||||
BT_WARN("Refusing to allocate buffer while suspended");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf = net_buf_alloc(pool, timeout);
|
||||
if (!buf) {
|
||||
return NULL;
|
||||
|
|
|
@ -3492,6 +3492,13 @@ struct bt_mesh_hb_pub *bt_mesh_hb_pub_get(void)
|
|||
return &conf->hb_pub;
|
||||
}
|
||||
|
||||
void bt_mesh_hb_pub_disable(void)
|
||||
{
|
||||
if (conf) {
|
||||
hb_pub_disable(conf);
|
||||
}
|
||||
}
|
||||
|
||||
struct bt_mesh_cfg_srv *bt_mesh_cfg_get(void)
|
||||
{
|
||||
return conf;
|
||||
|
|
|
@ -127,6 +127,7 @@ void bt_mesh_attention(struct bt_mesh_model *model, u8_t time);
|
|||
u8_t *bt_mesh_label_uuid_get(u16_t addr);
|
||||
|
||||
struct bt_mesh_hb_pub *bt_mesh_hb_pub_get(void);
|
||||
void bt_mesh_hb_pub_disable(void);
|
||||
struct bt_mesh_cfg_srv *bt_mesh_cfg_get(void);
|
||||
|
||||
u8_t bt_mesh_net_transmit_get(void);
|
||||
|
|
|
@ -191,6 +191,85 @@ int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void model_suspend(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
|
||||
bool vnd, bool primary, void *user_data)
|
||||
{
|
||||
if (mod->pub && mod->pub->update) {
|
||||
mod->pub->count = 0;
|
||||
k_delayed_work_cancel(&mod->pub->timer);
|
||||
}
|
||||
}
|
||||
|
||||
int bt_mesh_suspend(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (atomic_test_and_set_bit(bt_mesh.flags, BT_MESH_SUSPENDED)) {
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
err = bt_mesh_scan_disable();
|
||||
if (err) {
|
||||
atomic_clear_bit(bt_mesh.flags, BT_MESH_SUSPENDED);
|
||||
BT_WARN("Disabling scanning failed (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
bt_mesh_hb_pub_disable();
|
||||
|
||||
if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED) {
|
||||
bt_mesh_beacon_disable();
|
||||
}
|
||||
|
||||
bt_mesh_model_foreach(model_suspend, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void model_resume(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
|
||||
bool vnd, bool primary, void *user_data)
|
||||
{
|
||||
if (mod->pub && mod->pub->update) {
|
||||
s32_t period_ms = bt_mesh_model_pub_period_get(mod);
|
||||
|
||||
if (period_ms) {
|
||||
k_delayed_work_submit(&mod->pub->timer, period_ms);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int bt_mesh_resume(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_SUSPENDED)) {
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
err = bt_mesh_scan_enable();
|
||||
if (err) {
|
||||
BT_WARN("Re-enabling scanning failed (err %d)", err);
|
||||
atomic_set_bit(bt_mesh.flags, BT_MESH_SUSPENDED);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED) {
|
||||
bt_mesh_beacon_enable();
|
||||
}
|
||||
|
||||
bt_mesh_model_foreach(model_resume, NULL);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int bt_mesh_init(const struct bt_mesh_prov *prov,
|
||||
const struct bt_mesh_comp *comp)
|
||||
{
|
||||
|
|
|
@ -194,6 +194,7 @@ struct bt_mesh_lpn {
|
|||
/* bt_mesh_net.flags */
|
||||
enum {
|
||||
BT_MESH_VALID, /* We have been provisioned */
|
||||
BT_MESH_SUSPENDED, /* Network is temporarily suspended */
|
||||
BT_MESH_IVU_IN_PROGRESS, /* IV Update in Progress */
|
||||
BT_MESH_IVU_INITIATOR, /* IV Update initiated by us */
|
||||
BT_MESH_IVU_TEST, /* IV Update test mode */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue