diff --git a/subsys/bluetooth/mesh/cfg_srv.c b/subsys/bluetooth/mesh/cfg_srv.c index 162649524c6..875c1e9f3bc 100644 --- a/subsys/bluetooth/mesh/cfg_srv.c +++ b/subsys/bluetooth/mesh/cfg_srv.c @@ -2240,12 +2240,23 @@ static int krp_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, return send_krp_status(model, ctx, idx, phase, status); } +static uint8_t hb_sub_count_log(uint32_t val) +{ + if (val == 0xffff) { + return 0xff; + } else { + return bt_mesh_hb_log(val); + } +} + static uint8_t hb_pub_count_log(uint16_t val) { if (!val) { return 0x00; } else if (val == 0x01) { return 0x01; + } else if (val == 0xfffe) { + return 0x11; } else if (val == 0xffff) { return 0xff; } else { @@ -2312,8 +2323,19 @@ static int heartbeat_pub_set(struct bt_mesh_model *model, LOG_DBG("src 0x%04x", ctx->addr); pub.dst = sys_le16_to_cpu(param->dst); - pub.count = bt_mesh_hb_pwr2(param->count_log); - pub.period = bt_mesh_hb_pwr2(param->period_log); + if (param->count_log == 0x11) { + /* Special case defined in Mesh Profile Errata 11737 */ + pub.count = 0xfffe; + } else { + pub.count = bt_mesh_hb_pwr2(param->count_log); + } + + if (param->period_log == 0x11) { + pub.period = 0x10000; + } else { + pub.period = bt_mesh_hb_pwr2(param->period_log); + } + pub.ttl = param->ttl; pub.feat = sys_le16_to_cpu(param->feat); pub.net_idx = sys_le16_to_cpu(param->net_idx); @@ -2329,7 +2351,7 @@ static int heartbeat_pub_set(struct bt_mesh_model *model, goto rsp; } - if (param->period_log > 0x10) { + if (param->period_log > 0x11) { status = STATUS_CANNOT_SET; goto rsp; } @@ -2364,7 +2386,7 @@ static int hb_sub_send_status(struct bt_mesh_model *model, net_buf_simple_add_le16(&msg, sub->src); net_buf_simple_add_le16(&msg, sub->dst); net_buf_simple_add_u8(&msg, bt_mesh_hb_log(sub->remaining)); - net_buf_simple_add_u8(&msg, bt_mesh_hb_log(sub->count)); + net_buf_simple_add_u8(&msg, hb_sub_count_log(sub->count)); net_buf_simple_add_u8(&msg, sub->min_hops); net_buf_simple_add_u8(&msg, sub->max_hops); @@ -2411,7 +2433,11 @@ static int heartbeat_sub_set(struct bt_mesh_model *model, return -EINVAL; } - period = bt_mesh_hb_pwr2(period_log); + if (period_log == 0x11) { + period = 0x10000; + } else { + period = bt_mesh_hb_pwr2(period_log); + } status = bt_mesh_hb_sub_set(sub_src, sub_dst, period); if (status != STATUS_SUCCESS) { diff --git a/subsys/bluetooth/mesh/heartbeat.c b/subsys/bluetooth/mesh/heartbeat.c index f842994f35a..503a0994d55 100644 --- a/subsys/bluetooth/mesh/heartbeat.c +++ b/subsys/bluetooth/mesh/heartbeat.c @@ -231,8 +231,10 @@ static void pub_disable(void) pub.dst = BT_MESH_ADDR_UNASSIGNED; pub.count = 0U; - pub.ttl = 0U; pub.period = 0U; + pub.ttl = 0U; + pub.feat = 0U; + pub.net_idx = 0U; /* Try to cancel, but it's OK if this still runs (or is * running) as the handler will be a no-op if it hasn't diff --git a/subsys/bluetooth/mesh/heartbeat.h b/subsys/bluetooth/mesh/heartbeat.h index 1950855a156..077c9600875 100644 --- a/subsys/bluetooth/mesh/heartbeat.h +++ b/subsys/bluetooth/mesh/heartbeat.h @@ -8,7 +8,7 @@ static inline uint16_t bt_mesh_hb_pwr2(uint8_t val) { if (!val) { return 0x0000; - } else if (val == 0xff || val == 0x11) { + } else if (val == 0xff) { return 0xffff; } else { return (1 << (val - 1)); @@ -19,8 +19,6 @@ static inline uint8_t bt_mesh_hb_log(uint32_t val) { if (!val) { return 0x00; - } else if (val == 0xffff) { - return 0xff; } else { return 32 - __builtin_clz(val); }