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 "access.h"
10 #include "cfg.h"
11 #include "foundation.h"
12 #include "settings.h"
13
14 #define LOG_LEVEL CONFIG_BT_MESH_MODEL_LOG_LEVEL
15 #include <zephyr/logging/log.h>
16 LOG_MODULE_REGISTER(bt_mesh_od_priv_proxy_srv);
17
18
19 static const struct bt_mesh_model *od_priv_proxy_srv;
20 static uint8_t on_demand_state;
21
od_priv_proxy_store(bool delete)22 static int od_priv_proxy_store(bool delete)
23 {
24 if (!IS_ENABLED(CONFIG_BT_SETTINGS)) {
25 return 0;
26 }
27
28 const void *data = delete ? NULL : &on_demand_state;
29 size_t len = delete ? 0 : sizeof(uint8_t);
30
31 return bt_mesh_model_data_store(od_priv_proxy_srv, false, "pp", data, len);
32 }
33
proxy_status_rsp(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx)34 static int proxy_status_rsp(const struct bt_mesh_model *mod,
35 struct bt_mesh_msg_ctx *ctx)
36 {
37 BT_MESH_MODEL_BUF_DEFINE(buf, OP_OD_PRIV_PROXY_STATUS, 1);
38 bt_mesh_model_msg_init(&buf, OP_OD_PRIV_PROXY_STATUS);
39
40 net_buf_simple_add_u8(&buf, bt_mesh_od_priv_proxy_get());
41
42 bt_mesh_model_send(mod, ctx, &buf, NULL, NULL);
43
44 return 0;
45 }
46
handle_proxy_get(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)47 static int handle_proxy_get(const struct bt_mesh_model *mod,
48 struct bt_mesh_msg_ctx *ctx,
49 struct net_buf_simple *buf)
50 {
51 LOG_DBG("");
52
53 proxy_status_rsp(mod, ctx);
54
55 return 0;
56 }
57
handle_proxy_set(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)58 static int handle_proxy_set(const struct bt_mesh_model *mod,
59 struct bt_mesh_msg_ctx *ctx,
60 struct net_buf_simple *buf)
61 {
62 uint8_t state;
63
64 LOG_DBG("");
65
66 state = net_buf_simple_pull_u8(buf);
67 LOG_DBG("state %d", state);
68
69 bt_mesh_od_priv_proxy_set(state);
70 proxy_status_rsp(mod, ctx);
71
72 return 0;
73 }
74
75 const struct bt_mesh_model_op _bt_mesh_od_priv_proxy_srv_op[] = {
76 { OP_OD_PRIV_PROXY_GET, BT_MESH_LEN_EXACT(0), handle_proxy_get },
77 { OP_OD_PRIV_PROXY_SET, BT_MESH_LEN_EXACT(1), handle_proxy_set },
78
79 BT_MESH_MODEL_OP_END
80 };
81
od_priv_proxy_srv_init(const struct bt_mesh_model * mod)82 static int od_priv_proxy_srv_init(const struct bt_mesh_model *mod)
83 {
84 od_priv_proxy_srv = mod;
85
86 const struct bt_mesh_model *priv_beacon_srv =
87 bt_mesh_model_find(bt_mesh_model_elem(mod), BT_MESH_MODEL_ID_PRIV_BEACON_SRV);
88 const struct bt_mesh_model *sol_pdu_rpl_srv =
89 bt_mesh_model_find(bt_mesh_model_elem(mod), BT_MESH_MODEL_ID_SOL_PDU_RPL_SRV);
90
91 if (priv_beacon_srv == NULL) {
92 LOG_ERR("On-Demand Private Proxy server cannot extend Private Beacon server");
93 return -EINVAL;
94 }
95
96 mod->keys[0] = BT_MESH_KEY_DEV_LOCAL;
97 mod->rt->flags |= BT_MESH_MOD_DEVKEY_ONLY;
98
99 bt_mesh_model_extend(mod, priv_beacon_srv);
100
101 if (sol_pdu_rpl_srv != NULL) {
102 bt_mesh_model_correspond(mod, sol_pdu_rpl_srv);
103 } else {
104 LOG_WRN("On-Demand Private Proxy server cannot be corresponded by Solicitation PDU "
105 "RPL Configuration server");
106 }
107
108 return 0;
109 }
110
od_priv_proxy_srv_reset(const struct bt_mesh_model * model)111 static void od_priv_proxy_srv_reset(const struct bt_mesh_model *model)
112 {
113 on_demand_state = 0;
114 od_priv_proxy_store(true);
115 }
116
117 #ifdef CONFIG_BT_SETTINGS
od_priv_proxy_srv_settings_set(const struct bt_mesh_model * model,const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_data)118 static int od_priv_proxy_srv_settings_set(const struct bt_mesh_model *model, const char *name,
119 size_t len_rd, settings_read_cb read_cb, void *cb_data)
120 {
121 int err;
122
123 if (len_rd == 0) {
124 LOG_DBG("Cleared configuration state");
125 return 0;
126 }
127
128 err = bt_mesh_settings_set(read_cb, cb_data, &on_demand_state, sizeof(uint8_t));
129 if (err) {
130 LOG_ERR("Failed to set OD private proxy state");
131 return err;
132 }
133
134 bt_mesh_od_priv_proxy_set(on_demand_state);
135 return 0;
136 }
137
od_priv_proxy_srv_pending_store(const struct bt_mesh_model * model)138 static void od_priv_proxy_srv_pending_store(const struct bt_mesh_model *model)
139 {
140 on_demand_state = bt_mesh_od_priv_proxy_get();
141 od_priv_proxy_store(false);
142 }
143 #endif
144
145 const struct bt_mesh_model_cb _bt_mesh_od_priv_proxy_srv_cb = {
146 .init = od_priv_proxy_srv_init,
147 .reset = od_priv_proxy_srv_reset,
148 #ifdef CONFIG_BT_SETTINGS
149 .settings_set = od_priv_proxy_srv_settings_set,
150 .pending_store = od_priv_proxy_srv_pending_store,
151 #endif
152 };
153
bt_mesh_od_priv_proxy_srv_store_schedule(void)154 void bt_mesh_od_priv_proxy_srv_store_schedule(void)
155 {
156 if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
157 bt_mesh_model_data_store_schedule(od_priv_proxy_srv);
158 }
159 }
160