From 91fa9194f01a7c267ddcce7e6d76ef5c03527255 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Narajowski?= Date: Thu, 16 Jul 2020 14:16:46 +0200 Subject: [PATCH] Bluetooth: Mesh: Fix Heartbeat Pub/Sub Count/Period Log calculation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mesh Profile Specification Errata 11737 specifies that Period/Count Log value 0x11 is not defined Log field transformation in Table 4.1. Errata 11737 adds value 0x11 to Log field transformation table with 2-octet value equal to 0x10000 which does not fit into two octets. This patch changes period calculation to 32-bit precision. There is also a special case for publication count. If the log value is equal to 0x11 then the publication count value should be 0xfffe. When sending Hearbeat Publication Status message we should return the same value as the one received in Publication Set so we have to add a case in hb_pub_count_log(). Co-authored-by: Alperen Sener Signed-off-by: MichaƂ Narajowski Signed-off-by: Pavel Vasilyev --- subsys/bluetooth/mesh/cfg_srv.c | 36 ++++++++++++++++++++++++++----- subsys/bluetooth/mesh/heartbeat.c | 4 +++- subsys/bluetooth/mesh/heartbeat.h | 4 +--- 3 files changed, 35 insertions(+), 9 deletions(-) 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); }