xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/mesh/src/settings.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
1*042d53a7SEvalZero /*
2*042d53a7SEvalZero  * Copyright (c) 2018 Intel Corporation
3*042d53a7SEvalZero  *
4*042d53a7SEvalZero  * SPDX-License-Identifier: Apache-2.0
5*042d53a7SEvalZero  */
6*042d53a7SEvalZero 
7*042d53a7SEvalZero #include "syscfg/syscfg.h"
8*042d53a7SEvalZero 
9*042d53a7SEvalZero #if MYNEWT_VAL(BLE_MESH_SETTINGS)
10*042d53a7SEvalZero 
11*042d53a7SEvalZero #define BT_DBG_ENABLED MYNEWT_VAL(BLE_MESH_DEBUG_SETTINGS)
12*042d53a7SEvalZero 
13*042d53a7SEvalZero #include "mesh/mesh.h"
14*042d53a7SEvalZero #include "mesh/glue.h"
15*042d53a7SEvalZero #include "net.h"
16*042d53a7SEvalZero #include "crypto.h"
17*042d53a7SEvalZero #include "transport.h"
18*042d53a7SEvalZero #include "access.h"
19*042d53a7SEvalZero #include "foundation.h"
20*042d53a7SEvalZero #include "proxy.h"
21*042d53a7SEvalZero #include "settings.h"
22*042d53a7SEvalZero 
23*042d53a7SEvalZero #include "config/config.h"
24*042d53a7SEvalZero 
25*042d53a7SEvalZero /* Tracking of what storage changes are pending for App and Net Keys. We
26*042d53a7SEvalZero  * track this in a separate array here instead of within the respective
27*042d53a7SEvalZero  * bt_mesh_app_key and bt_mesh_subnet structs themselves, since once a key
28*042d53a7SEvalZero  * gets deleted its struct becomes invalid and may be reused for other keys.
29*042d53a7SEvalZero  */
30*042d53a7SEvalZero static struct key_update {
31*042d53a7SEvalZero 	u16_t key_idx:12,    /* AppKey or NetKey Index */
32*042d53a7SEvalZero 	      valid:1,       /* 1 if this entry is valid, 0 if not */
33*042d53a7SEvalZero 	      app_key:1,     /* 1 if this is an AppKey, 0 if a NetKey */
34*042d53a7SEvalZero 	      clear:1;       /* 1 if key needs clearing, 0 if storing */
35*042d53a7SEvalZero } key_updates[CONFIG_BT_MESH_APP_KEY_COUNT + CONFIG_BT_MESH_SUBNET_COUNT];
36*042d53a7SEvalZero 
37*042d53a7SEvalZero static struct k_delayed_work pending_store;
38*042d53a7SEvalZero 
39*042d53a7SEvalZero /* Mesh network storage information */
40*042d53a7SEvalZero struct net_val {
41*042d53a7SEvalZero 	u16_t primary_addr;
42*042d53a7SEvalZero 	u8_t  dev_key[16];
43*042d53a7SEvalZero } __packed;
44*042d53a7SEvalZero 
45*042d53a7SEvalZero /* Sequence number storage */
46*042d53a7SEvalZero struct seq_val {
47*042d53a7SEvalZero 	u8_t val[3];
48*042d53a7SEvalZero } __packed;
49*042d53a7SEvalZero 
50*042d53a7SEvalZero /* Heartbeat Publication storage */
51*042d53a7SEvalZero struct hb_pub_val {
52*042d53a7SEvalZero 	u16_t dst;
53*042d53a7SEvalZero 	u8_t  period;
54*042d53a7SEvalZero 	u8_t  ttl;
55*042d53a7SEvalZero 	u16_t feat;
56*042d53a7SEvalZero 	u16_t net_idx:12,
57*042d53a7SEvalZero 	      indefinite:1;
58*042d53a7SEvalZero };
59*042d53a7SEvalZero 
60*042d53a7SEvalZero /* Miscelaneous configuration server model states */
61*042d53a7SEvalZero struct cfg_val {
62*042d53a7SEvalZero 	u8_t net_transmit;
63*042d53a7SEvalZero 	u8_t relay;
64*042d53a7SEvalZero 	u8_t relay_retransmit;
65*042d53a7SEvalZero 	u8_t beacon;
66*042d53a7SEvalZero 	u8_t gatt_proxy;
67*042d53a7SEvalZero 	u8_t frnd;
68*042d53a7SEvalZero 	u8_t default_ttl;
69*042d53a7SEvalZero };
70*042d53a7SEvalZero 
71*042d53a7SEvalZero /* IV Index & IV Update storage */
72*042d53a7SEvalZero struct iv_val {
73*042d53a7SEvalZero 	u32_t iv_index;
74*042d53a7SEvalZero 	u8_t  iv_update:1,
75*042d53a7SEvalZero 	      iv_duration:7;
76*042d53a7SEvalZero } __packed;
77*042d53a7SEvalZero 
78*042d53a7SEvalZero /* Replay Protection List storage */
79*042d53a7SEvalZero struct rpl_val {
80*042d53a7SEvalZero 	u32_t seq:24,
81*042d53a7SEvalZero 	      old_iv:1;
82*042d53a7SEvalZero };
83*042d53a7SEvalZero 
84*042d53a7SEvalZero /* NetKey storage information */
85*042d53a7SEvalZero struct net_key_val {
86*042d53a7SEvalZero 	u8_t kr_flag:1,
87*042d53a7SEvalZero 	     kr_phase:7;
88*042d53a7SEvalZero 	u8_t val[2][16];
89*042d53a7SEvalZero } __packed;
90*042d53a7SEvalZero 
91*042d53a7SEvalZero /* AppKey storage information */
92*042d53a7SEvalZero struct app_key_val {
93*042d53a7SEvalZero 	u16_t net_idx;
94*042d53a7SEvalZero 	bool  updated;
95*042d53a7SEvalZero 	u8_t  val[2][16];
96*042d53a7SEvalZero } __packed;
97*042d53a7SEvalZero 
98*042d53a7SEvalZero struct mod_pub_val {
99*042d53a7SEvalZero 	u16_t addr;
100*042d53a7SEvalZero 	u16_t key;
101*042d53a7SEvalZero 	u8_t  ttl;
102*042d53a7SEvalZero 	u8_t  retransmit;
103*042d53a7SEvalZero 	u8_t  period;
104*042d53a7SEvalZero 	u8_t  period_div:4,
105*042d53a7SEvalZero 	      cred:1;
106*042d53a7SEvalZero };
107*042d53a7SEvalZero 
108*042d53a7SEvalZero /* We need this so we don't overwrite app-hardcoded values in case FCB
109*042d53a7SEvalZero  * contains a history of changes but then has a NULL at the end.
110*042d53a7SEvalZero  */
111*042d53a7SEvalZero static struct {
112*042d53a7SEvalZero 	bool valid;
113*042d53a7SEvalZero 	struct cfg_val cfg;
114*042d53a7SEvalZero } stored_cfg;
115*042d53a7SEvalZero 
net_set(int argc,char ** argv,char * val)116*042d53a7SEvalZero static int net_set(int argc, char **argv, char *val)
117*042d53a7SEvalZero {
118*042d53a7SEvalZero 	struct net_val net;
119*042d53a7SEvalZero 	int len, err;
120*042d53a7SEvalZero 
121*042d53a7SEvalZero 	BT_DBG("val %s", val ? val : "(null)");
122*042d53a7SEvalZero 
123*042d53a7SEvalZero 	if (!val) {
124*042d53a7SEvalZero 		bt_mesh_comp_unprovision();
125*042d53a7SEvalZero 		memset(bt_mesh.dev_key, 0, sizeof(bt_mesh.dev_key));
126*042d53a7SEvalZero 		return 0;
127*042d53a7SEvalZero 	}
128*042d53a7SEvalZero 
129*042d53a7SEvalZero 	len = sizeof(net);
130*042d53a7SEvalZero 	err = settings_bytes_from_str(val, &net, &len);
131*042d53a7SEvalZero 	if (err) {
132*042d53a7SEvalZero 		BT_ERR("Failed to decode value %s (err %d)", val, err);
133*042d53a7SEvalZero 		return err;
134*042d53a7SEvalZero 	}
135*042d53a7SEvalZero 
136*042d53a7SEvalZero 	if (len != sizeof(net)) {
137*042d53a7SEvalZero 		BT_ERR("Unexpected value length (%d != %zu)", len, sizeof(net));
138*042d53a7SEvalZero 		return -EINVAL;
139*042d53a7SEvalZero 	}
140*042d53a7SEvalZero 
141*042d53a7SEvalZero 	memcpy(bt_mesh.dev_key, net.dev_key, sizeof(bt_mesh.dev_key));
142*042d53a7SEvalZero 	bt_mesh_comp_provision(net.primary_addr);
143*042d53a7SEvalZero 
144*042d53a7SEvalZero 	BT_DBG("Provisioned with primary address 0x%04x", net.primary_addr);
145*042d53a7SEvalZero 	BT_DBG("Recovered DevKey %s", bt_hex(bt_mesh.dev_key, 16));
146*042d53a7SEvalZero 
147*042d53a7SEvalZero 	return 0;
148*042d53a7SEvalZero }
149*042d53a7SEvalZero 
iv_set(int argc,char ** argv,char * val)150*042d53a7SEvalZero static int iv_set(int argc, char **argv, char *val)
151*042d53a7SEvalZero {
152*042d53a7SEvalZero 	struct iv_val iv;
153*042d53a7SEvalZero 	int len, err;
154*042d53a7SEvalZero 
155*042d53a7SEvalZero 	BT_DBG("val %s", val ? val : "(null)");
156*042d53a7SEvalZero 
157*042d53a7SEvalZero 	if (!val) {
158*042d53a7SEvalZero 		bt_mesh.iv_index = 0;
159*042d53a7SEvalZero 		bt_mesh.iv_update = 0;
160*042d53a7SEvalZero 		return 0;
161*042d53a7SEvalZero 	}
162*042d53a7SEvalZero 
163*042d53a7SEvalZero 	len = sizeof(iv);
164*042d53a7SEvalZero 	err = settings_bytes_from_str(val, &iv, &len);
165*042d53a7SEvalZero 	if (err) {
166*042d53a7SEvalZero 		BT_ERR("Failed to decode value %s (err %d)", val, err);
167*042d53a7SEvalZero 		return err;
168*042d53a7SEvalZero 	}
169*042d53a7SEvalZero 
170*042d53a7SEvalZero 	if (len != sizeof(iv)) {
171*042d53a7SEvalZero 		BT_ERR("Unexpected value length (%d != %zu)", len, sizeof(iv));
172*042d53a7SEvalZero 		return -EINVAL;
173*042d53a7SEvalZero 	}
174*042d53a7SEvalZero 
175*042d53a7SEvalZero 	bt_mesh.iv_index = iv.iv_index;
176*042d53a7SEvalZero 	bt_mesh.iv_update = iv.iv_update;
177*042d53a7SEvalZero 	bt_mesh.ivu_duration = iv.iv_duration;
178*042d53a7SEvalZero 
179*042d53a7SEvalZero 	BT_DBG("IV Index 0x%04x (IV Update Flag %u) duration %u hours",
180*042d53a7SEvalZero 	       bt_mesh.iv_index, bt_mesh.iv_update, bt_mesh.ivu_duration);
181*042d53a7SEvalZero 
182*042d53a7SEvalZero 	return 0;
183*042d53a7SEvalZero }
184*042d53a7SEvalZero 
seq_set(int argc,char ** argv,char * val)185*042d53a7SEvalZero static int seq_set(int argc, char **argv, char *val)
186*042d53a7SEvalZero {
187*042d53a7SEvalZero 	struct seq_val seq;
188*042d53a7SEvalZero 	int len, err;
189*042d53a7SEvalZero 
190*042d53a7SEvalZero 	BT_DBG("val %s", val ? val : "(null)");
191*042d53a7SEvalZero 
192*042d53a7SEvalZero 	if (!val) {
193*042d53a7SEvalZero 		bt_mesh.seq = 0;
194*042d53a7SEvalZero 		return 0;
195*042d53a7SEvalZero 	}
196*042d53a7SEvalZero 
197*042d53a7SEvalZero 	len = sizeof(seq);
198*042d53a7SEvalZero 	err = settings_bytes_from_str(val, &seq, &len);
199*042d53a7SEvalZero 	if (err) {
200*042d53a7SEvalZero 		BT_ERR("Failed to decode value %s (err %d)", val, err);
201*042d53a7SEvalZero 		return err;
202*042d53a7SEvalZero 	}
203*042d53a7SEvalZero 
204*042d53a7SEvalZero 	if (len != sizeof(seq)) {
205*042d53a7SEvalZero 		BT_ERR("Unexpected value length (%d != %zu)", len, sizeof(seq));
206*042d53a7SEvalZero 		return -EINVAL;
207*042d53a7SEvalZero 	}
208*042d53a7SEvalZero 
209*042d53a7SEvalZero 	bt_mesh.seq = ((u32_t)seq.val[0] | ((u32_t)seq.val[1] << 8) |
210*042d53a7SEvalZero 		       ((u32_t)seq.val[2] << 16));
211*042d53a7SEvalZero 
212*042d53a7SEvalZero 	if (CONFIG_BT_MESH_SEQ_STORE_RATE > 0) {
213*042d53a7SEvalZero 		/* Make sure we have a large enough sequence number. We
214*042d53a7SEvalZero 		 * subtract 1 so that the first transmission causes a write
215*042d53a7SEvalZero 		 * to the settings storage.
216*042d53a7SEvalZero 		 */
217*042d53a7SEvalZero 		bt_mesh.seq += (CONFIG_BT_MESH_SEQ_STORE_RATE -
218*042d53a7SEvalZero 				(bt_mesh.seq % CONFIG_BT_MESH_SEQ_STORE_RATE));
219*042d53a7SEvalZero 		bt_mesh.seq--;
220*042d53a7SEvalZero 	}
221*042d53a7SEvalZero 
222*042d53a7SEvalZero 	BT_DBG("Sequence Number 0x%06x", bt_mesh.seq);
223*042d53a7SEvalZero 
224*042d53a7SEvalZero 	return 0;
225*042d53a7SEvalZero }
226*042d53a7SEvalZero 
rpl_find(u16_t src)227*042d53a7SEvalZero static struct bt_mesh_rpl *rpl_find(u16_t src)
228*042d53a7SEvalZero {
229*042d53a7SEvalZero 	int i;
230*042d53a7SEvalZero 
231*042d53a7SEvalZero 	for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
232*042d53a7SEvalZero 		if (bt_mesh.rpl[i].src == src) {
233*042d53a7SEvalZero 			return &bt_mesh.rpl[i];
234*042d53a7SEvalZero 		}
235*042d53a7SEvalZero 	}
236*042d53a7SEvalZero 
237*042d53a7SEvalZero 	return NULL;
238*042d53a7SEvalZero }
239*042d53a7SEvalZero 
rpl_alloc(u16_t src)240*042d53a7SEvalZero static struct bt_mesh_rpl *rpl_alloc(u16_t src)
241*042d53a7SEvalZero {
242*042d53a7SEvalZero 	int i;
243*042d53a7SEvalZero 
244*042d53a7SEvalZero 	for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
245*042d53a7SEvalZero 		if (!bt_mesh.rpl[i].src) {
246*042d53a7SEvalZero 			bt_mesh.rpl[i].src = src;
247*042d53a7SEvalZero 			return &bt_mesh.rpl[i];
248*042d53a7SEvalZero 		}
249*042d53a7SEvalZero 	}
250*042d53a7SEvalZero 
251*042d53a7SEvalZero 	return NULL;
252*042d53a7SEvalZero }
253*042d53a7SEvalZero 
rpl_set(int argc,char ** argv,char * val)254*042d53a7SEvalZero static int rpl_set(int argc, char **argv, char *val)
255*042d53a7SEvalZero {
256*042d53a7SEvalZero 	struct bt_mesh_rpl *entry;
257*042d53a7SEvalZero 	struct rpl_val rpl;
258*042d53a7SEvalZero 	int len, err;
259*042d53a7SEvalZero 	u16_t src;
260*042d53a7SEvalZero 
261*042d53a7SEvalZero 	if (argc < 1) {
262*042d53a7SEvalZero 		BT_ERR("Invalid argc (%d)", argc);
263*042d53a7SEvalZero 		return -ENOENT;
264*042d53a7SEvalZero 	}
265*042d53a7SEvalZero 
266*042d53a7SEvalZero 	BT_DBG("argv[0] %s val %s", argv[0], val ? val : "(null)");
267*042d53a7SEvalZero 
268*042d53a7SEvalZero 	src = strtol(argv[0], NULL, 16);
269*042d53a7SEvalZero 	entry = rpl_find(src);
270*042d53a7SEvalZero 
271*042d53a7SEvalZero 	if (!val) {
272*042d53a7SEvalZero 		if (entry) {
273*042d53a7SEvalZero 			memset(entry, 0, sizeof(*entry));
274*042d53a7SEvalZero 		} else {
275*042d53a7SEvalZero 			BT_WARN("Unable to find RPL entry for 0x%04x", src);
276*042d53a7SEvalZero 		}
277*042d53a7SEvalZero 
278*042d53a7SEvalZero 		return 0;
279*042d53a7SEvalZero 	}
280*042d53a7SEvalZero 
281*042d53a7SEvalZero 	if (!entry) {
282*042d53a7SEvalZero 		entry = rpl_alloc(src);
283*042d53a7SEvalZero 		if (!entry) {
284*042d53a7SEvalZero 			BT_ERR("Unable to allocate RPL entry for 0x%04x", src);
285*042d53a7SEvalZero 			return -ENOMEM;
286*042d53a7SEvalZero 		}
287*042d53a7SEvalZero 	}
288*042d53a7SEvalZero 
289*042d53a7SEvalZero 	len = sizeof(rpl);
290*042d53a7SEvalZero 	err = settings_bytes_from_str(val, &rpl, &len);
291*042d53a7SEvalZero 	if (err) {
292*042d53a7SEvalZero 		BT_ERR("Failed to decode value %s (err %d)", val, err);
293*042d53a7SEvalZero 		return err;
294*042d53a7SEvalZero 	}
295*042d53a7SEvalZero 
296*042d53a7SEvalZero 	if (len != sizeof(rpl)) {
297*042d53a7SEvalZero 		BT_ERR("Unexpected value length (%d != %zu)", len, sizeof(rpl));
298*042d53a7SEvalZero 		return -EINVAL;
299*042d53a7SEvalZero 	}
300*042d53a7SEvalZero 
301*042d53a7SEvalZero 	entry->seq = rpl.seq;
302*042d53a7SEvalZero 	entry->old_iv = rpl.old_iv;
303*042d53a7SEvalZero 
304*042d53a7SEvalZero 	BT_DBG("RPL entry for 0x%04x: Seq 0x%06x old_iv %u", entry->src,
305*042d53a7SEvalZero 	       entry->seq, entry->old_iv);
306*042d53a7SEvalZero 
307*042d53a7SEvalZero 	return 0;
308*042d53a7SEvalZero }
309*042d53a7SEvalZero 
net_key_set(int argc,char ** argv,char * val)310*042d53a7SEvalZero static int net_key_set(int argc, char **argv, char *val)
311*042d53a7SEvalZero {
312*042d53a7SEvalZero 	struct bt_mesh_subnet *sub;
313*042d53a7SEvalZero 	struct net_key_val key;
314*042d53a7SEvalZero 	int len, i, err;
315*042d53a7SEvalZero 	u16_t net_idx;
316*042d53a7SEvalZero 
317*042d53a7SEvalZero 	BT_DBG("argv[0] %s val %s", argv[0], val ? val : "(null)");
318*042d53a7SEvalZero 
319*042d53a7SEvalZero 	net_idx = strtol(argv[0], NULL, 16);
320*042d53a7SEvalZero 	sub = bt_mesh_subnet_get(net_idx);
321*042d53a7SEvalZero 
322*042d53a7SEvalZero 	if (!val) {
323*042d53a7SEvalZero 		if (!sub) {
324*042d53a7SEvalZero 			BT_ERR("No subnet with NetKeyIndex 0x%03x", net_idx);
325*042d53a7SEvalZero 			return -ENOENT;
326*042d53a7SEvalZero 		}
327*042d53a7SEvalZero 
328*042d53a7SEvalZero 		BT_DBG("Deleting NetKeyIndex 0x%03x", net_idx);
329*042d53a7SEvalZero 		bt_mesh_subnet_del(sub, false);
330*042d53a7SEvalZero 		return 0;
331*042d53a7SEvalZero 	}
332*042d53a7SEvalZero 
333*042d53a7SEvalZero 	len = sizeof(key);
334*042d53a7SEvalZero 	err = settings_bytes_from_str(val, &key, &len);
335*042d53a7SEvalZero 	if (err) {
336*042d53a7SEvalZero 		BT_ERR("Failed to decode value %s (err %d)", val, err);
337*042d53a7SEvalZero 		return err;
338*042d53a7SEvalZero 	}
339*042d53a7SEvalZero 
340*042d53a7SEvalZero 	if (len != sizeof(key)) {
341*042d53a7SEvalZero 		BT_ERR("Unexpected value length (%d != %zu)", len, sizeof(key));
342*042d53a7SEvalZero 		return -EINVAL;
343*042d53a7SEvalZero 	}
344*042d53a7SEvalZero 
345*042d53a7SEvalZero 	if (sub) {
346*042d53a7SEvalZero 		BT_DBG("Updating existing NetKeyIndex 0x%03x", net_idx);
347*042d53a7SEvalZero 
348*042d53a7SEvalZero 		sub->kr_flag = key.kr_flag;
349*042d53a7SEvalZero 		sub->kr_phase = key.kr_phase;
350*042d53a7SEvalZero 		memcpy(sub->keys[0].net, &key.val[0], 16);
351*042d53a7SEvalZero 		memcpy(sub->keys[1].net, &key.val[1], 16);
352*042d53a7SEvalZero 
353*042d53a7SEvalZero 		return 0;
354*042d53a7SEvalZero 	}
355*042d53a7SEvalZero 
356*042d53a7SEvalZero 	for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
357*042d53a7SEvalZero 		if (bt_mesh.sub[i].net_idx == BT_MESH_KEY_UNUSED) {
358*042d53a7SEvalZero 			sub = &bt_mesh.sub[i];
359*042d53a7SEvalZero 			break;
360*042d53a7SEvalZero 		}
361*042d53a7SEvalZero 	}
362*042d53a7SEvalZero 
363*042d53a7SEvalZero 	if (!sub) {
364*042d53a7SEvalZero 		BT_ERR("No space to allocate a new subnet");
365*042d53a7SEvalZero 		return -ENOMEM;
366*042d53a7SEvalZero 	}
367*042d53a7SEvalZero 
368*042d53a7SEvalZero 	sub->net_idx = net_idx;
369*042d53a7SEvalZero 	sub->kr_flag = key.kr_flag;
370*042d53a7SEvalZero 	sub->kr_phase = key.kr_phase;
371*042d53a7SEvalZero 	memcpy(sub->keys[0].net, &key.val[0], 16);
372*042d53a7SEvalZero 	memcpy(sub->keys[1].net, &key.val[1], 16);
373*042d53a7SEvalZero 
374*042d53a7SEvalZero 	BT_DBG("NetKeyIndex 0x%03x recovered from storage", net_idx);
375*042d53a7SEvalZero 
376*042d53a7SEvalZero 	return 0;
377*042d53a7SEvalZero }
378*042d53a7SEvalZero 
app_key_set(int argc,char ** argv,char * val)379*042d53a7SEvalZero static int app_key_set(int argc, char **argv, char *val)
380*042d53a7SEvalZero {
381*042d53a7SEvalZero 	struct bt_mesh_app_key *app;
382*042d53a7SEvalZero 	struct bt_mesh_subnet *sub;
383*042d53a7SEvalZero 	struct app_key_val key;
384*042d53a7SEvalZero 	u16_t app_idx;
385*042d53a7SEvalZero 	int len, err;
386*042d53a7SEvalZero 
387*042d53a7SEvalZero 	BT_DBG("argv[0] %s val %s", argv[0], val ? val : "(null)");
388*042d53a7SEvalZero 
389*042d53a7SEvalZero 	app_idx = strtol(argv[0], NULL, 16);
390*042d53a7SEvalZero 
391*042d53a7SEvalZero 	if (!val) {
392*042d53a7SEvalZero 		BT_DBG("Deleting AppKeyIndex 0x%03x", app_idx);
393*042d53a7SEvalZero 
394*042d53a7SEvalZero 		app = bt_mesh_app_key_find(app_idx);
395*042d53a7SEvalZero 		if (app) {
396*042d53a7SEvalZero 			bt_mesh_app_key_del(app, false);
397*042d53a7SEvalZero 		}
398*042d53a7SEvalZero 
399*042d53a7SEvalZero 		return 0;
400*042d53a7SEvalZero 	}
401*042d53a7SEvalZero 
402*042d53a7SEvalZero 	len = sizeof(key);
403*042d53a7SEvalZero 	err = settings_bytes_from_str(val, &key, &len);
404*042d53a7SEvalZero 	if (err) {
405*042d53a7SEvalZero 		BT_ERR("Failed to decode value %s (err %d)", val, err);
406*042d53a7SEvalZero 		return err;
407*042d53a7SEvalZero 	}
408*042d53a7SEvalZero 
409*042d53a7SEvalZero 	if (len != sizeof(key)) {
410*042d53a7SEvalZero 		BT_ERR("Unexpected value length (%d != %zu)", len, sizeof(key));
411*042d53a7SEvalZero 		return -EINVAL;
412*042d53a7SEvalZero 	}
413*042d53a7SEvalZero 
414*042d53a7SEvalZero 	sub = bt_mesh_subnet_get(key.net_idx);
415*042d53a7SEvalZero 	if (!sub) {
416*042d53a7SEvalZero 		BT_ERR("Failed to find subnet 0x%03x", key.net_idx);
417*042d53a7SEvalZero 		return -ENOENT;
418*042d53a7SEvalZero 	}
419*042d53a7SEvalZero 
420*042d53a7SEvalZero 	app = bt_mesh_app_key_find(app_idx);
421*042d53a7SEvalZero 	if (!app) {
422*042d53a7SEvalZero 		app = bt_mesh_app_key_alloc(app_idx);
423*042d53a7SEvalZero 	}
424*042d53a7SEvalZero 
425*042d53a7SEvalZero 	if (!app) {
426*042d53a7SEvalZero 		BT_ERR("No space for a new app key");
427*042d53a7SEvalZero 		return -ENOMEM;
428*042d53a7SEvalZero 	}
429*042d53a7SEvalZero 
430*042d53a7SEvalZero 	app->net_idx = key.net_idx;
431*042d53a7SEvalZero 	app->app_idx = app_idx;
432*042d53a7SEvalZero 	app->updated = key.updated;
433*042d53a7SEvalZero 	memcpy(app->keys[0].val, key.val[0], 16);
434*042d53a7SEvalZero 	memcpy(app->keys[1].val, key.val[1], 16);
435*042d53a7SEvalZero 
436*042d53a7SEvalZero 	bt_mesh_app_id(app->keys[0].val, &app->keys[0].id);
437*042d53a7SEvalZero 	bt_mesh_app_id(app->keys[1].val, &app->keys[1].id);
438*042d53a7SEvalZero 
439*042d53a7SEvalZero 	BT_DBG("AppKeyIndex 0x%03x recovered from storage", app_idx);
440*042d53a7SEvalZero 
441*042d53a7SEvalZero 	return 0;
442*042d53a7SEvalZero }
443*042d53a7SEvalZero 
hb_pub_set(int argc,char ** argv,char * val)444*042d53a7SEvalZero static int hb_pub_set(int argc, char **argv, char *val)
445*042d53a7SEvalZero {
446*042d53a7SEvalZero 	struct bt_mesh_hb_pub *pub = bt_mesh_hb_pub_get();
447*042d53a7SEvalZero 	struct hb_pub_val hb_val;
448*042d53a7SEvalZero 	int len, err;
449*042d53a7SEvalZero 
450*042d53a7SEvalZero 	BT_DBG("val %s", val ? val : "(null)");
451*042d53a7SEvalZero 
452*042d53a7SEvalZero 	if (!pub) {
453*042d53a7SEvalZero 		return -ENOENT;
454*042d53a7SEvalZero 	}
455*042d53a7SEvalZero 
456*042d53a7SEvalZero 	if (!val) {
457*042d53a7SEvalZero 		pub->dst = BT_MESH_ADDR_UNASSIGNED;
458*042d53a7SEvalZero 		pub->count = 0;
459*042d53a7SEvalZero 		pub->ttl = 0;
460*042d53a7SEvalZero 		pub->period = 0;
461*042d53a7SEvalZero 		pub->feat = 0;
462*042d53a7SEvalZero 
463*042d53a7SEvalZero 		BT_DBG("Cleared heartbeat publication");
464*042d53a7SEvalZero 		return 0;
465*042d53a7SEvalZero 	}
466*042d53a7SEvalZero 
467*042d53a7SEvalZero 	len = sizeof(hb_val);
468*042d53a7SEvalZero 	err = settings_bytes_from_str(val, &hb_val, &len);
469*042d53a7SEvalZero 	if (err) {
470*042d53a7SEvalZero 		BT_ERR("Failed to decode value %s (err %d)", val, err);
471*042d53a7SEvalZero 		return err;
472*042d53a7SEvalZero 	}
473*042d53a7SEvalZero 
474*042d53a7SEvalZero 	if (len != sizeof(hb_val)) {
475*042d53a7SEvalZero 		BT_ERR("Unexpected value length (%d != %zu)", len,
476*042d53a7SEvalZero 		       sizeof(hb_val));
477*042d53a7SEvalZero 		return -EINVAL;
478*042d53a7SEvalZero 	}
479*042d53a7SEvalZero 
480*042d53a7SEvalZero 	pub->dst = hb_val.dst;
481*042d53a7SEvalZero 	pub->period = hb_val.period;
482*042d53a7SEvalZero 	pub->ttl = hb_val.ttl;
483*042d53a7SEvalZero 	pub->feat = hb_val.feat;
484*042d53a7SEvalZero 	pub->net_idx = hb_val.net_idx;
485*042d53a7SEvalZero 
486*042d53a7SEvalZero 	if (hb_val.indefinite) {
487*042d53a7SEvalZero 		pub->count = 0xffff;
488*042d53a7SEvalZero 	} else {
489*042d53a7SEvalZero 		pub->count = 0;
490*042d53a7SEvalZero 	}
491*042d53a7SEvalZero 
492*042d53a7SEvalZero 	BT_DBG("Restored heartbeat publication");
493*042d53a7SEvalZero 
494*042d53a7SEvalZero 	return 0;
495*042d53a7SEvalZero }
496*042d53a7SEvalZero 
cfg_set(int argc,char ** argv,char * val)497*042d53a7SEvalZero static int cfg_set(int argc, char **argv, char *val)
498*042d53a7SEvalZero {
499*042d53a7SEvalZero 	struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
500*042d53a7SEvalZero 	int len, err;
501*042d53a7SEvalZero 
502*042d53a7SEvalZero 	BT_DBG("val %s", val ? val : "(null)");
503*042d53a7SEvalZero 
504*042d53a7SEvalZero 	if (!cfg) {
505*042d53a7SEvalZero 		return -ENOENT;
506*042d53a7SEvalZero 	}
507*042d53a7SEvalZero 
508*042d53a7SEvalZero 	if (!val) {
509*042d53a7SEvalZero 		stored_cfg.valid = false;
510*042d53a7SEvalZero 		BT_DBG("Cleared configuration state");
511*042d53a7SEvalZero 		return 0;
512*042d53a7SEvalZero 	}
513*042d53a7SEvalZero 
514*042d53a7SEvalZero 	len = sizeof(stored_cfg.cfg);
515*042d53a7SEvalZero 	err = settings_bytes_from_str(val, &stored_cfg.cfg, &len);
516*042d53a7SEvalZero 	if (err) {
517*042d53a7SEvalZero 		BT_ERR("Failed to decode value %s (err %d)", val, err);
518*042d53a7SEvalZero 		return err;
519*042d53a7SEvalZero 	}
520*042d53a7SEvalZero 
521*042d53a7SEvalZero 	if (len != sizeof(stored_cfg.cfg)) {
522*042d53a7SEvalZero 		BT_ERR("Unexpected value length (%d != %zu)", len,
523*042d53a7SEvalZero 		       sizeof(stored_cfg.cfg));
524*042d53a7SEvalZero 		return -EINVAL;
525*042d53a7SEvalZero 	}
526*042d53a7SEvalZero 
527*042d53a7SEvalZero 	stored_cfg.valid = true;
528*042d53a7SEvalZero 	BT_DBG("Restored configuration state");
529*042d53a7SEvalZero 
530*042d53a7SEvalZero 	return 0;
531*042d53a7SEvalZero }
532*042d53a7SEvalZero 
mod_set_bind(struct bt_mesh_model * mod,char * val)533*042d53a7SEvalZero static int mod_set_bind(struct bt_mesh_model *mod, char *val)
534*042d53a7SEvalZero {
535*042d53a7SEvalZero 	int len, err, i;
536*042d53a7SEvalZero 
537*042d53a7SEvalZero 	/* Start with empty array regardless of cleared or set value */
538*042d53a7SEvalZero 	for (i = 0; i < ARRAY_SIZE(mod->keys); i++) {
539*042d53a7SEvalZero 		mod->keys[i] = BT_MESH_KEY_UNUSED;
540*042d53a7SEvalZero 	}
541*042d53a7SEvalZero 
542*042d53a7SEvalZero 	if (!val) {
543*042d53a7SEvalZero 		BT_DBG("Cleared bindings for model");
544*042d53a7SEvalZero 		return 0;
545*042d53a7SEvalZero 	}
546*042d53a7SEvalZero 
547*042d53a7SEvalZero 	len = sizeof(mod->keys);
548*042d53a7SEvalZero 	err = settings_bytes_from_str(val, mod->keys, &len);
549*042d53a7SEvalZero 	if (err) {
550*042d53a7SEvalZero 		BT_ERR("Failed to decode value %s (err %d)", val, err);
551*042d53a7SEvalZero 		return -EINVAL;
552*042d53a7SEvalZero 	}
553*042d53a7SEvalZero 
554*042d53a7SEvalZero 	BT_DBG("Decoded %u bound keys for model", len / sizeof(mod->keys[0]));
555*042d53a7SEvalZero 	return 0;
556*042d53a7SEvalZero }
557*042d53a7SEvalZero 
mod_set_sub(struct bt_mesh_model * mod,char * val)558*042d53a7SEvalZero static int mod_set_sub(struct bt_mesh_model *mod, char *val)
559*042d53a7SEvalZero {
560*042d53a7SEvalZero 	int len, err;
561*042d53a7SEvalZero 
562*042d53a7SEvalZero 	/* Start with empty array regardless of cleared or set value */
563*042d53a7SEvalZero 	memset(mod->groups, 0, sizeof(mod->groups));
564*042d53a7SEvalZero 
565*042d53a7SEvalZero 	if (!val) {
566*042d53a7SEvalZero 		BT_DBG("Cleared subscriptions for model");
567*042d53a7SEvalZero 		return 0;
568*042d53a7SEvalZero 	}
569*042d53a7SEvalZero 
570*042d53a7SEvalZero 	len = sizeof(mod->groups);
571*042d53a7SEvalZero 	err = settings_bytes_from_str(val, mod->groups, &len);
572*042d53a7SEvalZero 	if (err) {
573*042d53a7SEvalZero 		BT_ERR("Failed to decode value %s (err %d)", val, err);
574*042d53a7SEvalZero 		return -EINVAL;
575*042d53a7SEvalZero 	}
576*042d53a7SEvalZero 
577*042d53a7SEvalZero 	BT_DBG("Decoded %u subscribed group addresses for model",
578*042d53a7SEvalZero 	       len / sizeof(mod->groups[0]));
579*042d53a7SEvalZero 	return 0;
580*042d53a7SEvalZero }
581*042d53a7SEvalZero 
mod_set_pub(struct bt_mesh_model * mod,char * val)582*042d53a7SEvalZero static int mod_set_pub(struct bt_mesh_model *mod, char *val)
583*042d53a7SEvalZero {
584*042d53a7SEvalZero 	struct mod_pub_val pub;
585*042d53a7SEvalZero 	int len, err;
586*042d53a7SEvalZero 
587*042d53a7SEvalZero 	if (!mod->pub) {
588*042d53a7SEvalZero 		BT_WARN("Model has no publication context!");
589*042d53a7SEvalZero 		return -EINVAL;
590*042d53a7SEvalZero 	}
591*042d53a7SEvalZero 
592*042d53a7SEvalZero 	if (!val) {
593*042d53a7SEvalZero 		mod->pub->addr = BT_MESH_ADDR_UNASSIGNED;
594*042d53a7SEvalZero 		mod->pub->key = 0;
595*042d53a7SEvalZero 		mod->pub->cred = 0;
596*042d53a7SEvalZero 		mod->pub->ttl = 0;
597*042d53a7SEvalZero 		mod->pub->period = 0;
598*042d53a7SEvalZero 		mod->pub->retransmit = 0;
599*042d53a7SEvalZero 		mod->pub->count = 0;
600*042d53a7SEvalZero 
601*042d53a7SEvalZero 		BT_DBG("Cleared publication for model");
602*042d53a7SEvalZero 		return 0;
603*042d53a7SEvalZero 	}
604*042d53a7SEvalZero 
605*042d53a7SEvalZero 	len = sizeof(pub);
606*042d53a7SEvalZero 	err = settings_bytes_from_str(val, &pub, &len);
607*042d53a7SEvalZero 	if (err) {
608*042d53a7SEvalZero 		BT_ERR("Failed to decode value %s (err %d)", val, err);
609*042d53a7SEvalZero 		return -EINVAL;
610*042d53a7SEvalZero 	}
611*042d53a7SEvalZero 
612*042d53a7SEvalZero 	if (len != sizeof(pub)) {
613*042d53a7SEvalZero 		BT_ERR("Invalid length for model publication");
614*042d53a7SEvalZero 		return -EINVAL;
615*042d53a7SEvalZero 	}
616*042d53a7SEvalZero 
617*042d53a7SEvalZero 	mod->pub->addr = pub.addr;
618*042d53a7SEvalZero 	mod->pub->key = pub.key;
619*042d53a7SEvalZero 	mod->pub->cred = pub.cred;
620*042d53a7SEvalZero 	mod->pub->ttl = pub.ttl;
621*042d53a7SEvalZero 	mod->pub->period = pub.period;
622*042d53a7SEvalZero 	mod->pub->retransmit = pub.retransmit;
623*042d53a7SEvalZero 	mod->pub->count = 0;
624*042d53a7SEvalZero 
625*042d53a7SEvalZero 	BT_DBG("Restored model publication, dst 0x%04x app_idx 0x%03x",
626*042d53a7SEvalZero 	       pub.addr, pub.key);
627*042d53a7SEvalZero 
628*042d53a7SEvalZero 	return 0;
629*042d53a7SEvalZero }
630*042d53a7SEvalZero 
mod_set(bool vnd,int argc,char ** argv,char * val)631*042d53a7SEvalZero static int mod_set(bool vnd, int argc, char **argv, char *val)
632*042d53a7SEvalZero {
633*042d53a7SEvalZero 	struct bt_mesh_model *mod;
634*042d53a7SEvalZero 	u8_t elem_idx, mod_idx;
635*042d53a7SEvalZero 	u16_t mod_key;
636*042d53a7SEvalZero 
637*042d53a7SEvalZero 	if (argc < 2) {
638*042d53a7SEvalZero 		BT_ERR("Too small argc (%d)", argc);
639*042d53a7SEvalZero 		return -ENOENT;
640*042d53a7SEvalZero 	}
641*042d53a7SEvalZero 
642*042d53a7SEvalZero 	mod_key = strtol(argv[0], NULL, 16);
643*042d53a7SEvalZero 	elem_idx = mod_key >> 8;
644*042d53a7SEvalZero 	mod_idx = mod_key;
645*042d53a7SEvalZero 
646*042d53a7SEvalZero 	BT_DBG("Decoded mod_key 0x%04x as elem_idx %u mod_idx %u",
647*042d53a7SEvalZero 	       mod_key, elem_idx, mod_idx);
648*042d53a7SEvalZero 
649*042d53a7SEvalZero 	mod = bt_mesh_model_get(vnd, elem_idx, mod_idx);
650*042d53a7SEvalZero 	if (!mod) {
651*042d53a7SEvalZero 		BT_ERR("Failed to get model for elem_idx %u mod_idx %u",
652*042d53a7SEvalZero 		       elem_idx, mod_idx);
653*042d53a7SEvalZero 		return -ENOENT;
654*042d53a7SEvalZero 	}
655*042d53a7SEvalZero 
656*042d53a7SEvalZero 	if (!strcmp(argv[1], "bind")) {
657*042d53a7SEvalZero 		return mod_set_bind(mod, val);
658*042d53a7SEvalZero 	}
659*042d53a7SEvalZero 
660*042d53a7SEvalZero 	if (!strcmp(argv[1], "sub")) {
661*042d53a7SEvalZero 		return mod_set_sub(mod, val);
662*042d53a7SEvalZero 	}
663*042d53a7SEvalZero 
664*042d53a7SEvalZero 	if (!strcmp(argv[1], "pub")) {
665*042d53a7SEvalZero 		return mod_set_pub(mod, val);
666*042d53a7SEvalZero 	}
667*042d53a7SEvalZero 
668*042d53a7SEvalZero 	BT_WARN("Unknown module key %s", argv[1]);
669*042d53a7SEvalZero 	return -ENOENT;
670*042d53a7SEvalZero }
671*042d53a7SEvalZero 
sig_mod_set(int argc,char ** argv,char * val)672*042d53a7SEvalZero static int sig_mod_set(int argc, char **argv, char *val)
673*042d53a7SEvalZero {
674*042d53a7SEvalZero 	return mod_set(false, argc, argv, val);
675*042d53a7SEvalZero }
676*042d53a7SEvalZero 
vnd_mod_set(int argc,char ** argv,char * val)677*042d53a7SEvalZero static int vnd_mod_set(int argc, char **argv, char *val)
678*042d53a7SEvalZero {
679*042d53a7SEvalZero 	return mod_set(true, argc, argv, val);
680*042d53a7SEvalZero }
681*042d53a7SEvalZero 
682*042d53a7SEvalZero const struct mesh_setting {
683*042d53a7SEvalZero 	const char *name;
684*042d53a7SEvalZero 	int (*func)(int argc, char **argv, char *val);
685*042d53a7SEvalZero } settings[] = {
686*042d53a7SEvalZero 	{ "Net", net_set },
687*042d53a7SEvalZero 	{ "IV", iv_set },
688*042d53a7SEvalZero 	{ "Seq", seq_set },
689*042d53a7SEvalZero 	{ "RPL", rpl_set },
690*042d53a7SEvalZero 	{ "NetKey", net_key_set },
691*042d53a7SEvalZero 	{ "AppKey", app_key_set },
692*042d53a7SEvalZero 	{ "HBPub", hb_pub_set },
693*042d53a7SEvalZero 	{ "Cfg", cfg_set },
694*042d53a7SEvalZero 	{ "s", sig_mod_set },
695*042d53a7SEvalZero 	{ "v", vnd_mod_set },
696*042d53a7SEvalZero };
697*042d53a7SEvalZero 
mesh_set(int argc,char ** argv,char * val)698*042d53a7SEvalZero static int mesh_set(int argc, char **argv, char *val)
699*042d53a7SEvalZero {
700*042d53a7SEvalZero 	int i;
701*042d53a7SEvalZero 
702*042d53a7SEvalZero 	if (argc < 1) {
703*042d53a7SEvalZero 		BT_ERR("Insufficient number of arguments");
704*042d53a7SEvalZero 		return -EINVAL;
705*042d53a7SEvalZero 	}
706*042d53a7SEvalZero 
707*042d53a7SEvalZero 	BT_DBG("argv[0] %s val %s", argv[0], val ? val : "(null)");
708*042d53a7SEvalZero 
709*042d53a7SEvalZero 	for (i = 0; i < ARRAY_SIZE(settings); i++) {
710*042d53a7SEvalZero 		if (!strcmp(settings[i].name, argv[0])) {
711*042d53a7SEvalZero 			argc--;
712*042d53a7SEvalZero 			argv++;
713*042d53a7SEvalZero 
714*042d53a7SEvalZero 			return settings[i].func(argc, argv, val);
715*042d53a7SEvalZero 		}
716*042d53a7SEvalZero 	}
717*042d53a7SEvalZero 
718*042d53a7SEvalZero 	BT_WARN("No matching handler for key %s", argv[0]);
719*042d53a7SEvalZero 
720*042d53a7SEvalZero 	return -ENOENT;
721*042d53a7SEvalZero }
722*042d53a7SEvalZero 
subnet_init(struct bt_mesh_subnet * sub)723*042d53a7SEvalZero static int subnet_init(struct bt_mesh_subnet *sub)
724*042d53a7SEvalZero {
725*042d53a7SEvalZero 	int err;
726*042d53a7SEvalZero 
727*042d53a7SEvalZero 	err = bt_mesh_net_keys_create(&sub->keys[0], sub->keys[0].net);
728*042d53a7SEvalZero 	if (err) {
729*042d53a7SEvalZero 		BT_ERR("Unable to generate keys for subnet");
730*042d53a7SEvalZero 		return -EIO;
731*042d53a7SEvalZero 	}
732*042d53a7SEvalZero 
733*042d53a7SEvalZero 	if (sub->kr_phase != BT_MESH_KR_NORMAL) {
734*042d53a7SEvalZero 		err = bt_mesh_net_keys_create(&sub->keys[1], sub->keys[1].net);
735*042d53a7SEvalZero 		if (err) {
736*042d53a7SEvalZero 			BT_ERR("Unable to generate keys for subnet");
737*042d53a7SEvalZero 			memset(&sub->keys[0], 0, sizeof(sub->keys[0]));
738*042d53a7SEvalZero 			return -EIO;
739*042d53a7SEvalZero 		}
740*042d53a7SEvalZero 	}
741*042d53a7SEvalZero 
742*042d53a7SEvalZero 	if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
743*042d53a7SEvalZero 		sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED;
744*042d53a7SEvalZero 	} else {
745*042d53a7SEvalZero 		sub->node_id = BT_MESH_NODE_IDENTITY_NOT_SUPPORTED;
746*042d53a7SEvalZero 	}
747*042d53a7SEvalZero 
748*042d53a7SEvalZero 	/* Make sure we have valid beacon data to be sent */
749*042d53a7SEvalZero 	bt_mesh_net_beacon_update(sub);
750*042d53a7SEvalZero 
751*042d53a7SEvalZero 	return 0;
752*042d53a7SEvalZero }
753*042d53a7SEvalZero 
commit_mod(struct bt_mesh_model * mod,struct bt_mesh_elem * elem,bool vnd,bool primary,void * user_data)754*042d53a7SEvalZero static void commit_mod(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
755*042d53a7SEvalZero 		       bool vnd, bool primary, void *user_data)
756*042d53a7SEvalZero {
757*042d53a7SEvalZero 	if (mod->pub && mod->pub->update &&
758*042d53a7SEvalZero 	    mod->pub->addr != BT_MESH_ADDR_UNASSIGNED) {
759*042d53a7SEvalZero 		s32_t ms = bt_mesh_model_pub_period_get(mod);
760*042d53a7SEvalZero 		if (ms) {
761*042d53a7SEvalZero 			BT_DBG("Starting publish timer (period %u ms)", ms);
762*042d53a7SEvalZero 			k_delayed_work_submit(&mod->pub->timer, ms);
763*042d53a7SEvalZero 		}
764*042d53a7SEvalZero 	}
765*042d53a7SEvalZero }
766*042d53a7SEvalZero 
mesh_commit(void)767*042d53a7SEvalZero static int mesh_commit(void)
768*042d53a7SEvalZero {
769*042d53a7SEvalZero 	struct bt_mesh_hb_pub *hb_pub;
770*042d53a7SEvalZero 	struct bt_mesh_cfg_srv *cfg;
771*042d53a7SEvalZero 	int i;
772*042d53a7SEvalZero 
773*042d53a7SEvalZero 	BT_DBG("sub[0].net_idx 0x%03x", bt_mesh.sub[0].net_idx);
774*042d53a7SEvalZero 
775*042d53a7SEvalZero 	if (bt_mesh.sub[0].net_idx == BT_MESH_KEY_UNUSED) {
776*042d53a7SEvalZero 		/* Nothing to do since we're not yet provisioned */
777*042d53a7SEvalZero 		return 0;
778*042d53a7SEvalZero 	}
779*042d53a7SEvalZero 
780*042d53a7SEvalZero 	if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) {
781*042d53a7SEvalZero 		bt_mesh_proxy_prov_disable();
782*042d53a7SEvalZero 	}
783*042d53a7SEvalZero 
784*042d53a7SEvalZero 	for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
785*042d53a7SEvalZero 		struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
786*042d53a7SEvalZero 		int err;
787*042d53a7SEvalZero 
788*042d53a7SEvalZero 		if (sub->net_idx == BT_MESH_KEY_UNUSED) {
789*042d53a7SEvalZero 			continue;
790*042d53a7SEvalZero 		}
791*042d53a7SEvalZero 
792*042d53a7SEvalZero 		err = subnet_init(sub);
793*042d53a7SEvalZero 		if (err) {
794*042d53a7SEvalZero 			BT_ERR("Failed to init subnet 0x%03x", sub->net_idx);
795*042d53a7SEvalZero 		}
796*042d53a7SEvalZero 	}
797*042d53a7SEvalZero 
798*042d53a7SEvalZero 	if (bt_mesh.ivu_duration < BT_MESH_IVU_MIN_HOURS) {
799*042d53a7SEvalZero 		k_delayed_work_submit(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT);
800*042d53a7SEvalZero 	}
801*042d53a7SEvalZero 
802*042d53a7SEvalZero 	bt_mesh_model_foreach(commit_mod, NULL);
803*042d53a7SEvalZero 
804*042d53a7SEvalZero 	hb_pub = bt_mesh_hb_pub_get();
805*042d53a7SEvalZero 	if (hb_pub && hb_pub->dst != BT_MESH_ADDR_UNASSIGNED &&
806*042d53a7SEvalZero 	    hb_pub->count && hb_pub->period) {
807*042d53a7SEvalZero 		BT_DBG("Starting heartbeat publication");
808*042d53a7SEvalZero 		k_work_submit(&hb_pub->timer.work);
809*042d53a7SEvalZero 	}
810*042d53a7SEvalZero 
811*042d53a7SEvalZero 	cfg = bt_mesh_cfg_get();
812*042d53a7SEvalZero 	if (cfg && stored_cfg.valid) {
813*042d53a7SEvalZero 		cfg->net_transmit = stored_cfg.cfg.net_transmit;
814*042d53a7SEvalZero 		cfg->relay = stored_cfg.cfg.relay;
815*042d53a7SEvalZero 		cfg->relay_retransmit = stored_cfg.cfg.relay_retransmit;
816*042d53a7SEvalZero 		cfg->beacon = stored_cfg.cfg.beacon;
817*042d53a7SEvalZero 		cfg->gatt_proxy = stored_cfg.cfg.gatt_proxy;
818*042d53a7SEvalZero 		cfg->frnd = stored_cfg.cfg.frnd;
819*042d53a7SEvalZero 		cfg->default_ttl = stored_cfg.cfg.default_ttl;
820*042d53a7SEvalZero 	}
821*042d53a7SEvalZero 
822*042d53a7SEvalZero 	bt_mesh.valid = 1;
823*042d53a7SEvalZero 
824*042d53a7SEvalZero 	bt_mesh_net_start();
825*042d53a7SEvalZero 
826*042d53a7SEvalZero 	return 0;
827*042d53a7SEvalZero }
828*042d53a7SEvalZero 
schedule_store(int flag)829*042d53a7SEvalZero static void schedule_store(int flag)
830*042d53a7SEvalZero {
831*042d53a7SEvalZero 	s32_t timeout;
832*042d53a7SEvalZero 
833*042d53a7SEvalZero 	atomic_set_bit(bt_mesh.flags, flag);
834*042d53a7SEvalZero 
835*042d53a7SEvalZero 	if (atomic_test_bit(bt_mesh.flags, BT_MESH_NET_PENDING) ||
836*042d53a7SEvalZero 	    atomic_test_bit(bt_mesh.flags, BT_MESH_IV_PENDING) ||
837*042d53a7SEvalZero 	    atomic_test_bit(bt_mesh.flags, BT_MESH_SEQ_PENDING)) {
838*042d53a7SEvalZero 		timeout = K_NO_WAIT;
839*042d53a7SEvalZero 	} else if (atomic_test_bit(bt_mesh.flags, BT_MESH_RPL_PENDING) &&
840*042d53a7SEvalZero 		   (CONFIG_BT_MESH_RPL_STORE_TIMEOUT <
841*042d53a7SEvalZero 		    CONFIG_BT_MESH_STORE_TIMEOUT)) {
842*042d53a7SEvalZero 		timeout = K_SECONDS(CONFIG_BT_MESH_RPL_STORE_TIMEOUT);
843*042d53a7SEvalZero 	} else {
844*042d53a7SEvalZero 		timeout = K_SECONDS(CONFIG_BT_MESH_STORE_TIMEOUT);
845*042d53a7SEvalZero 	}
846*042d53a7SEvalZero 
847*042d53a7SEvalZero 	BT_DBG("Waiting %d seconds", timeout / MSEC_PER_SEC);
848*042d53a7SEvalZero 
849*042d53a7SEvalZero 	k_delayed_work_submit(&pending_store, timeout);
850*042d53a7SEvalZero }
851*042d53a7SEvalZero 
clear_iv(void)852*042d53a7SEvalZero static void clear_iv(void)
853*042d53a7SEvalZero {
854*042d53a7SEvalZero 	BT_DBG("Clearing IV");
855*042d53a7SEvalZero 	settings_save_one("bt_mesh/IV", NULL);
856*042d53a7SEvalZero }
857*042d53a7SEvalZero 
clear_net(void)858*042d53a7SEvalZero static void clear_net(void)
859*042d53a7SEvalZero {
860*042d53a7SEvalZero 	BT_DBG("Clearing Network");
861*042d53a7SEvalZero 	settings_save_one("bt_mesh/Net", NULL);
862*042d53a7SEvalZero }
863*042d53a7SEvalZero 
store_pending_net(void)864*042d53a7SEvalZero static void store_pending_net(void)
865*042d53a7SEvalZero {
866*042d53a7SEvalZero 	char buf[BT_SETTINGS_SIZE(sizeof(struct net_val))];
867*042d53a7SEvalZero 	struct net_val net;
868*042d53a7SEvalZero 	char *str;
869*042d53a7SEvalZero 
870*042d53a7SEvalZero 	BT_DBG("addr 0x%04x DevKey %s", bt_mesh_primary_addr(),
871*042d53a7SEvalZero 	       bt_hex(bt_mesh.dev_key, 16));
872*042d53a7SEvalZero 
873*042d53a7SEvalZero 	net.primary_addr = bt_mesh_primary_addr();
874*042d53a7SEvalZero 	memcpy(net.dev_key, bt_mesh.dev_key, 16);
875*042d53a7SEvalZero 
876*042d53a7SEvalZero 	str = settings_str_from_bytes(&net, sizeof(net), buf, sizeof(buf));
877*042d53a7SEvalZero 	if (!str) {
878*042d53a7SEvalZero 		BT_ERR("Unable to encode Network as value");
879*042d53a7SEvalZero 		return;
880*042d53a7SEvalZero 	}
881*042d53a7SEvalZero 
882*042d53a7SEvalZero 	BT_DBG("Saving Network as value %s", str);
883*042d53a7SEvalZero 	settings_save_one("bt_mesh/Net", str);
884*042d53a7SEvalZero }
885*042d53a7SEvalZero 
bt_mesh_store_net(void)886*042d53a7SEvalZero void bt_mesh_store_net(void)
887*042d53a7SEvalZero {
888*042d53a7SEvalZero 	schedule_store(BT_MESH_NET_PENDING);
889*042d53a7SEvalZero }
890*042d53a7SEvalZero 
store_pending_iv(void)891*042d53a7SEvalZero static void store_pending_iv(void)
892*042d53a7SEvalZero {
893*042d53a7SEvalZero 	char buf[BT_SETTINGS_SIZE(sizeof(struct iv_val))];
894*042d53a7SEvalZero 	struct iv_val iv;
895*042d53a7SEvalZero 	char *str;
896*042d53a7SEvalZero 
897*042d53a7SEvalZero 	iv.iv_index = bt_mesh.iv_index;
898*042d53a7SEvalZero 	iv.iv_update = bt_mesh.iv_update;
899*042d53a7SEvalZero 	iv.iv_duration = bt_mesh.ivu_duration;
900*042d53a7SEvalZero 
901*042d53a7SEvalZero 	str = settings_str_from_bytes(&iv, sizeof(iv), buf, sizeof(buf));
902*042d53a7SEvalZero 	if (!str) {
903*042d53a7SEvalZero 		BT_ERR("Unable to encode IV as value");
904*042d53a7SEvalZero 		return;
905*042d53a7SEvalZero 	}
906*042d53a7SEvalZero 
907*042d53a7SEvalZero 	BT_DBG("Saving IV as value %s", str);
908*042d53a7SEvalZero 	settings_save_one("bt_mesh/IV", str);
909*042d53a7SEvalZero }
910*042d53a7SEvalZero 
bt_mesh_store_iv(bool only_duration)911*042d53a7SEvalZero void bt_mesh_store_iv(bool only_duration)
912*042d53a7SEvalZero {
913*042d53a7SEvalZero 	schedule_store(BT_MESH_IV_PENDING);
914*042d53a7SEvalZero 
915*042d53a7SEvalZero 	if (!only_duration) {
916*042d53a7SEvalZero 		/* Always update Seq whenever IV changes */
917*042d53a7SEvalZero 		schedule_store(BT_MESH_SEQ_PENDING);
918*042d53a7SEvalZero 	}
919*042d53a7SEvalZero }
920*042d53a7SEvalZero 
store_pending_seq(void)921*042d53a7SEvalZero static void store_pending_seq(void)
922*042d53a7SEvalZero {
923*042d53a7SEvalZero 	char buf[BT_SETTINGS_SIZE(sizeof(struct seq_val))];
924*042d53a7SEvalZero 	struct seq_val seq;
925*042d53a7SEvalZero 	char *str;
926*042d53a7SEvalZero 
927*042d53a7SEvalZero 	seq.val[0] = bt_mesh.seq;
928*042d53a7SEvalZero 	seq.val[1] = bt_mesh.seq >> 8;
929*042d53a7SEvalZero 	seq.val[2] = bt_mesh.seq >> 16;
930*042d53a7SEvalZero 
931*042d53a7SEvalZero 	str = settings_str_from_bytes(&seq, sizeof(seq), buf, sizeof(buf));
932*042d53a7SEvalZero 	if (!str) {
933*042d53a7SEvalZero 		BT_ERR("Unable to encode Seq as value");
934*042d53a7SEvalZero 		return;
935*042d53a7SEvalZero 	}
936*042d53a7SEvalZero 
937*042d53a7SEvalZero 	BT_DBG("Saving Seq as value %s", str);
938*042d53a7SEvalZero 	settings_save_one("bt_mesh/Seq", str);
939*042d53a7SEvalZero }
940*042d53a7SEvalZero 
bt_mesh_store_seq(void)941*042d53a7SEvalZero void bt_mesh_store_seq(void)
942*042d53a7SEvalZero {
943*042d53a7SEvalZero 	if (CONFIG_BT_MESH_SEQ_STORE_RATE &&
944*042d53a7SEvalZero 	    (bt_mesh.seq % CONFIG_BT_MESH_SEQ_STORE_RATE)) {
945*042d53a7SEvalZero 		return;
946*042d53a7SEvalZero 	}
947*042d53a7SEvalZero 
948*042d53a7SEvalZero 	schedule_store(BT_MESH_SEQ_PENDING);
949*042d53a7SEvalZero }
950*042d53a7SEvalZero 
store_rpl(struct bt_mesh_rpl * entry)951*042d53a7SEvalZero static void store_rpl(struct bt_mesh_rpl *entry)
952*042d53a7SEvalZero {
953*042d53a7SEvalZero 	char buf[BT_SETTINGS_SIZE(sizeof(struct rpl_val))];
954*042d53a7SEvalZero 	struct rpl_val rpl;
955*042d53a7SEvalZero 	char path[18];
956*042d53a7SEvalZero 	char *str;
957*042d53a7SEvalZero 
958*042d53a7SEvalZero 	BT_DBG("src 0x%04x seq 0x%06x old_iv %u", entry->src, entry->seq,
959*042d53a7SEvalZero 	       entry->old_iv);
960*042d53a7SEvalZero 
961*042d53a7SEvalZero 	rpl.seq = entry->seq;
962*042d53a7SEvalZero 	rpl.old_iv = entry->old_iv;
963*042d53a7SEvalZero 
964*042d53a7SEvalZero 	str = settings_str_from_bytes(&rpl, sizeof(rpl), buf, sizeof(buf));
965*042d53a7SEvalZero 	if (!str) {
966*042d53a7SEvalZero 		BT_ERR("Unable to encode RPL as value");
967*042d53a7SEvalZero 		return;
968*042d53a7SEvalZero 	}
969*042d53a7SEvalZero 
970*042d53a7SEvalZero 	snprintk(path, sizeof(path), "bt_mesh/RPL/%x", entry->src);
971*042d53a7SEvalZero 
972*042d53a7SEvalZero 	BT_DBG("Saving RPL %s as value %s", path, str);
973*042d53a7SEvalZero 	settings_save_one(path, str);
974*042d53a7SEvalZero }
975*042d53a7SEvalZero 
clear_rpl(void)976*042d53a7SEvalZero static void clear_rpl(void)
977*042d53a7SEvalZero {
978*042d53a7SEvalZero 	int i;
979*042d53a7SEvalZero 
980*042d53a7SEvalZero 	BT_DBG("");
981*042d53a7SEvalZero 
982*042d53a7SEvalZero 	for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
983*042d53a7SEvalZero 		struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
984*042d53a7SEvalZero 		char path[18];
985*042d53a7SEvalZero 
986*042d53a7SEvalZero 		if (!rpl->src) {
987*042d53a7SEvalZero 			continue;
988*042d53a7SEvalZero 		}
989*042d53a7SEvalZero 
990*042d53a7SEvalZero 		snprintk(path, sizeof(path), "bt_mesh/RPL/%x", rpl->src);
991*042d53a7SEvalZero 		settings_save_one(path, NULL);
992*042d53a7SEvalZero 
993*042d53a7SEvalZero 		memset(rpl, 0, sizeof(*rpl));
994*042d53a7SEvalZero 	}
995*042d53a7SEvalZero }
996*042d53a7SEvalZero 
store_pending_rpl(void)997*042d53a7SEvalZero static void store_pending_rpl(void)
998*042d53a7SEvalZero {
999*042d53a7SEvalZero 	int i;
1000*042d53a7SEvalZero 
1001*042d53a7SEvalZero 	BT_DBG("");
1002*042d53a7SEvalZero 
1003*042d53a7SEvalZero 	for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
1004*042d53a7SEvalZero 		struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
1005*042d53a7SEvalZero 
1006*042d53a7SEvalZero 		if (rpl->store) {
1007*042d53a7SEvalZero 			rpl->store = false;
1008*042d53a7SEvalZero 			store_rpl(rpl);
1009*042d53a7SEvalZero 		}
1010*042d53a7SEvalZero 	}
1011*042d53a7SEvalZero }
1012*042d53a7SEvalZero 
store_pending_hb_pub(void)1013*042d53a7SEvalZero static void store_pending_hb_pub(void)
1014*042d53a7SEvalZero {
1015*042d53a7SEvalZero 	char buf[BT_SETTINGS_SIZE(sizeof(struct hb_pub_val))];
1016*042d53a7SEvalZero 	struct bt_mesh_hb_pub *pub = bt_mesh_hb_pub_get();
1017*042d53a7SEvalZero 	struct hb_pub_val val;
1018*042d53a7SEvalZero 	char *str;
1019*042d53a7SEvalZero 
1020*042d53a7SEvalZero 	if (!pub) {
1021*042d53a7SEvalZero 		return;
1022*042d53a7SEvalZero 	}
1023*042d53a7SEvalZero 
1024*042d53a7SEvalZero 	if (pub->dst == BT_MESH_ADDR_UNASSIGNED) {
1025*042d53a7SEvalZero 		str = NULL;
1026*042d53a7SEvalZero 	} else {
1027*042d53a7SEvalZero 		val.indefinite = (pub->count = 0xffff);
1028*042d53a7SEvalZero 		val.dst = pub->dst;
1029*042d53a7SEvalZero 		val.period = pub->period;
1030*042d53a7SEvalZero 		val.ttl = pub->ttl;
1031*042d53a7SEvalZero 		val.feat = pub->feat;
1032*042d53a7SEvalZero 		val.net_idx = pub->net_idx;
1033*042d53a7SEvalZero 
1034*042d53a7SEvalZero 		str = settings_str_from_bytes(&val, sizeof(val),
1035*042d53a7SEvalZero 					      buf, sizeof(buf));
1036*042d53a7SEvalZero 		if (!str) {
1037*042d53a7SEvalZero 			BT_ERR("Unable to encode hb pub as value");
1038*042d53a7SEvalZero 			return;
1039*042d53a7SEvalZero 		}
1040*042d53a7SEvalZero 	}
1041*042d53a7SEvalZero 
1042*042d53a7SEvalZero 	BT_DBG("Saving Heartbeat Publication as value %s",
1043*042d53a7SEvalZero 	       str ? str : "(null)");
1044*042d53a7SEvalZero 	settings_save_one("bt_mesh/HBPub", str);
1045*042d53a7SEvalZero }
1046*042d53a7SEvalZero 
store_pending_cfg(void)1047*042d53a7SEvalZero static void store_pending_cfg(void)
1048*042d53a7SEvalZero {
1049*042d53a7SEvalZero 	char buf[BT_SETTINGS_SIZE(sizeof(struct cfg_val))];
1050*042d53a7SEvalZero 	struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
1051*042d53a7SEvalZero 	struct cfg_val val;
1052*042d53a7SEvalZero 	char *str;
1053*042d53a7SEvalZero 
1054*042d53a7SEvalZero 	if (!cfg) {
1055*042d53a7SEvalZero 		return;
1056*042d53a7SEvalZero 	}
1057*042d53a7SEvalZero 
1058*042d53a7SEvalZero 	val.net_transmit = cfg->net_transmit;
1059*042d53a7SEvalZero 	val.relay = cfg->relay;
1060*042d53a7SEvalZero 	val.relay_retransmit = cfg->relay_retransmit;
1061*042d53a7SEvalZero 	val.beacon = cfg->beacon;
1062*042d53a7SEvalZero 	val.gatt_proxy = cfg->gatt_proxy;
1063*042d53a7SEvalZero 	val.frnd = cfg->frnd;
1064*042d53a7SEvalZero 	val.default_ttl = cfg->default_ttl;
1065*042d53a7SEvalZero 
1066*042d53a7SEvalZero 	str = settings_str_from_bytes(&val, sizeof(val), buf, sizeof(buf));
1067*042d53a7SEvalZero 	if (!str) {
1068*042d53a7SEvalZero 		BT_ERR("Unable to encode configuration as value");
1069*042d53a7SEvalZero 		return;
1070*042d53a7SEvalZero 	}
1071*042d53a7SEvalZero 
1072*042d53a7SEvalZero 	BT_DBG("Saving configuration as value %s", str);
1073*042d53a7SEvalZero 	settings_save_one("bt_mesh/Cfg", str);
1074*042d53a7SEvalZero }
1075*042d53a7SEvalZero 
clear_cfg(void)1076*042d53a7SEvalZero static void clear_cfg(void)
1077*042d53a7SEvalZero {
1078*042d53a7SEvalZero 	BT_DBG("Clearing configuration");
1079*042d53a7SEvalZero 	settings_save_one("bt_mesh/Cfg", NULL);
1080*042d53a7SEvalZero }
1081*042d53a7SEvalZero 
clear_app_key(u16_t app_idx)1082*042d53a7SEvalZero static void clear_app_key(u16_t app_idx)
1083*042d53a7SEvalZero {
1084*042d53a7SEvalZero 	char path[20];
1085*042d53a7SEvalZero 
1086*042d53a7SEvalZero 	BT_DBG("AppKeyIndex 0x%03x", app_idx);
1087*042d53a7SEvalZero 
1088*042d53a7SEvalZero 	snprintk(path, sizeof(path), "bt_mesh/AppKey/%x", app_idx);
1089*042d53a7SEvalZero 	settings_save_one(path, NULL);
1090*042d53a7SEvalZero }
1091*042d53a7SEvalZero 
clear_net_key(u16_t net_idx)1092*042d53a7SEvalZero static void clear_net_key(u16_t net_idx)
1093*042d53a7SEvalZero {
1094*042d53a7SEvalZero 	char path[20];
1095*042d53a7SEvalZero 
1096*042d53a7SEvalZero 	BT_DBG("NetKeyIndex 0x%03x", net_idx);
1097*042d53a7SEvalZero 
1098*042d53a7SEvalZero 	snprintk(path, sizeof(path), "bt_mesh/NetKey/%x", net_idx);
1099*042d53a7SEvalZero 	settings_save_one(path, NULL);
1100*042d53a7SEvalZero }
1101*042d53a7SEvalZero 
store_net_key(struct bt_mesh_subnet * sub)1102*042d53a7SEvalZero static void store_net_key(struct bt_mesh_subnet *sub)
1103*042d53a7SEvalZero {
1104*042d53a7SEvalZero 	char buf[BT_SETTINGS_SIZE(sizeof(struct net_key_val))];
1105*042d53a7SEvalZero 	struct net_key_val key;
1106*042d53a7SEvalZero 	char path[20];
1107*042d53a7SEvalZero 	char *str;
1108*042d53a7SEvalZero 
1109*042d53a7SEvalZero 	BT_DBG("NetKeyIndex 0x%03x NetKey %s", sub->net_idx,
1110*042d53a7SEvalZero 	       bt_hex(sub->keys[0].net, 16));
1111*042d53a7SEvalZero 
1112*042d53a7SEvalZero 	memcpy(&key.val[0], sub->keys[0].net, 16);
1113*042d53a7SEvalZero 	memcpy(&key.val[1], sub->keys[1].net, 16);
1114*042d53a7SEvalZero 	key.kr_flag = sub->kr_flag;
1115*042d53a7SEvalZero 	key.kr_phase = sub->kr_phase;
1116*042d53a7SEvalZero 
1117*042d53a7SEvalZero 	str = settings_str_from_bytes(&key, sizeof(key), buf, sizeof(buf));
1118*042d53a7SEvalZero 	if (!str) {
1119*042d53a7SEvalZero 		BT_ERR("Unable to encode NetKey as value");
1120*042d53a7SEvalZero 		return;
1121*042d53a7SEvalZero 	}
1122*042d53a7SEvalZero 
1123*042d53a7SEvalZero 	snprintk(path, sizeof(path), "bt_mesh/NetKey/%x", sub->net_idx);
1124*042d53a7SEvalZero 
1125*042d53a7SEvalZero 	BT_DBG("Saving NetKey %s as value %s", path, str);
1126*042d53a7SEvalZero 	settings_save_one(path, str);
1127*042d53a7SEvalZero }
1128*042d53a7SEvalZero 
store_app_key(struct bt_mesh_app_key * app)1129*042d53a7SEvalZero static void store_app_key(struct bt_mesh_app_key *app)
1130*042d53a7SEvalZero {
1131*042d53a7SEvalZero 	char buf[BT_SETTINGS_SIZE(sizeof(struct app_key_val))];
1132*042d53a7SEvalZero 	struct app_key_val key;
1133*042d53a7SEvalZero 	char path[20];
1134*042d53a7SEvalZero 	char *str;
1135*042d53a7SEvalZero 
1136*042d53a7SEvalZero 	key.net_idx = app->net_idx;
1137*042d53a7SEvalZero 	key.updated = app->updated;
1138*042d53a7SEvalZero 	memcpy(key.val[0], app->keys[0].val, 16);
1139*042d53a7SEvalZero 	memcpy(key.val[1], app->keys[1].val, 16);
1140*042d53a7SEvalZero 
1141*042d53a7SEvalZero 	str = settings_str_from_bytes(&key, sizeof(key), buf, sizeof(buf));
1142*042d53a7SEvalZero 	if (!str) {
1143*042d53a7SEvalZero 		BT_ERR("Unable to encode AppKey as value");
1144*042d53a7SEvalZero 		return;
1145*042d53a7SEvalZero 	}
1146*042d53a7SEvalZero 
1147*042d53a7SEvalZero 	snprintk(path, sizeof(path), "bt_mesh/AppKey/%x", app->app_idx);
1148*042d53a7SEvalZero 
1149*042d53a7SEvalZero 	BT_DBG("Saving AppKey %s as value %s", path, str);
1150*042d53a7SEvalZero 	settings_save_one(path, str);
1151*042d53a7SEvalZero }
1152*042d53a7SEvalZero 
store_pending_keys(void)1153*042d53a7SEvalZero static void store_pending_keys(void)
1154*042d53a7SEvalZero {
1155*042d53a7SEvalZero 	int i;
1156*042d53a7SEvalZero 
1157*042d53a7SEvalZero 	for (i = 0; i < ARRAY_SIZE(key_updates); i++) {
1158*042d53a7SEvalZero 		struct key_update *update = &key_updates[i];
1159*042d53a7SEvalZero 
1160*042d53a7SEvalZero 		if (!update->valid) {
1161*042d53a7SEvalZero 			continue;
1162*042d53a7SEvalZero 		}
1163*042d53a7SEvalZero 
1164*042d53a7SEvalZero 		if (update->clear) {
1165*042d53a7SEvalZero 			if (update->app_key) {
1166*042d53a7SEvalZero 				clear_app_key(update->key_idx);
1167*042d53a7SEvalZero 			} else {
1168*042d53a7SEvalZero 				clear_net_key(update->key_idx);
1169*042d53a7SEvalZero 			}
1170*042d53a7SEvalZero 		} else {
1171*042d53a7SEvalZero 			if (update->app_key) {
1172*042d53a7SEvalZero 				struct bt_mesh_app_key *key;
1173*042d53a7SEvalZero 
1174*042d53a7SEvalZero 				key = bt_mesh_app_key_find(update->key_idx);
1175*042d53a7SEvalZero 				if (key) {
1176*042d53a7SEvalZero 					store_app_key(key);
1177*042d53a7SEvalZero 				} else {
1178*042d53a7SEvalZero 					BT_WARN("AppKeyIndex 0x%03x not found",
1179*042d53a7SEvalZero 					       update->key_idx);
1180*042d53a7SEvalZero 				}
1181*042d53a7SEvalZero 
1182*042d53a7SEvalZero 			} else {
1183*042d53a7SEvalZero 				struct bt_mesh_subnet *sub;
1184*042d53a7SEvalZero 
1185*042d53a7SEvalZero 				sub = bt_mesh_subnet_get(update->key_idx);
1186*042d53a7SEvalZero 				if (sub) {
1187*042d53a7SEvalZero 					store_net_key(sub);
1188*042d53a7SEvalZero 				} else {
1189*042d53a7SEvalZero 					BT_WARN("NetKeyIndex 0x%03x not found",
1190*042d53a7SEvalZero 					       update->key_idx);
1191*042d53a7SEvalZero 				}
1192*042d53a7SEvalZero 			}
1193*042d53a7SEvalZero 		}
1194*042d53a7SEvalZero 
1195*042d53a7SEvalZero 		update->valid = 0;
1196*042d53a7SEvalZero 	}
1197*042d53a7SEvalZero }
1198*042d53a7SEvalZero 
encode_mod_path(struct bt_mesh_model * mod,bool vnd,const char * key,char * path,size_t path_len)1199*042d53a7SEvalZero static void encode_mod_path(struct bt_mesh_model *mod, bool vnd,
1200*042d53a7SEvalZero 			    const char *key, char *path, size_t path_len)
1201*042d53a7SEvalZero {
1202*042d53a7SEvalZero 	u16_t mod_key = (((u16_t)mod->elem_idx << 8) | mod->mod_idx);
1203*042d53a7SEvalZero 
1204*042d53a7SEvalZero 	if (vnd) {
1205*042d53a7SEvalZero 		snprintk(path, path_len, "bt_mesh/v/%x/%s", mod_key, key);
1206*042d53a7SEvalZero 	} else {
1207*042d53a7SEvalZero 		snprintk(path, path_len, "bt_mesh/s/%x/%s", mod_key, key);
1208*042d53a7SEvalZero 	}
1209*042d53a7SEvalZero }
1210*042d53a7SEvalZero 
store_pending_mod_bind(struct bt_mesh_model * mod,bool vnd)1211*042d53a7SEvalZero static void store_pending_mod_bind(struct bt_mesh_model *mod, bool vnd)
1212*042d53a7SEvalZero {
1213*042d53a7SEvalZero 	u16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT];
1214*042d53a7SEvalZero 	char buf[BT_SETTINGS_SIZE(sizeof(keys))];
1215*042d53a7SEvalZero 	char path[20];
1216*042d53a7SEvalZero 	int i, count;
1217*042d53a7SEvalZero 	char *val;
1218*042d53a7SEvalZero 
1219*042d53a7SEvalZero 	for (i = 0, count = 0; i < ARRAY_SIZE(mod->keys); i++) {
1220*042d53a7SEvalZero 		if (mod->keys[i] != BT_MESH_KEY_UNUSED) {
1221*042d53a7SEvalZero 			keys[count++] = mod->keys[i];
1222*042d53a7SEvalZero 		}
1223*042d53a7SEvalZero 	}
1224*042d53a7SEvalZero 
1225*042d53a7SEvalZero 	if (count) {
1226*042d53a7SEvalZero 		val = settings_str_from_bytes(keys, count * sizeof(keys[0]),
1227*042d53a7SEvalZero 					      buf, sizeof(buf));
1228*042d53a7SEvalZero 		if (!val) {
1229*042d53a7SEvalZero 			BT_ERR("Unable to encode model bindings as value");
1230*042d53a7SEvalZero 			return;
1231*042d53a7SEvalZero 		}
1232*042d53a7SEvalZero 	} else {
1233*042d53a7SEvalZero 		val = NULL;
1234*042d53a7SEvalZero 	}
1235*042d53a7SEvalZero 
1236*042d53a7SEvalZero 	encode_mod_path(mod, vnd, "bind", path, sizeof(path));
1237*042d53a7SEvalZero 
1238*042d53a7SEvalZero 	BT_DBG("Saving %s as %s", path, val ? val : "(null)");
1239*042d53a7SEvalZero 	settings_save_one(path, val);
1240*042d53a7SEvalZero }
1241*042d53a7SEvalZero 
store_pending_mod_sub(struct bt_mesh_model * mod,bool vnd)1242*042d53a7SEvalZero static void store_pending_mod_sub(struct bt_mesh_model *mod, bool vnd)
1243*042d53a7SEvalZero {
1244*042d53a7SEvalZero 	u16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT];
1245*042d53a7SEvalZero 	char buf[BT_SETTINGS_SIZE(sizeof(groups))];
1246*042d53a7SEvalZero 	char path[20];
1247*042d53a7SEvalZero 	int i, count;
1248*042d53a7SEvalZero 	char *val;
1249*042d53a7SEvalZero 
1250*042d53a7SEvalZero 	for (i = 0, count = 0; i < ARRAY_SIZE(mod->groups); i++) {
1251*042d53a7SEvalZero 		if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) {
1252*042d53a7SEvalZero 			groups[count++] = mod->groups[i];
1253*042d53a7SEvalZero 		}
1254*042d53a7SEvalZero 	}
1255*042d53a7SEvalZero 
1256*042d53a7SEvalZero 	if (count) {
1257*042d53a7SEvalZero 		val = settings_str_from_bytes(groups, count * sizeof(groups[0]),
1258*042d53a7SEvalZero 					      buf, sizeof(buf));
1259*042d53a7SEvalZero 		if (!val) {
1260*042d53a7SEvalZero 			BT_ERR("Unable to encode model subscription as value");
1261*042d53a7SEvalZero 			return;
1262*042d53a7SEvalZero 		}
1263*042d53a7SEvalZero 	} else {
1264*042d53a7SEvalZero 		val = NULL;
1265*042d53a7SEvalZero 	}
1266*042d53a7SEvalZero 
1267*042d53a7SEvalZero 	encode_mod_path(mod, vnd, "sub", path, sizeof(path));
1268*042d53a7SEvalZero 
1269*042d53a7SEvalZero 	BT_DBG("Saving %s as %s", path, val ? val : "(null)");
1270*042d53a7SEvalZero 	settings_save_one(path, val);
1271*042d53a7SEvalZero }
1272*042d53a7SEvalZero 
store_pending_mod_pub(struct bt_mesh_model * mod,bool vnd)1273*042d53a7SEvalZero static void store_pending_mod_pub(struct bt_mesh_model *mod, bool vnd)
1274*042d53a7SEvalZero {
1275*042d53a7SEvalZero 	char buf[BT_SETTINGS_SIZE(sizeof(struct mod_pub_val))];
1276*042d53a7SEvalZero 	struct mod_pub_val pub;
1277*042d53a7SEvalZero 	char path[20];
1278*042d53a7SEvalZero 	char *val;
1279*042d53a7SEvalZero 
1280*042d53a7SEvalZero 	if (!mod->pub || mod->pub->addr == BT_MESH_ADDR_UNASSIGNED) {
1281*042d53a7SEvalZero 		val = NULL;
1282*042d53a7SEvalZero 	} else {
1283*042d53a7SEvalZero 		pub.addr = mod->pub->addr;
1284*042d53a7SEvalZero 		pub.key = mod->pub->key;
1285*042d53a7SEvalZero 		pub.ttl = mod->pub->ttl;
1286*042d53a7SEvalZero 		pub.retransmit = mod->pub->retransmit;
1287*042d53a7SEvalZero 		pub.period = mod->pub->period;
1288*042d53a7SEvalZero 		pub.period_div = mod->pub->period_div;
1289*042d53a7SEvalZero 		pub.cred = mod->pub->cred;
1290*042d53a7SEvalZero 
1291*042d53a7SEvalZero 		val = settings_str_from_bytes(&pub, sizeof(pub),
1292*042d53a7SEvalZero 					      buf, sizeof(buf));
1293*042d53a7SEvalZero 		if (!val) {
1294*042d53a7SEvalZero 			BT_ERR("Unable to encode model publication as value");
1295*042d53a7SEvalZero 			return;
1296*042d53a7SEvalZero 		}
1297*042d53a7SEvalZero 	}
1298*042d53a7SEvalZero 
1299*042d53a7SEvalZero 	encode_mod_path(mod, vnd, "pub", path, sizeof(path));
1300*042d53a7SEvalZero 
1301*042d53a7SEvalZero 	BT_DBG("Saving %s as %s", path, val ? val : "(null)");
1302*042d53a7SEvalZero 	settings_save_one(path, val);
1303*042d53a7SEvalZero }
1304*042d53a7SEvalZero 
store_pending_mod(struct bt_mesh_model * mod,struct bt_mesh_elem * elem,bool vnd,bool primary,void * user_data)1305*042d53a7SEvalZero static void store_pending_mod(struct bt_mesh_model *mod,
1306*042d53a7SEvalZero 			      struct bt_mesh_elem *elem, bool vnd,
1307*042d53a7SEvalZero 			      bool primary, void *user_data)
1308*042d53a7SEvalZero {
1309*042d53a7SEvalZero 	if (!mod->flags) {
1310*042d53a7SEvalZero 		return;
1311*042d53a7SEvalZero 	}
1312*042d53a7SEvalZero 
1313*042d53a7SEvalZero 	if (mod->flags & BT_MESH_MOD_BIND_PENDING) {
1314*042d53a7SEvalZero 		mod->flags &= ~BT_MESH_MOD_BIND_PENDING;
1315*042d53a7SEvalZero 		store_pending_mod_bind(mod, vnd);
1316*042d53a7SEvalZero 	}
1317*042d53a7SEvalZero 
1318*042d53a7SEvalZero 	if (mod->flags & BT_MESH_MOD_SUB_PENDING) {
1319*042d53a7SEvalZero 		mod->flags &= ~BT_MESH_MOD_SUB_PENDING;
1320*042d53a7SEvalZero 		store_pending_mod_sub(mod, vnd);
1321*042d53a7SEvalZero 	}
1322*042d53a7SEvalZero 
1323*042d53a7SEvalZero 	if (mod->flags & BT_MESH_MOD_PUB_PENDING) {
1324*042d53a7SEvalZero 		mod->flags &= ~BT_MESH_MOD_PUB_PENDING;
1325*042d53a7SEvalZero 		store_pending_mod_pub(mod, vnd);
1326*042d53a7SEvalZero 	}
1327*042d53a7SEvalZero }
1328*042d53a7SEvalZero 
store_pending(struct ble_npl_event * work)1329*042d53a7SEvalZero static void store_pending(struct ble_npl_event *work)
1330*042d53a7SEvalZero {
1331*042d53a7SEvalZero 	BT_DBG("");
1332*042d53a7SEvalZero 
1333*042d53a7SEvalZero 	if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_RPL_PENDING)) {
1334*042d53a7SEvalZero 		if (bt_mesh.valid) {
1335*042d53a7SEvalZero 			store_pending_rpl();
1336*042d53a7SEvalZero 		} else {
1337*042d53a7SEvalZero 			clear_rpl();
1338*042d53a7SEvalZero 		}
1339*042d53a7SEvalZero 	}
1340*042d53a7SEvalZero 
1341*042d53a7SEvalZero 	if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_KEYS_PENDING)) {
1342*042d53a7SEvalZero 		store_pending_keys();
1343*042d53a7SEvalZero 	}
1344*042d53a7SEvalZero 
1345*042d53a7SEvalZero 	if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_NET_PENDING)) {
1346*042d53a7SEvalZero 		if (bt_mesh.valid) {
1347*042d53a7SEvalZero 			store_pending_net();
1348*042d53a7SEvalZero 		} else {
1349*042d53a7SEvalZero 			clear_net();
1350*042d53a7SEvalZero 		}
1351*042d53a7SEvalZero 	}
1352*042d53a7SEvalZero 
1353*042d53a7SEvalZero 	if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_IV_PENDING)) {
1354*042d53a7SEvalZero 		if (bt_mesh.valid) {
1355*042d53a7SEvalZero 			store_pending_iv();
1356*042d53a7SEvalZero 		} else {
1357*042d53a7SEvalZero 			clear_iv();
1358*042d53a7SEvalZero 		}
1359*042d53a7SEvalZero 	}
1360*042d53a7SEvalZero 
1361*042d53a7SEvalZero 	if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_SEQ_PENDING)) {
1362*042d53a7SEvalZero 		store_pending_seq();
1363*042d53a7SEvalZero 	}
1364*042d53a7SEvalZero 
1365*042d53a7SEvalZero 	if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_HB_PUB_PENDING)) {
1366*042d53a7SEvalZero 		store_pending_hb_pub();
1367*042d53a7SEvalZero 	}
1368*042d53a7SEvalZero 
1369*042d53a7SEvalZero 	if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_CFG_PENDING)) {
1370*042d53a7SEvalZero 		if (bt_mesh.valid) {
1371*042d53a7SEvalZero 			store_pending_cfg();
1372*042d53a7SEvalZero 		} else {
1373*042d53a7SEvalZero 			clear_cfg();
1374*042d53a7SEvalZero 		}
1375*042d53a7SEvalZero 	}
1376*042d53a7SEvalZero 
1377*042d53a7SEvalZero 	if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_MOD_PENDING)) {
1378*042d53a7SEvalZero 		bt_mesh_model_foreach(store_pending_mod, NULL);
1379*042d53a7SEvalZero 	}
1380*042d53a7SEvalZero }
1381*042d53a7SEvalZero 
bt_mesh_store_rpl(struct bt_mesh_rpl * entry)1382*042d53a7SEvalZero void bt_mesh_store_rpl(struct bt_mesh_rpl *entry)
1383*042d53a7SEvalZero {
1384*042d53a7SEvalZero 	entry->store = true;
1385*042d53a7SEvalZero 	schedule_store(BT_MESH_RPL_PENDING);
1386*042d53a7SEvalZero }
1387*042d53a7SEvalZero 
key_update_find(bool app_key,u16_t key_idx,struct key_update ** free_slot)1388*042d53a7SEvalZero static struct key_update *key_update_find(bool app_key, u16_t key_idx,
1389*042d53a7SEvalZero 					  struct key_update **free_slot)
1390*042d53a7SEvalZero {
1391*042d53a7SEvalZero 	struct key_update *match;
1392*042d53a7SEvalZero 	int i;
1393*042d53a7SEvalZero 
1394*042d53a7SEvalZero 	match = NULL;
1395*042d53a7SEvalZero 	*free_slot = NULL;
1396*042d53a7SEvalZero 
1397*042d53a7SEvalZero 	for (i = 0; i < ARRAY_SIZE(key_updates); i++) {
1398*042d53a7SEvalZero 		struct key_update *update = &key_updates[i];
1399*042d53a7SEvalZero 
1400*042d53a7SEvalZero 		if (!update->valid) {
1401*042d53a7SEvalZero 			*free_slot = update;
1402*042d53a7SEvalZero 			continue;
1403*042d53a7SEvalZero 		}
1404*042d53a7SEvalZero 
1405*042d53a7SEvalZero 		if (update->app_key != app_key) {
1406*042d53a7SEvalZero 			continue;
1407*042d53a7SEvalZero 		}
1408*042d53a7SEvalZero 
1409*042d53a7SEvalZero 		if (update->key_idx == key_idx) {
1410*042d53a7SEvalZero 			match = update;
1411*042d53a7SEvalZero 		}
1412*042d53a7SEvalZero 	}
1413*042d53a7SEvalZero 
1414*042d53a7SEvalZero 	return match;
1415*042d53a7SEvalZero }
1416*042d53a7SEvalZero 
bt_mesh_store_subnet(struct bt_mesh_subnet * sub)1417*042d53a7SEvalZero void bt_mesh_store_subnet(struct bt_mesh_subnet *sub)
1418*042d53a7SEvalZero {
1419*042d53a7SEvalZero 	struct key_update *update, *free_slot;
1420*042d53a7SEvalZero 
1421*042d53a7SEvalZero 	BT_DBG("NetKeyIndex 0x%03x", sub->net_idx);
1422*042d53a7SEvalZero 
1423*042d53a7SEvalZero 	update = key_update_find(false, sub->net_idx, &free_slot);
1424*042d53a7SEvalZero 	if (update) {
1425*042d53a7SEvalZero 		update->clear = 0;
1426*042d53a7SEvalZero 		schedule_store(BT_MESH_KEYS_PENDING);
1427*042d53a7SEvalZero 		return;
1428*042d53a7SEvalZero 	}
1429*042d53a7SEvalZero 
1430*042d53a7SEvalZero 	if (!free_slot) {
1431*042d53a7SEvalZero 		store_net_key(sub);
1432*042d53a7SEvalZero 		return;
1433*042d53a7SEvalZero 	}
1434*042d53a7SEvalZero 
1435*042d53a7SEvalZero 	free_slot->valid = 1;
1436*042d53a7SEvalZero 	free_slot->key_idx = sub->net_idx;
1437*042d53a7SEvalZero 	free_slot->app_key = 0;
1438*042d53a7SEvalZero 	free_slot->clear = 0;
1439*042d53a7SEvalZero 
1440*042d53a7SEvalZero 	schedule_store(BT_MESH_KEYS_PENDING);
1441*042d53a7SEvalZero }
1442*042d53a7SEvalZero 
bt_mesh_store_app_key(struct bt_mesh_app_key * key)1443*042d53a7SEvalZero void bt_mesh_store_app_key(struct bt_mesh_app_key *key)
1444*042d53a7SEvalZero {
1445*042d53a7SEvalZero 	struct key_update *update, *free_slot;
1446*042d53a7SEvalZero 
1447*042d53a7SEvalZero 	BT_DBG("AppKeyIndex 0x%03x", key->app_idx);
1448*042d53a7SEvalZero 
1449*042d53a7SEvalZero 	update = key_update_find(true, key->app_idx, &free_slot);
1450*042d53a7SEvalZero 	if (update) {
1451*042d53a7SEvalZero 		update->clear = 0;
1452*042d53a7SEvalZero 		schedule_store(BT_MESH_KEYS_PENDING);
1453*042d53a7SEvalZero 		return;
1454*042d53a7SEvalZero 	}
1455*042d53a7SEvalZero 
1456*042d53a7SEvalZero 	if (!free_slot) {
1457*042d53a7SEvalZero 		store_app_key(key);
1458*042d53a7SEvalZero 		return;
1459*042d53a7SEvalZero 	}
1460*042d53a7SEvalZero 
1461*042d53a7SEvalZero 	free_slot->valid = 1;
1462*042d53a7SEvalZero 	free_slot->key_idx = key->app_idx;
1463*042d53a7SEvalZero 	free_slot->app_key = 1;
1464*042d53a7SEvalZero 	free_slot->clear = 0;
1465*042d53a7SEvalZero 
1466*042d53a7SEvalZero 	schedule_store(BT_MESH_KEYS_PENDING);
1467*042d53a7SEvalZero }
1468*042d53a7SEvalZero 
bt_mesh_store_hb_pub(void)1469*042d53a7SEvalZero void bt_mesh_store_hb_pub(void)
1470*042d53a7SEvalZero {
1471*042d53a7SEvalZero 	schedule_store(BT_MESH_HB_PUB_PENDING);
1472*042d53a7SEvalZero }
1473*042d53a7SEvalZero 
bt_mesh_store_cfg(void)1474*042d53a7SEvalZero void bt_mesh_store_cfg(void)
1475*042d53a7SEvalZero {
1476*042d53a7SEvalZero 	schedule_store(BT_MESH_CFG_PENDING);
1477*042d53a7SEvalZero }
1478*042d53a7SEvalZero 
bt_mesh_clear_net(void)1479*042d53a7SEvalZero void bt_mesh_clear_net(void)
1480*042d53a7SEvalZero {
1481*042d53a7SEvalZero 	schedule_store(BT_MESH_NET_PENDING);
1482*042d53a7SEvalZero 	schedule_store(BT_MESH_IV_PENDING);
1483*042d53a7SEvalZero 	schedule_store(BT_MESH_CFG_PENDING);
1484*042d53a7SEvalZero }
1485*042d53a7SEvalZero 
bt_mesh_clear_subnet(struct bt_mesh_subnet * sub)1486*042d53a7SEvalZero void bt_mesh_clear_subnet(struct bt_mesh_subnet *sub)
1487*042d53a7SEvalZero {
1488*042d53a7SEvalZero 	struct key_update *update, *free_slot;
1489*042d53a7SEvalZero 
1490*042d53a7SEvalZero 	BT_DBG("NetKeyIndex 0x%03x", sub->net_idx);
1491*042d53a7SEvalZero 
1492*042d53a7SEvalZero 	update = key_update_find(false, sub->net_idx, &free_slot);
1493*042d53a7SEvalZero 	if (update) {
1494*042d53a7SEvalZero 		update->clear = 1;
1495*042d53a7SEvalZero 		schedule_store(BT_MESH_KEYS_PENDING);
1496*042d53a7SEvalZero 		return;
1497*042d53a7SEvalZero 	}
1498*042d53a7SEvalZero 
1499*042d53a7SEvalZero 	if (!free_slot) {
1500*042d53a7SEvalZero 		clear_net_key(sub->net_idx);
1501*042d53a7SEvalZero 		return;
1502*042d53a7SEvalZero 	}
1503*042d53a7SEvalZero 
1504*042d53a7SEvalZero 	free_slot->valid = 1;
1505*042d53a7SEvalZero 	free_slot->key_idx = sub->net_idx;
1506*042d53a7SEvalZero 	free_slot->app_key = 0;
1507*042d53a7SEvalZero 	free_slot->clear = 1;
1508*042d53a7SEvalZero 
1509*042d53a7SEvalZero 	schedule_store(BT_MESH_KEYS_PENDING);
1510*042d53a7SEvalZero }
1511*042d53a7SEvalZero 
bt_mesh_clear_app_key(struct bt_mesh_app_key * key)1512*042d53a7SEvalZero void bt_mesh_clear_app_key(struct bt_mesh_app_key *key)
1513*042d53a7SEvalZero {
1514*042d53a7SEvalZero 	struct key_update *update, *free_slot;
1515*042d53a7SEvalZero 
1516*042d53a7SEvalZero 	BT_DBG("AppKeyIndex 0x%03x", key->app_idx);
1517*042d53a7SEvalZero 
1518*042d53a7SEvalZero 	update = key_update_find(true, key->app_idx, &free_slot);
1519*042d53a7SEvalZero 	if (update) {
1520*042d53a7SEvalZero 		update->clear = 1;
1521*042d53a7SEvalZero 		schedule_store(BT_MESH_KEYS_PENDING);
1522*042d53a7SEvalZero 		return;
1523*042d53a7SEvalZero 	}
1524*042d53a7SEvalZero 
1525*042d53a7SEvalZero 	if (!free_slot) {
1526*042d53a7SEvalZero 		clear_app_key(key->app_idx);
1527*042d53a7SEvalZero 		return;
1528*042d53a7SEvalZero 	}
1529*042d53a7SEvalZero 
1530*042d53a7SEvalZero 	free_slot->valid = 1;
1531*042d53a7SEvalZero 	free_slot->key_idx = key->app_idx;
1532*042d53a7SEvalZero 	free_slot->app_key = 1;
1533*042d53a7SEvalZero 	free_slot->clear = 1;
1534*042d53a7SEvalZero 
1535*042d53a7SEvalZero 	schedule_store(BT_MESH_KEYS_PENDING);
1536*042d53a7SEvalZero }
1537*042d53a7SEvalZero 
bt_mesh_clear_rpl(void)1538*042d53a7SEvalZero void bt_mesh_clear_rpl(void)
1539*042d53a7SEvalZero {
1540*042d53a7SEvalZero 	schedule_store(BT_MESH_RPL_PENDING);
1541*042d53a7SEvalZero }
1542*042d53a7SEvalZero 
bt_mesh_store_mod_bind(struct bt_mesh_model * mod)1543*042d53a7SEvalZero void bt_mesh_store_mod_bind(struct bt_mesh_model *mod)
1544*042d53a7SEvalZero {
1545*042d53a7SEvalZero 	mod->flags |= BT_MESH_MOD_BIND_PENDING;
1546*042d53a7SEvalZero 	schedule_store(BT_MESH_MOD_PENDING);
1547*042d53a7SEvalZero }
1548*042d53a7SEvalZero 
bt_mesh_store_mod_sub(struct bt_mesh_model * mod)1549*042d53a7SEvalZero void bt_mesh_store_mod_sub(struct bt_mesh_model *mod)
1550*042d53a7SEvalZero {
1551*042d53a7SEvalZero 	mod->flags |= BT_MESH_MOD_SUB_PENDING;
1552*042d53a7SEvalZero 	schedule_store(BT_MESH_MOD_PENDING);
1553*042d53a7SEvalZero }
1554*042d53a7SEvalZero 
bt_mesh_store_mod_pub(struct bt_mesh_model * mod)1555*042d53a7SEvalZero void bt_mesh_store_mod_pub(struct bt_mesh_model *mod)
1556*042d53a7SEvalZero {
1557*042d53a7SEvalZero 	mod->flags |= BT_MESH_MOD_PUB_PENDING;
1558*042d53a7SEvalZero 	schedule_store(BT_MESH_MOD_PENDING);
1559*042d53a7SEvalZero }
1560*042d53a7SEvalZero 
1561*042d53a7SEvalZero static struct conf_handler bt_mesh_settings_conf_handler = {
1562*042d53a7SEvalZero 	.ch_name = "bt_mesh",
1563*042d53a7SEvalZero 	.ch_get = NULL,
1564*042d53a7SEvalZero 	.ch_set = mesh_set,
1565*042d53a7SEvalZero 	.ch_commit = mesh_commit,
1566*042d53a7SEvalZero 	.ch_export = NULL,
1567*042d53a7SEvalZero };
1568*042d53a7SEvalZero 
bt_mesh_settings_init(void)1569*042d53a7SEvalZero void bt_mesh_settings_init(void)
1570*042d53a7SEvalZero {
1571*042d53a7SEvalZero 	int rc;
1572*042d53a7SEvalZero 
1573*042d53a7SEvalZero 	rc = conf_register(&bt_mesh_settings_conf_handler);
1574*042d53a7SEvalZero 
1575*042d53a7SEvalZero 	SYSINIT_PANIC_ASSERT_MSG(rc == 0,
1576*042d53a7SEvalZero 				 "Failed to register bt_mesh_settings conf");
1577*042d53a7SEvalZero 
1578*042d53a7SEvalZero 	k_delayed_work_init(&pending_store, store_pending);
1579*042d53a7SEvalZero }
1580*042d53a7SEvalZero 
1581*042d53a7SEvalZero #endif /* MYNEWT_VAL(BLE_MESH_SETTINGS) */
1582