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