1 /*
2  * Copyright (c) 2018 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <errno.h>
9 #include <sys/types.h>
10 #include <zephyr/sys/util.h>
11 
12 #include <zephyr/bluetooth/hci.h>
13 
14 #include <zephyr/settings/settings.h>
15 #include <zephyr/bluetooth/mesh.h>
16 
17 #include "host/hci_core.h"
18 #include "mesh.h"
19 #include "subnet.h"
20 #include "app_keys.h"
21 #include "net.h"
22 #include "cdb.h"
23 #include "crypto.h"
24 #include "rpl.h"
25 #include "transport.h"
26 #include "heartbeat.h"
27 #include "access.h"
28 #include "proxy.h"
29 #include "pb_gatt_srv.h"
30 #include "settings.h"
31 #include "cfg.h"
32 #include "solicitation.h"
33 #include "va.h"
34 
35 #define LOG_LEVEL CONFIG_BT_MESH_SETTINGS_LOG_LEVEL
36 #include <zephyr/logging/log.h>
37 LOG_MODULE_REGISTER(bt_mesh_settings);
38 
39 #ifdef CONFIG_BT_MESH_RPL_STORE_TIMEOUT
40 #define RPL_STORE_TIMEOUT CONFIG_BT_MESH_RPL_STORE_TIMEOUT
41 #else
42 #define RPL_STORE_TIMEOUT (-1)
43 #endif
44 
45 #ifdef CONFIG_BT_MESH_SETTINGS_WORKQ_PRIO
46 #define SETTINGS_WORKQ_PRIO CONFIG_BT_MESH_SETTINGS_WORKQ_PRIO
47 #else
48 #define SETTINGS_WORKQ_PRIO 1
49 #endif
50 
51 #ifdef CONFIG_BT_MESH_SETTINGS_WORKQ_STACK_SIZE
52 #define SETTINGS_WORKQ_STACK_SIZE CONFIG_BT_MESH_SETTINGS_WORKQ_STACK_SIZE
53 #else
54 #define SETTINGS_WORKQ_STACK_SIZE 0
55 #endif
56 
57 static struct k_work_q settings_work_q;
58 static K_THREAD_STACK_DEFINE(settings_work_stack, SETTINGS_WORKQ_STACK_SIZE);
59 
60 static struct k_work_delayable pending_store;
61 static ATOMIC_DEFINE(pending_flags, BT_MESH_SETTINGS_FLAG_COUNT);
62 
bt_mesh_settings_set(settings_read_cb read_cb,void * cb_arg,void * out,size_t read_len)63 int bt_mesh_settings_set(settings_read_cb read_cb, void *cb_arg,
64 			 void *out, size_t read_len)
65 {
66 	ssize_t len;
67 
68 	len = read_cb(cb_arg, out, read_len);
69 	if (len < 0) {
70 		LOG_ERR("Failed to read value (err %zd)", len);
71 		return len;
72 	}
73 
74 	LOG_HEXDUMP_DBG(out, len, "val");
75 
76 	if (len != read_len) {
77 		LOG_ERR("Unexpected value length (%zd != %zu)", len, read_len);
78 		return -EINVAL;
79 	}
80 
81 	return 0;
82 }
83 
mesh_commit(void)84 static int mesh_commit(void)
85 {
86 	if (!atomic_test_bit(bt_mesh.flags, BT_MESH_INIT)) {
87 		return 0;
88 	}
89 
90 	if (!atomic_test_bit(bt_dev.flags, BT_DEV_ENABLE)) {
91 		/* The Bluetooth mesh settings loader calls bt_mesh_start() immediately
92 		 * after loading the settings. This is not intended to work before
93 		 * bt_enable(). The doc on @ref bt_enable requires the "bt/" settings
94 		 * tree to be loaded after @ref bt_enable is completed, so this handler
95 		 * will be called again later.
96 		 */
97 		return 0;
98 	}
99 
100 	if (!bt_mesh_subnet_next(NULL)) {
101 		/* Nothing to do since we're not yet provisioned */
102 		return 0;
103 	}
104 
105 	if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) {
106 		(void)bt_mesh_pb_gatt_srv_disable();
107 	}
108 
109 	bt_mesh_net_settings_commit();
110 	bt_mesh_model_settings_commit();
111 
112 	atomic_set_bit(bt_mesh.flags, BT_MESH_VALID);
113 
114 	bt_mesh_start();
115 
116 	return 0;
117 }
118 
119 SETTINGS_STATIC_HANDLER_DEFINE(bt_mesh, "bt/mesh", NULL, NULL, mesh_commit,
120 			       NULL);
121 
122 /* Pending flags that use K_NO_WAIT as the storage timeout */
123 #define NO_WAIT_PENDING_BITS (BIT(BT_MESH_SETTINGS_NET_PENDING) |           \
124 			      BIT(BT_MESH_SETTINGS_IV_PENDING)  |           \
125 			      BIT(BT_MESH_SETTINGS_SEQ_PENDING) |           \
126 			      BIT(BT_MESH_SETTINGS_CDB_PENDING))
127 
128 /* Pending flags that use CONFIG_BT_MESH_STORE_TIMEOUT */
129 #define GENERIC_PENDING_BITS (BIT(BT_MESH_SETTINGS_NET_KEYS_PENDING) |      \
130 			      BIT(BT_MESH_SETTINGS_APP_KEYS_PENDING) |      \
131 			      BIT(BT_MESH_SETTINGS_HB_PUB_PENDING)   |      \
132 			      BIT(BT_MESH_SETTINGS_CFG_PENDING)      |      \
133 			      BIT(BT_MESH_SETTINGS_MOD_PENDING)      |      \
134 			      BIT(BT_MESH_SETTINGS_VA_PENDING)       |      \
135 			      BIT(BT_MESH_SETTINGS_SSEQ_PENDING)     |      \
136 			      BIT(BT_MESH_SETTINGS_COMP_PENDING)     |      \
137 			      BIT(BT_MESH_SETTINGS_DEV_KEY_CAND_PENDING))
138 
bt_mesh_settings_store_schedule(enum bt_mesh_settings_flag flag)139 void bt_mesh_settings_store_schedule(enum bt_mesh_settings_flag flag)
140 {
141 	uint32_t timeout_ms, remaining_ms;
142 
143 	atomic_set_bit(pending_flags, flag);
144 
145 	if (atomic_get(pending_flags) & NO_WAIT_PENDING_BITS) {
146 		timeout_ms = 0;
147 	} else if (IS_ENABLED(CONFIG_BT_MESH_RPL_STORAGE_MODE_SETTINGS) && RPL_STORE_TIMEOUT >= 0 &&
148 		   (atomic_test_bit(pending_flags, BT_MESH_SETTINGS_RPL_PENDING) ||
149 		     atomic_test_bit(pending_flags, BT_MESH_SETTINGS_SRPL_PENDING)) &&
150 		   !(atomic_get(pending_flags) & GENERIC_PENDING_BITS)) {
151 		timeout_ms = RPL_STORE_TIMEOUT * MSEC_PER_SEC;
152 	} else {
153 		timeout_ms = CONFIG_BT_MESH_STORE_TIMEOUT * MSEC_PER_SEC;
154 	}
155 
156 	remaining_ms = k_ticks_to_ms_floor32(k_work_delayable_remaining_get(&pending_store));
157 	LOG_DBG("Waiting %u ms vs rem %u ms", timeout_ms, remaining_ms);
158 
159 	/* If the new deadline is sooner, override any existing
160 	 * deadline; otherwise schedule without changing any existing
161 	 * deadline.
162 	 */
163 	if (timeout_ms < remaining_ms) {
164 		if (IS_ENABLED(CONFIG_BT_MESH_SETTINGS_WORKQ)) {
165 			k_work_reschedule_for_queue(&settings_work_q, &pending_store,
166 						    K_MSEC(timeout_ms));
167 		} else {
168 			k_work_reschedule(&pending_store, K_MSEC(timeout_ms));
169 		}
170 	} else {
171 		if (IS_ENABLED(CONFIG_BT_MESH_SETTINGS_WORKQ)) {
172 			k_work_schedule_for_queue(&settings_work_q, &pending_store,
173 						  K_MSEC(timeout_ms));
174 		} else {
175 			k_work_schedule(&pending_store, K_MSEC(timeout_ms));
176 		}
177 	}
178 }
179 
bt_mesh_settings_store_cancel(enum bt_mesh_settings_flag flag)180 void bt_mesh_settings_store_cancel(enum bt_mesh_settings_flag flag)
181 {
182 	atomic_clear_bit(pending_flags, flag);
183 }
184 
store_pending(struct k_work * work)185 static void store_pending(struct k_work *work)
186 {
187 	LOG_DBG("");
188 
189 	if (IS_ENABLED(CONFIG_BT_MESH_RPL_STORAGE_MODE_SETTINGS) &&
190 	    atomic_test_and_clear_bit(pending_flags, BT_MESH_SETTINGS_RPL_PENDING)) {
191 		bt_mesh_rpl_pending_store(BT_MESH_ADDR_ALL_NODES);
192 	}
193 
194 	if (atomic_test_and_clear_bit(pending_flags,
195 				      BT_MESH_SETTINGS_NET_KEYS_PENDING)) {
196 		bt_mesh_subnet_pending_store();
197 	}
198 
199 	if (atomic_test_and_clear_bit(pending_flags,
200 				      BT_MESH_SETTINGS_APP_KEYS_PENDING)) {
201 		bt_mesh_app_key_pending_store();
202 	}
203 
204 	if (atomic_test_and_clear_bit(pending_flags,
205 				      BT_MESH_SETTINGS_NET_PENDING)) {
206 		bt_mesh_net_pending_net_store();
207 	}
208 
209 	if (atomic_test_and_clear_bit(pending_flags,
210 				      BT_MESH_SETTINGS_IV_PENDING)) {
211 		bt_mesh_net_pending_iv_store();
212 	}
213 
214 	if (atomic_test_and_clear_bit(pending_flags,
215 				      BT_MESH_SETTINGS_SEQ_PENDING)) {
216 		bt_mesh_net_pending_seq_store();
217 	}
218 
219 	if (atomic_test_and_clear_bit(pending_flags,
220 				      BT_MESH_SETTINGS_DEV_KEY_CAND_PENDING)) {
221 		bt_mesh_net_pending_dev_key_cand_store();
222 	}
223 
224 	if (atomic_test_and_clear_bit(pending_flags,
225 				      BT_MESH_SETTINGS_HB_PUB_PENDING)) {
226 		bt_mesh_hb_pub_pending_store();
227 	}
228 
229 	if (atomic_test_and_clear_bit(pending_flags,
230 				      BT_MESH_SETTINGS_CFG_PENDING)) {
231 		bt_mesh_cfg_pending_store();
232 	}
233 
234 	if (atomic_test_and_clear_bit(pending_flags,
235 				      BT_MESH_SETTINGS_COMP_PENDING)) {
236 		bt_mesh_comp_data_pending_clear();
237 	}
238 
239 	if (atomic_test_and_clear_bit(pending_flags,
240 				      BT_MESH_SETTINGS_MOD_PENDING)) {
241 		bt_mesh_model_pending_store();
242 	}
243 
244 	if (atomic_test_and_clear_bit(pending_flags,
245 				      BT_MESH_SETTINGS_VA_PENDING)) {
246 		bt_mesh_va_pending_store();
247 	}
248 
249 	if (IS_ENABLED(CONFIG_BT_MESH_CDB) &&
250 	    atomic_test_and_clear_bit(pending_flags,
251 				      BT_MESH_SETTINGS_CDB_PENDING)) {
252 		bt_mesh_cdb_pending_store();
253 	}
254 
255 	if (IS_ENABLED(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV) &&
256 		atomic_test_and_clear_bit(pending_flags,
257 					  BT_MESH_SETTINGS_SRPL_PENDING)) {
258 		bt_mesh_srpl_pending_store();
259 	}
260 
261 	if (IS_ENABLED(CONFIG_BT_MESH_PROXY_SOLICITATION) &&
262 		atomic_test_and_clear_bit(pending_flags,
263 					  BT_MESH_SETTINGS_SSEQ_PENDING)) {
264 		bt_mesh_sseq_pending_store();
265 	}
266 }
267 
bt_mesh_settings_init(void)268 void bt_mesh_settings_init(void)
269 {
270 	if (IS_ENABLED(CONFIG_BT_MESH_SETTINGS_WORKQ)) {
271 		k_work_queue_start(&settings_work_q, settings_work_stack,
272 				   K_THREAD_STACK_SIZEOF(settings_work_stack),
273 				   K_PRIO_COOP(SETTINGS_WORKQ_PRIO), NULL);
274 		k_thread_name_set(&settings_work_q.thread, "BT Mesh settings workq");
275 	}
276 
277 	k_work_init_delayable(&pending_store, store_pending);
278 }
279 
bt_mesh_settings_store_pending(void)280 void bt_mesh_settings_store_pending(void)
281 {
282 	(void)k_work_cancel_delayable(&pending_store);
283 
284 	store_pending(&pending_store.work);
285 }
286