1 /*
2 * Copyright (c) 2022 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/bluetooth/mesh.h>
8
9 #include "foundation.h"
10 #include "subnet.h"
11 #include "solicitation.h"
12
13 #define LOG_LEVEL CONFIG_BT_MESH_MODEL_LOG_LEVEL
14 #include <zephyr/logging/log.h>
15 LOG_MODULE_REGISTER(bt_mesh_sol_pdu_rpl_srv);
16
sol_rpl_status_rsp(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,uint16_t range,uint8_t len)17 static void sol_rpl_status_rsp(const struct bt_mesh_model *mod,
18 struct bt_mesh_msg_ctx *ctx,
19 uint16_t range,
20 uint8_t len)
21 {
22 BT_MESH_MODEL_BUF_DEFINE(buf, OP_SOL_PDU_RPL_ITEM_STATUS, 2 + (len < 2 ? 0 : 1));
23
24 bt_mesh_model_msg_init(&buf, OP_SOL_PDU_RPL_ITEM_STATUS);
25
26 net_buf_simple_add_le16(&buf, range);
27
28 if (len >= 2) {
29 net_buf_simple_add_u8(&buf, len);
30 }
31
32 bt_mesh_model_send(mod, ctx, &buf, NULL, NULL);
33 }
34
item_clear(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf,bool acked)35 static int item_clear(const struct bt_mesh_model *mod,
36 struct bt_mesh_msg_ctx *ctx,
37 struct net_buf_simple *buf,
38 bool acked)
39 {
40 uint16_t primary, range;
41 uint8_t len = 0;
42
43 LOG_DBG("");
44
45 if (buf->len > 3) {
46 return -EMSGSIZE;
47 }
48
49 range = net_buf_simple_pull_le16(buf);
50 primary = range >> 1;
51
52 LOG_DBG("Start address: 0x%02x, %d", primary, buf->len);
53 if (range & BIT(0)) {
54 if (buf->len == 0) {
55 return -EMSGSIZE;
56 }
57
58 len = net_buf_simple_pull_u8(buf);
59
60 if (len < 2) {
61 return -EINVAL;
62 }
63 }
64
65 if ((primary + len) > 0x8000 || primary == 0) {
66 LOG_WRN("Range outside unicast address range or equal to 0");
67 return -EINVAL;
68 }
69
70 for (int i = 0; i < len || i == 0; i++) {
71 bt_mesh_srpl_entry_clear(primary + i);
72 }
73
74 if (acked) {
75 sol_rpl_status_rsp(mod, ctx, range, len);
76 }
77
78 return 0;
79 }
80
handle_item_clear(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)81 static int handle_item_clear(const struct bt_mesh_model *mod,
82 struct bt_mesh_msg_ctx *ctx,
83 struct net_buf_simple *buf)
84 {
85 return item_clear(mod, ctx, buf, true);
86 }
87
handle_item_clear_unacked(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)88 static int handle_item_clear_unacked(const struct bt_mesh_model *mod,
89 struct bt_mesh_msg_ctx *ctx,
90 struct net_buf_simple *buf)
91 {
92 return item_clear(mod, ctx, buf, false);
93 }
94
95 const struct bt_mesh_model_op _bt_mesh_sol_pdu_rpl_srv_op[] = {
96 { OP_SOL_PDU_RPL_ITEM_CLEAR, BT_MESH_LEN_MIN(2), handle_item_clear },
97 { OP_SOL_PDU_RPL_ITEM_CLEAR_UNACKED, BT_MESH_LEN_MIN(2), handle_item_clear_unacked },
98
99 BT_MESH_MODEL_OP_END
100 };
101
sol_pdu_rpl_srv_init(const struct bt_mesh_model * mod)102 static int sol_pdu_rpl_srv_init(const struct bt_mesh_model *mod)
103 {
104 if (!bt_mesh_model_in_primary(mod)) {
105 LOG_ERR("Solicitation PDU RPL Configuration server not in primary element");
106 return -EINVAL;
107 }
108
109 return 0;
110 }
111
112 const struct bt_mesh_model_cb _bt_mesh_sol_pdu_rpl_srv_cb = {
113 .init = sol_pdu_rpl_srv_init,
114 };
115