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