1 /*
2 * Copyright (c) 2020 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <string.h>
8 #include <zephyr/bluetooth/mesh.h>
9 #include <common/bt_str.h>
10 #include "dfu_slot.h"
11 #include "dfd.h"
12 #include "dfu.h"
13 #include "dfd_srv_internal.h"
14 #include "net.h"
15 #include "transport.h"
16
17 #define LOG_LEVEL CONFIG_BT_MESH_DFU_LOG_LEVEL
18 #include <zephyr/logging/log.h>
19 LOG_MODULE_REGISTER(bt_mesh_dfd_srv);
20
21 #define ERASE_BLOCK_SIZE DT_PROP(DT_CHOSEN(zephyr_flash), erase_block_size)
22
23 #define DFD_UPLOAD_STATUS_MSG_MAXLEN (5 + CONFIG_BT_MESH_DFU_FWID_MAXLEN)
24
25 BUILD_ASSERT((DFD_UPLOAD_STATUS_MSG_MAXLEN + BT_MESH_MODEL_OP_LEN(BT_MESH_DFD_OP_UPLOAD_STATUS) +
26 BT_MESH_MIC_SHORT) <= BT_MESH_TX_SDU_MAX,
27 "The Firmware Distribution Upload Status message does not fit into the maximum "
28 "outgoing SDU size.");
29
30 #define DFD_UPLOAD_START_MSG_MAXLEN (16 + CONFIG_BT_MESH_DFU_FWID_MAXLEN + \
31 CONFIG_BT_MESH_DFU_METADATA_MAXLEN)
32
33 BUILD_ASSERT((DFD_UPLOAD_START_MSG_MAXLEN + BT_MESH_MODEL_OP_LEN(BT_MESH_DFD_OP_UPLOAD_START) +
34 BT_MESH_MIC_SHORT) <= BT_MESH_RX_SDU_MAX,
35 "The Firmware Distribution Upload Start message does not fit into the maximum "
36 "incoming SDU size.");
37
38 #define DFD_RECEIVERS_LIST_MSG_MAXLEN (4 + CONFIG_BT_MESH_DFD_SRV_TARGETS_MAX * 5)
39
40 BUILD_ASSERT((DFD_RECEIVERS_LIST_MSG_MAXLEN + BT_MESH_MODEL_OP_LEN(BT_MESH_DFD_OP_RECEIVERS_LIST) +
41 BT_MESH_MIC_SHORT) <= BT_MESH_TX_SDU_MAX,
42 "The Firmware Distribution Receivers List message does not fit into the maximum "
43 "outgoing SDU size.");
44
45 #define DFD_RECEIVERS_ADD_MSG_MAXLEN (CONFIG_BT_MESH_DFD_SRV_TARGETS_MAX * 3)
46
47 BUILD_ASSERT((DFD_RECEIVERS_ADD_MSG_MAXLEN + BT_MESH_MODEL_OP_LEN(BT_MESH_DFD_OP_RECEIVERS_ADD) +
48 BT_MESH_MIC_SHORT) <= BT_MESH_RX_SDU_MAX,
49 "The Firmware Distribution Receivers Add message does not fit into the maximum "
50 "incoming SDU size.");
51
52 struct slot_search_ctx {
53 off_t offset;
54 size_t size;
55 bool failed;
56 };
57
dfd_phase_set(struct bt_mesh_dfd_srv * srv,enum bt_mesh_dfd_phase new_phase)58 static void dfd_phase_set(struct bt_mesh_dfd_srv *srv,
59 enum bt_mesh_dfd_phase new_phase)
60 {
61 srv->phase = new_phase;
62
63 if (srv->cb && srv->cb->phase) {
64 srv->cb->phase(srv, srv->phase);
65 }
66 }
67
target_get(struct bt_mesh_dfd_srv * srv,uint16_t addr)68 static struct bt_mesh_dfu_target *target_get(struct bt_mesh_dfd_srv *srv,
69 uint16_t addr)
70 {
71 for (int i = 0; i < srv->target_cnt; ++i) {
72 if (addr == srv->targets[i].blob.addr) {
73 return &srv->targets[i];
74 }
75 }
76
77 return NULL;
78 }
79
is_busy(const struct bt_mesh_dfd_srv * srv)80 static bool is_busy(const struct bt_mesh_dfd_srv *srv)
81 {
82 return srv->phase == BT_MESH_DFD_PHASE_TRANSFER_ACTIVE ||
83 srv->phase == BT_MESH_DFD_PHASE_TRANSFER_SUCCESS ||
84 srv->phase == BT_MESH_DFD_PHASE_APPLYING_UPDATE;
85 }
86
upload_is_busy(const struct bt_mesh_dfd_srv * srv)87 static bool upload_is_busy(const struct bt_mesh_dfd_srv *srv)
88 {
89 return bt_mesh_blob_srv_is_busy(&srv->upload.blob) ||
90 srv->upload.phase == BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE;
91 }
92
slot_del(struct bt_mesh_dfd_srv * srv,const struct bt_mesh_dfu_slot * slot)93 static int slot_del(struct bt_mesh_dfd_srv *srv, const struct bt_mesh_dfu_slot *slot)
94 {
95 if (srv->cb && srv->cb->del) {
96 srv->cb->del(srv, slot);
97 }
98
99 return bt_mesh_dfu_slot_del(slot);
100 }
101
receivers_status_rsp(struct bt_mesh_dfd_srv * srv,struct bt_mesh_msg_ctx * ctx,enum bt_mesh_dfd_status status)102 static void receivers_status_rsp(struct bt_mesh_dfd_srv *srv,
103 struct bt_mesh_msg_ctx *ctx,
104 enum bt_mesh_dfd_status status)
105 {
106 BT_MESH_MODEL_BUF_DEFINE(buf, BT_MESH_DFD_OP_RECEIVERS_STATUS, 3);
107 bt_mesh_model_msg_init(&buf, BT_MESH_DFD_OP_RECEIVERS_STATUS);
108
109 net_buf_simple_add_u8(&buf, status);
110 net_buf_simple_add_le16(&buf, srv->target_cnt);
111
112 bt_mesh_model_send(srv->mod, ctx, &buf, NULL, NULL);
113 }
114
handle_receivers_add(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)115 static int handle_receivers_add(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
116 struct net_buf_simple *buf)
117 {
118 enum bt_mesh_dfd_status status = BT_MESH_DFD_SUCCESS;
119 struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
120
121 if (buf->len % 3) {
122 return -EINVAL;
123 }
124
125 if (bt_mesh_dfu_cli_is_busy(&srv->dfu)) {
126 receivers_status_rsp(srv, ctx,
127 BT_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION);
128 return 0;
129 }
130
131 while (buf->len >= 3 && status == BT_MESH_DFD_SUCCESS) {
132 uint8_t img_idx;
133 uint16_t addr;
134
135 addr = net_buf_simple_pull_le16(buf);
136 img_idx = net_buf_simple_pull_u8(buf);
137
138 status = bt_mesh_dfd_srv_receiver_add(srv, addr, img_idx);
139 }
140
141 receivers_status_rsp(srv, ctx, status);
142
143 return 0;
144 }
145
handle_receivers_delete_all(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)146 static int handle_receivers_delete_all(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
147 struct net_buf_simple *buf)
148 {
149 struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
150
151 receivers_status_rsp(srv, ctx, bt_mesh_dfd_srv_receivers_delete_all(srv));
152
153 return 0;
154 }
155
handle_receivers_get(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)156 static int handle_receivers_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
157 struct net_buf_simple *buf)
158 {
159 struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
160 uint16_t first, cnt;
161 uint8_t progress;
162 int i;
163
164 first = net_buf_simple_pull_le16(buf);
165 cnt = net_buf_simple_pull_le16(buf);
166 if (cnt == 0) {
167 return -EINVAL;
168 }
169
170 /* Create a buffer that can fit the full target list, maxing out at TX_SDU_MAX: */
171 NET_BUF_SIMPLE_DEFINE(
172 rsp, BT_MESH_MODEL_BUF_LEN(BT_MESH_DFD_OP_RECEIVERS_LIST,
173 DFD_RECEIVERS_LIST_MSG_MAXLEN));
174 bt_mesh_model_msg_init(&rsp, BT_MESH_DFD_OP_RECEIVERS_LIST);
175
176 net_buf_simple_add_le16(&rsp, srv->target_cnt);
177 net_buf_simple_add_le16(&rsp, first);
178
179 cnt = MIN(cnt, srv->target_cnt - first);
180 progress = bt_mesh_dfu_cli_progress(&srv->dfu) / 2;
181
182 for (i = 0; i < cnt && net_buf_simple_tailroom(&rsp) >= 5 + BT_MESH_MIC_SHORT; i++) {
183 const struct bt_mesh_dfu_target *t = &srv->targets[i + first];
184
185 net_buf_simple_add_le32(
186 &rsp, ((t->blob.addr & BIT_MASK(15)) |
187 ((t->phase & BIT_MASK(4)) << 15U) |
188 ((t->status & BIT_MASK(3)) << 19U) |
189 ((t->blob.status & BIT_MASK(4)) << 22U) |
190 ((progress & BIT_MASK(6)) << 26U)));
191 net_buf_simple_add_u8(&rsp, t->img_idx);
192 }
193
194 bt_mesh_model_send(srv->mod, ctx, &rsp, NULL, NULL);
195
196 return 0;
197 }
198
slot_space_cb(const struct bt_mesh_dfu_slot * slot,void * user_data)199 static enum bt_mesh_dfu_iter slot_space_cb(const struct bt_mesh_dfu_slot *slot,
200 void *user_data)
201 {
202 size_t *total = user_data;
203
204 *total += slot->size;
205
206 return BT_MESH_DFU_ITER_CONTINUE;
207 }
208
handle_capabilities_get(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)209 static int handle_capabilities_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
210 struct net_buf_simple *buf)
211 {
212 size_t size = 0;
213
214 BT_MESH_MODEL_BUF_DEFINE(rsp, BT_MESH_DFD_OP_CAPABILITIES_STATUS, 17);
215 bt_mesh_model_msg_init(&rsp, BT_MESH_DFD_OP_CAPABILITIES_STATUS);
216
217 net_buf_simple_add_le16(&rsp, CONFIG_BT_MESH_DFD_SRV_TARGETS_MAX);
218 net_buf_simple_add_le16(&rsp, CONFIG_BT_MESH_DFU_SLOT_CNT);
219 net_buf_simple_add_le32(&rsp, CONFIG_BT_MESH_DFD_SRV_SLOT_MAX_SIZE);
220 net_buf_simple_add_le32(&rsp, CONFIG_BT_MESH_DFD_SRV_SLOT_SPACE);
221
222 /* Remaining size */
223 (void)bt_mesh_dfu_slot_foreach(slot_space_cb, &size);
224 size = MIN(size, CONFIG_BT_MESH_DFD_SRV_SLOT_SPACE);
225
226 net_buf_simple_add_le32(&rsp, CONFIG_BT_MESH_DFD_SRV_SLOT_SPACE - size);
227
228 #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD
229 struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
230
231 if (srv->oob_schemes.count > 0) {
232 net_buf_simple_add_u8(&rsp, 1);
233 net_buf_simple_add_mem(&rsp, srv->oob_schemes.schemes,
234 srv->oob_schemes.count);
235 } else
236 #endif
237 {
238 net_buf_simple_add_u8(&rsp, 0);
239 }
240
241 bt_mesh_model_send(mod, ctx, &rsp, NULL, NULL);
242
243 return 0;
244 }
245
status_rsp(struct bt_mesh_dfd_srv * srv,struct bt_mesh_msg_ctx * ctx,enum bt_mesh_dfd_status status)246 static void status_rsp(struct bt_mesh_dfd_srv *srv, struct bt_mesh_msg_ctx *ctx,
247 enum bt_mesh_dfd_status status)
248 {
249 BT_MESH_MODEL_BUF_DEFINE(rsp, BT_MESH_DFD_OP_STATUS, 12);
250 bt_mesh_model_msg_init(&rsp, BT_MESH_DFD_OP_STATUS);
251
252 net_buf_simple_add_u8(&rsp, status);
253 net_buf_simple_add_u8(&rsp, srv->phase);
254
255 if (srv->phase == BT_MESH_DFD_PHASE_IDLE || !srv->dfu.xfer.slot) {
256 bt_mesh_model_send(srv->mod, ctx, &rsp, NULL, NULL);
257 return;
258 }
259
260 net_buf_simple_add_le16(&rsp, srv->inputs.group);
261 net_buf_simple_add_le16(&rsp, srv->inputs.app_idx);
262 net_buf_simple_add_u8(&rsp, srv->inputs.ttl);
263 net_buf_simple_add_le16(&rsp, srv->inputs.timeout_base);
264 net_buf_simple_add_u8(&rsp, ((srv->dfu.xfer.blob.mode & BIT_MASK(2)) |
265 ((srv->apply & BIT_MASK(1)) << 2)));
266 net_buf_simple_add_le16(&rsp, srv->slot_idx);
267
268 bt_mesh_model_send(srv->mod, ctx, &rsp, NULL, NULL);
269 }
270
handle_get(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)271 static int handle_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
272 struct net_buf_simple *buf)
273 {
274 struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
275
276 status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS);
277
278 return 0;
279 }
280
handle_start(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)281 static int handle_start(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
282 struct net_buf_simple *buf)
283 {
284 struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
285 struct bt_mesh_dfd_start_params params;
286 uint8_t byte;
287
288 params.app_idx = net_buf_simple_pull_le16(buf);
289 params.ttl = net_buf_simple_pull_u8(buf);
290 params.timeout_base = net_buf_simple_pull_le16(buf);
291 byte = net_buf_simple_pull_u8(buf);
292 params.xfer_mode = byte & BIT_MASK(2);
293 params.apply = (byte >> 2U) & BIT_MASK(1);
294 params.slot_idx = net_buf_simple_pull_le16(buf);
295
296 if (buf->len == 16) {
297 /* TODO: Virtual addresses not supported. */
298 status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL);
299 return 0;
300 }
301
302 if (buf->len != 2) {
303 return -EINVAL;
304 }
305
306 params.group = net_buf_simple_pull_le16(buf);
307
308 status_rsp(srv, ctx, bt_mesh_dfd_srv_start(srv, ¶ms));
309
310 return 0;
311 }
312
handle_suspend(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)313 static int handle_suspend(const struct bt_mesh_model *mod,
314 struct bt_mesh_msg_ctx *ctx,
315 struct net_buf_simple *buf)
316 {
317 struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
318
319 status_rsp(srv, ctx, bt_mesh_dfd_srv_suspend(srv));
320
321 return 0;
322 }
323
handle_cancel(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)324 static int handle_cancel(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
325 struct net_buf_simple *buf)
326 {
327 struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
328
329 bt_mesh_dfd_srv_cancel(srv, ctx);
330
331 return 0;
332 }
333
handle_apply(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)334 static int handle_apply(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
335 struct net_buf_simple *buf)
336 {
337 struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
338
339 status_rsp(srv, ctx, bt_mesh_dfd_srv_apply(srv));
340
341 return 0;
342 }
343
upload_status_rsp_with_progress(struct bt_mesh_dfd_srv * srv,struct bt_mesh_msg_ctx * ctx,enum bt_mesh_dfd_status status,uint8_t progress)344 static void upload_status_rsp_with_progress(struct bt_mesh_dfd_srv *srv,
345 struct bt_mesh_msg_ctx *ctx,
346 enum bt_mesh_dfd_status status,
347 uint8_t progress)
348 {
349 BT_MESH_MODEL_BUF_DEFINE(rsp, BT_MESH_DFD_OP_UPLOAD_STATUS,
350 DFD_UPLOAD_STATUS_MSG_MAXLEN);
351 bt_mesh_model_msg_init(&rsp, BT_MESH_DFD_OP_UPLOAD_STATUS);
352
353 net_buf_simple_add_u8(&rsp, status);
354 net_buf_simple_add_u8(&rsp, srv->upload.phase);
355
356 if (srv->upload.phase == BT_MESH_DFD_UPLOAD_PHASE_IDLE ||
357 !srv->upload.slot) {
358 bt_mesh_model_send(srv->mod, ctx, &rsp, NULL, NULL);
359 return;
360 }
361
362 #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD
363 if (srv->upload.is_oob) {
364 net_buf_simple_add_u8(&rsp, progress | BIT(7));
365 net_buf_simple_add_mem(&rsp, srv->upload.oob.current_fwid,
366 srv->upload.oob.current_fwid_len);
367 } else
368 #endif
369 {
370 net_buf_simple_add_u8(&rsp, progress);
371 net_buf_simple_add_mem(&rsp, srv->upload.slot->fwid,
372 srv->upload.slot->fwid_len);
373 }
374
375 bt_mesh_model_send(srv->mod, ctx, &rsp, NULL, NULL);
376 }
377
upload_status_rsp(struct bt_mesh_dfd_srv * srv,struct bt_mesh_msg_ctx * ctx,enum bt_mesh_dfd_status status)378 static void upload_status_rsp(struct bt_mesh_dfd_srv *srv,
379 struct bt_mesh_msg_ctx *ctx,
380 enum bt_mesh_dfd_status status)
381 {
382 uint8_t progress;
383
384 #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD
385 if (srv->upload.is_oob) {
386 progress = srv->cb->oob_progress_get(srv, srv->upload.slot);
387 } else
388 #endif
389 {
390 progress = bt_mesh_blob_srv_progress(&srv->upload.blob);
391 }
392
393 upload_status_rsp_with_progress(srv, ctx, status, progress);
394 }
395
handle_upload_get(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)396 static int handle_upload_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
397 struct net_buf_simple *buf)
398 {
399 struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
400
401 upload_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS);
402
403 return 0;
404 }
405
set_upload_fwid(struct bt_mesh_dfd_srv * srv,struct bt_mesh_msg_ctx * ctx,const uint8_t * fwid,size_t fwid_len)406 static inline int set_upload_fwid(struct bt_mesh_dfd_srv *srv, struct bt_mesh_msg_ctx *ctx,
407 const uint8_t *fwid, size_t fwid_len)
408 {
409 int err = bt_mesh_dfu_slot_fwid_set(srv->upload.slot, fwid, fwid_len);
410
411 switch (err) {
412 case -EFBIG: /* Fwid too long */
413 case -EALREADY: /* Other server is in progress with this fwid */
414 bt_mesh_dfu_slot_release(srv->upload.slot);
415 srv->upload.slot = NULL;
416 upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL);
417 break;
418 case -EEXIST: /* Img with this fwid already is in list */
419 srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_SUCCESS;
420 bt_mesh_dfu_slot_release(srv->upload.slot);
421
422 err = bt_mesh_dfu_slot_get(fwid, fwid_len, &srv->upload.slot);
423 if (!err) {
424 upload_status_rsp_with_progress(srv, ctx, BT_MESH_DFD_SUCCESS, 100);
425 } else {
426 srv->upload.slot = NULL;
427 upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL);
428 }
429 break;
430 case 0:
431 srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE;
432 break;
433 case -EINVAL: /* Slot in wrong state. */
434 default:
435 break;
436 }
437
438 return err;
439 }
440
handle_upload_start(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)441 static int handle_upload_start(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
442 struct net_buf_simple *buf)
443 {
444 struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
445 size_t meta_len, fwid_len, size;
446 const uint8_t *meta, *fwid;
447 uint16_t timeout_base;
448 uint64_t blob_id;
449 int err;
450 uint8_t ttl;
451
452 ttl = net_buf_simple_pull_u8(buf);
453 timeout_base = net_buf_simple_pull_le16(buf);
454 blob_id = net_buf_simple_pull_le64(buf);
455 size = net_buf_simple_pull_le32(buf);
456 meta_len = net_buf_simple_pull_u8(buf);
457 if (buf->len < meta_len) {
458 return -EINVAL;
459 }
460
461 meta = net_buf_simple_pull_mem(buf, meta_len);
462 fwid_len = buf->len;
463 fwid = net_buf_simple_pull_mem(buf, fwid_len);
464
465 LOG_DBG("Upload Start: size: %d, fwid: %s, metadata: %s", size, bt_hex(fwid, fwid_len),
466 bt_hex(meta, meta_len));
467
468 if (size > CONFIG_BT_MESH_DFD_SRV_SLOT_MAX_SIZE) {
469 upload_status_rsp(srv, ctx,
470 BT_MESH_DFD_ERR_INSUFFICIENT_RESOURCES);
471 return 0;
472 }
473
474 if (upload_is_busy(srv)) {
475 if (!srv->upload.slot) {
476 LOG_WRN("Busy with no upload slot");
477 upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL);
478 return 0;
479 }
480
481 if (srv->upload.slot->fwid_len == fwid_len &&
482 !memcmp(srv->upload.slot->fwid, fwid, fwid_len) &&
483 srv->upload.slot->metadata_len == meta_len &&
484 !memcmp(srv->upload.slot->metadata, meta, meta_len) &&
485 srv->upload.blob.state.xfer.id == blob_id &&
486 srv->upload.blob.state.ttl == ttl &&
487 srv->upload.blob.state.timeout_base == timeout_base
488 #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD
489 && !srv->upload.is_oob
490 #endif
491 ) {
492 LOG_DBG("Duplicate upload start");
493 upload_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS);
494 return 0;
495 }
496
497 LOG_WRN("Upload already in progress");
498 upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_BUSY_WITH_UPLOAD);
499 return 0;
500 }
501
502 /* This will be a no-op if the slot state isn't RESERVED, which is
503 * what we want.
504 */
505 if (srv->upload.slot) {
506 bt_mesh_dfu_slot_release(srv->upload.slot);
507 }
508
509 #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD
510 srv->upload.is_oob = false;
511 #endif
512 srv->upload.slot = bt_mesh_dfu_slot_reserve();
513
514 if (!srv->upload.slot) {
515 LOG_WRN("No space for slot");
516 upload_status_rsp(srv, ctx,
517 BT_MESH_DFD_ERR_INSUFFICIENT_RESOURCES);
518 return 0;
519 }
520
521 err = set_upload_fwid(srv, ctx, fwid, fwid_len);
522 if (err) {
523 return err;
524 }
525
526 err = bt_mesh_dfu_slot_info_set(srv->upload.slot, size, meta, meta_len);
527 switch (err) {
528 case -EFBIG:
529 upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL);
530 break;
531 case 0:
532 break;
533 default:
534 return err;
535 }
536
537 srv->io = NULL;
538 err = srv->cb->recv(srv, srv->upload.slot, &srv->io);
539 if (err || !srv->io) {
540 LOG_ERR("App rejected upload. err: %d io: %p", err, srv->io);
541 bt_mesh_dfu_slot_release(srv->upload.slot);
542 upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL);
543 return 0;
544 }
545
546 err = bt_mesh_blob_srv_recv(&srv->upload.blob, blob_id, srv->io, ttl,
547 timeout_base);
548 if (err) {
549 LOG_ERR("BLOB Server rejected upload (err: %d)", err);
550 bt_mesh_dfu_slot_release(srv->upload.slot);
551 upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL);
552 return 0;
553 }
554
555 LOG_DBG("%s", bt_hex(fwid, fwid_len));
556
557 srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE;
558 upload_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS);
559
560 return 0;
561 }
562
handle_upload_start_oob(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)563 static int handle_upload_start_oob(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
564 struct net_buf_simple *buf)
565 {
566 struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
567 uint8_t uri_len;
568 uint8_t *uri;
569 uint16_t fwid_len;
570 uint8_t *fwid;
571
572 uri_len = net_buf_simple_pull_u8(buf);
573
574 if (uri_len > buf->len) {
575 return -EINVAL;
576 }
577
578 uri = net_buf_simple_pull_mem(buf, uri_len);
579 fwid_len = buf->len;
580 fwid = net_buf_simple_pull_mem(buf, fwid_len);
581
582 LOG_DBG("Upload OOB Start");
583 LOG_HEXDUMP_DBG(uri, uri_len, "URI");
584 LOG_HEXDUMP_DBG(fwid, fwid_len, "FWID");
585
586 if (upload_is_busy(srv)) {
587 #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD
588 if (srv->upload.is_oob &&
589 uri_len == srv->upload.oob.uri_len &&
590 fwid_len == srv->upload.oob.current_fwid_len &&
591 !memcmp(uri, srv->upload.oob.uri, uri_len) &&
592 !memcmp(fwid, srv->upload.oob.current_fwid, fwid_len)) {
593 /* Same image, return SUCCESS for idempotency */
594 upload_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS);
595 return 0;
596 }
597 #endif
598 upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_BUSY_WITH_UPLOAD);
599 return 0;
600 #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD
601 } else if (srv->upload.is_oob && srv->upload.is_pending_oob_check) {
602 /* Ignore the request if we didn't confirm the previous one. */
603 return 0;
604 #endif
605 }
606
607 #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD
608 if (uri_len > CONFIG_BT_MESH_DFU_URI_MAXLEN ||
609 fwid_len > CONFIG_BT_MESH_DFU_FWID_MAXLEN) {
610 upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL);
611 return 0;
612 }
613
614 struct bt_mesh_dfu_slot *slot = bt_mesh_dfu_slot_reserve();
615
616 if (slot == NULL) {
617 upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INSUFFICIENT_RESOURCES);
618 return 0;
619 }
620
621 /* This will be a no-op if the slot state isn't RESERVED, which is
622 * what we want.
623 */
624 if (srv->upload.slot) {
625 bt_mesh_dfu_slot_release(srv->upload.slot);
626 }
627
628 srv->upload.is_oob = true;
629 srv->upload.slot = slot;
630 memcpy(srv->upload.oob.uri, uri, uri_len);
631 srv->upload.oob.uri_len = uri_len;
632 memcpy(srv->upload.oob.current_fwid, fwid, fwid_len);
633 srv->upload.oob.current_fwid_len = fwid_len;
634 memcpy(&srv->upload.oob.ctx, ctx, sizeof(struct bt_mesh_msg_ctx));
635
636 int status = srv->cb->start_oob_upload(srv, srv->upload.slot, srv->upload.oob.uri,
637 srv->upload.oob.uri_len,
638 srv->upload.oob.current_fwid,
639 srv->upload.oob.current_fwid_len);
640
641 if (status != BT_MESH_DFD_SUCCESS) {
642 upload_status_rsp(srv, ctx, status);
643 bt_mesh_dfu_slot_release(srv->upload.slot);
644 } else {
645 srv->upload.is_pending_oob_check = true;
646 }
647 #else
648 upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_URI_NOT_SUPPORTED);
649 #endif /* CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD */
650
651 return 0;
652 }
653
handle_upload_cancel(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)654 static int handle_upload_cancel(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
655 struct net_buf_simple *buf)
656 {
657 struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
658
659 srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_IDLE;
660 #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD
661 if (srv->upload.is_oob) {
662 srv->cb->cancel_oob_upload(srv, srv->upload.slot);
663 } else
664 #endif
665 {
666 (void)bt_mesh_blob_srv_cancel(&srv->upload.blob);
667 }
668 upload_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS);
669
670 return 0;
671 }
672
fw_status_rsp(struct bt_mesh_dfd_srv * srv,struct bt_mesh_msg_ctx * ctx,enum bt_mesh_dfd_status status,uint16_t idx,const uint8_t * fwid,size_t fwid_len)673 static void fw_status_rsp(struct bt_mesh_dfd_srv *srv,
674 struct bt_mesh_msg_ctx *ctx,
675 enum bt_mesh_dfd_status status, uint16_t idx,
676 const uint8_t *fwid, size_t fwid_len)
677 {
678 BT_MESH_MODEL_BUF_DEFINE(rsp, BT_MESH_DFD_OP_FW_STATUS,
679 7 + CONFIG_BT_MESH_DFU_FWID_MAXLEN);
680 bt_mesh_model_msg_init(&rsp, BT_MESH_DFD_OP_FW_STATUS);
681
682 net_buf_simple_add_u8(&rsp, status);
683 net_buf_simple_add_le16(&rsp, bt_mesh_dfu_slot_count());
684
685 net_buf_simple_add_le16(&rsp, idx);
686 if (fwid) {
687 net_buf_simple_add_mem(&rsp, fwid, fwid_len);
688 }
689
690 bt_mesh_model_send(srv->mod, ctx, &rsp, NULL, NULL);
691 }
692
handle_fw_get(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)693 static int handle_fw_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
694 struct net_buf_simple *buf)
695 {
696 struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
697 struct bt_mesh_dfu_slot *slot;
698 const uint8_t *fwid;
699 size_t fwid_len;
700 int idx;
701
702 fwid_len = buf->len;
703 fwid = net_buf_simple_pull_mem(buf, fwid_len);
704
705 idx = bt_mesh_dfu_slot_get(fwid, fwid_len, &slot);
706 if (idx >= 0) {
707 fw_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS, idx, fwid,
708 fwid_len);
709 } else {
710 fw_status_rsp(srv, ctx, BT_MESH_DFD_ERR_FW_NOT_FOUND, 0xffff,
711 fwid, fwid_len);
712 }
713
714 return 0;
715 }
716
handle_fw_get_by_index(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)717 static int handle_fw_get_by_index(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
718 struct net_buf_simple *buf)
719 {
720 struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
721 const struct bt_mesh_dfu_slot *slot;
722 uint16_t idx;
723
724 idx = net_buf_simple_pull_le16(buf);
725
726 slot = bt_mesh_dfu_slot_at(idx);
727 if (slot) {
728 fw_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS, idx, slot->fwid,
729 slot->fwid_len);
730 } else {
731 fw_status_rsp(srv, ctx, BT_MESH_DFD_ERR_FW_NOT_FOUND, idx,
732 NULL, 0);
733 }
734
735 return 0;
736 }
737
handle_fw_delete(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)738 static int handle_fw_delete(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
739 struct net_buf_simple *buf)
740 {
741 struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
742 const uint8_t *fwid;
743 size_t fwid_len;
744
745 fwid_len = buf->len;
746 fwid = net_buf_simple_pull_mem(buf, fwid_len);
747
748 enum bt_mesh_dfd_status status = bt_mesh_dfd_srv_fw_delete(srv, &fwid_len, &fwid);
749
750 fw_status_rsp(srv, ctx, status, 0xffff, fwid, fwid_len);
751
752 return 0;
753 }
754
slot_del_cb(const struct bt_mesh_dfu_slot * slot,void * user_data)755 static enum bt_mesh_dfu_iter slot_del_cb(const struct bt_mesh_dfu_slot *slot,
756 void *user_data)
757 {
758 struct bt_mesh_dfd_srv *srv = user_data;
759
760 if (srv->cb && srv->cb->del) {
761 srv->cb->del(srv, slot);
762 }
763
764 return BT_MESH_DFU_ITER_CONTINUE;
765 }
766
handle_fw_delete_all(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)767 static int handle_fw_delete_all(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
768 struct net_buf_simple *buf)
769 {
770 struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
771
772 fw_status_rsp(srv, ctx, bt_mesh_dfd_srv_fw_delete_all(srv), 0xffff, NULL, 0);
773
774 return 0;
775 }
776
777 const struct bt_mesh_model_op _bt_mesh_dfd_srv_op[] = {
778 { BT_MESH_DFD_OP_RECEIVERS_ADD, BT_MESH_LEN_MIN(3), handle_receivers_add },
779 { BT_MESH_DFD_OP_RECEIVERS_DELETE_ALL, BT_MESH_LEN_EXACT(0), handle_receivers_delete_all },
780 { BT_MESH_DFD_OP_RECEIVERS_GET, BT_MESH_LEN_EXACT(4), handle_receivers_get },
781 { BT_MESH_DFD_OP_CAPABILITIES_GET, BT_MESH_LEN_EXACT(0), handle_capabilities_get },
782 { BT_MESH_DFD_OP_GET, BT_MESH_LEN_EXACT(0), handle_get },
783 { BT_MESH_DFD_OP_START, BT_MESH_LEN_MIN(10), handle_start },
784 { BT_MESH_DFD_OP_SUSPEND, BT_MESH_LEN_EXACT(0), handle_suspend },
785 { BT_MESH_DFD_OP_CANCEL, BT_MESH_LEN_EXACT(0), handle_cancel },
786 { BT_MESH_DFD_OP_APPLY, BT_MESH_LEN_EXACT(0), handle_apply },
787 { BT_MESH_DFD_OP_UPLOAD_GET, BT_MESH_LEN_EXACT(0), handle_upload_get },
788 { BT_MESH_DFD_OP_UPLOAD_START, BT_MESH_LEN_MIN(16), handle_upload_start },
789 { BT_MESH_DFD_OP_UPLOAD_START_OOB, BT_MESH_LEN_MIN(2), handle_upload_start_oob },
790 { BT_MESH_DFD_OP_UPLOAD_CANCEL, BT_MESH_LEN_EXACT(0), handle_upload_cancel },
791 { BT_MESH_DFD_OP_FW_GET, BT_MESH_LEN_MIN(0), handle_fw_get },
792 { BT_MESH_DFD_OP_FW_GET_BY_INDEX, BT_MESH_LEN_EXACT(2), handle_fw_get_by_index },
793 { BT_MESH_DFD_OP_FW_DELETE, BT_MESH_LEN_MIN(0), handle_fw_delete },
794 { BT_MESH_DFD_OP_FW_DELETE_ALL, BT_MESH_LEN_EXACT(0), handle_fw_delete_all },
795
796 BT_MESH_MODEL_OP_END
797 };
798
dfu_suspended(struct bt_mesh_dfu_cli * cli)799 static void dfu_suspended(struct bt_mesh_dfu_cli *cli)
800 {
801 struct bt_mesh_dfd_srv *srv =
802 CONTAINER_OF(cli, struct bt_mesh_dfd_srv, dfu);
803
804 srv->phase = BT_MESH_DFD_PHASE_TRANSFER_SUSPENDED;
805 }
806
dfu_ended(struct bt_mesh_dfu_cli * cli,enum bt_mesh_dfu_status reason)807 static void dfu_ended(struct bt_mesh_dfu_cli *cli,
808 enum bt_mesh_dfu_status reason)
809 {
810 struct bt_mesh_dfd_srv *srv =
811 CONTAINER_OF(cli, struct bt_mesh_dfd_srv, dfu);
812 int err;
813
814 LOG_DBG("reason: %u, phase: %u, apply: %u", reason, srv->phase, srv->apply);
815
816 if (srv->phase == BT_MESH_DFD_PHASE_IDLE) {
817 return;
818 }
819
820 if (srv->phase == BT_MESH_DFD_PHASE_CANCELING_UPDATE) {
821 dfd_phase_set(srv, BT_MESH_DFD_PHASE_IDLE);
822 return;
823 }
824
825 if (reason != BT_MESH_DFU_SUCCESS) {
826 dfd_phase_set(srv, BT_MESH_DFD_PHASE_FAILED);
827 return;
828 }
829
830 if (!srv->apply) {
831 dfd_phase_set(srv, BT_MESH_DFD_PHASE_TRANSFER_SUCCESS);
832 return;
833 }
834
835 dfd_phase_set(srv, BT_MESH_DFD_PHASE_APPLYING_UPDATE);
836
837 err = bt_mesh_dfu_cli_apply(cli);
838 if (err) {
839 LOG_ERR("Apply failed: %d", err);
840 dfd_phase_set(srv, BT_MESH_DFD_PHASE_FAILED);
841 }
842 }
843
dfu_applied(struct bt_mesh_dfu_cli * cli)844 static void dfu_applied(struct bt_mesh_dfu_cli *cli)
845 {
846 struct bt_mesh_dfd_srv *srv =
847 CONTAINER_OF(cli, struct bt_mesh_dfd_srv, dfu);
848 int err;
849
850 if (srv->phase == BT_MESH_DFD_PHASE_CANCELING_UPDATE) {
851 dfd_phase_set(srv, BT_MESH_DFD_PHASE_FAILED);
852 return;
853 }
854
855 if (srv->phase != BT_MESH_DFD_PHASE_APPLYING_UPDATE) {
856 return;
857 }
858
859 err = bt_mesh_dfu_cli_confirm(cli);
860 if (err) {
861 LOG_ERR("Confirm failed: %d", err);
862 dfd_phase_set(srv, BT_MESH_DFD_PHASE_FAILED);
863 }
864 }
865
dfu_confirmed(struct bt_mesh_dfu_cli * cli)866 static void dfu_confirmed(struct bt_mesh_dfu_cli *cli)
867 {
868 struct bt_mesh_dfd_srv *srv =
869 CONTAINER_OF(cli, struct bt_mesh_dfd_srv, dfu);
870
871 if (srv->phase != BT_MESH_DFD_PHASE_APPLYING_UPDATE &&
872 srv->phase != BT_MESH_DFD_PHASE_CANCELING_UPDATE) {
873 return;
874 }
875
876 dfd_phase_set(srv, BT_MESH_DFD_PHASE_COMPLETED);
877 }
878
879 const struct bt_mesh_dfu_cli_cb _bt_mesh_dfd_srv_dfu_cb = {
880 .suspended = dfu_suspended,
881 .ended = dfu_ended,
882 .applied = dfu_applied,
883 .confirmed = dfu_confirmed,
884 };
885
upload_start(struct bt_mesh_blob_srv * b,struct bt_mesh_msg_ctx * ctx,struct bt_mesh_blob_xfer * xfer)886 static int upload_start(struct bt_mesh_blob_srv *b, struct bt_mesh_msg_ctx *ctx,
887 struct bt_mesh_blob_xfer *xfer)
888 {
889 LOG_DBG("");
890 return 0;
891 }
892
upload_end(struct bt_mesh_blob_srv * b,uint64_t id,bool success)893 static void upload_end(struct bt_mesh_blob_srv *b, uint64_t id, bool success)
894 {
895 struct bt_mesh_dfd_srv *srv =
896 CONTAINER_OF(b, struct bt_mesh_dfd_srv, upload.blob);
897
898 if (srv->upload.phase != BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE) {
899 return;
900 }
901
902 LOG_DBG("%u", success);
903
904 if (success && (bt_mesh_dfu_slot_commit(srv->upload.slot) == 0)) {
905 srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_SUCCESS;
906 return;
907 }
908
909 /* Will delete slot when we start a new upload */
910 srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ERROR;
911 }
912
upload_timeout(struct bt_mesh_blob_srv * b)913 static void upload_timeout(struct bt_mesh_blob_srv *b)
914 {
915 LOG_DBG("");
916
917 upload_end(b, b->state.xfer.id, false);
918 }
919
920 const struct bt_mesh_blob_srv_cb _bt_mesh_dfd_srv_blob_cb = {
921 .start = upload_start,
922 .end = upload_end,
923 .suspended = upload_timeout,
924 };
925
dfd_srv_init(const struct bt_mesh_model * mod)926 static int dfd_srv_init(const struct bt_mesh_model *mod)
927 {
928 struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
929
930 srv->mod = mod;
931
932 if (IS_ENABLED(CONFIG_BT_MESH_MODEL_EXTENSIONS)) {
933 bt_mesh_model_extend(mod, srv->upload.blob.mod);
934 }
935
936 return 0;
937 }
938
dfd_srv_reset(const struct bt_mesh_model * mod)939 static void dfd_srv_reset(const struct bt_mesh_model *mod)
940 {
941 struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
942
943 dfd_phase_set(srv, BT_MESH_DFD_PHASE_IDLE);
944 srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_IDLE;
945
946 sys_slist_init(&srv->inputs.targets);
947 srv->target_cnt = 0;
948
949 bt_mesh_dfu_slot_foreach(slot_del_cb, srv);
950 bt_mesh_dfu_slot_del_all();
951 }
952
953 const struct bt_mesh_model_cb _bt_mesh_dfd_srv_cb = {
954 .init = dfd_srv_init,
955 .reset = dfd_srv_reset,
956 };
957
bt_mesh_dfd_srv_receiver_add(struct bt_mesh_dfd_srv * srv,uint16_t addr,uint8_t img_idx)958 enum bt_mesh_dfd_status bt_mesh_dfd_srv_receiver_add(struct bt_mesh_dfd_srv *srv, uint16_t addr,
959 uint8_t img_idx)
960 {
961 struct bt_mesh_dfu_target *t;
962 struct bt_mesh_blob_target_pull *p;
963
964 if (!BT_MESH_ADDR_IS_UNICAST(addr)) {
965 return BT_MESH_DFD_SUCCESS;
966 }
967
968 t = target_get(srv, addr);
969 if (t) {
970 t->img_idx = img_idx;
971 return BT_MESH_DFD_SUCCESS;
972 }
973
974 /* New target node, add it to the list */
975
976 if (srv->target_cnt == ARRAY_SIZE(srv->targets)) {
977 return BT_MESH_DFD_ERR_INSUFFICIENT_RESOURCES;
978 }
979
980 t = &srv->targets[srv->target_cnt];
981 p = &srv->pull_ctxs[srv->target_cnt];
982 srv->target_cnt++;
983
984 memset(t, 0, sizeof(*t));
985 memset(p, 0, sizeof(*p));
986 t->blob.addr = addr;
987 t->blob.pull = p;
988 t->img_idx = img_idx;
989
990 LOG_DBG("Added receiver 0x%04x img: %u", t->blob.addr,
991 t->img_idx);
992
993 return BT_MESH_DFD_SUCCESS;
994 }
995
bt_mesh_dfd_srv_receivers_delete_all(struct bt_mesh_dfd_srv * srv)996 enum bt_mesh_dfd_status bt_mesh_dfd_srv_receivers_delete_all(struct bt_mesh_dfd_srv *srv)
997 {
998 if (bt_mesh_dfu_cli_is_busy(&srv->dfu)) {
999 return BT_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION;
1000 }
1001
1002 sys_slist_init(&srv->inputs.targets);
1003 srv->target_cnt = 0;
1004
1005 return BT_MESH_DFD_SUCCESS;
1006 }
1007
bt_mesh_dfd_srv_start(struct bt_mesh_dfd_srv * srv,struct bt_mesh_dfd_start_params * params)1008 enum bt_mesh_dfd_status bt_mesh_dfd_srv_start(struct bt_mesh_dfd_srv *srv,
1009 struct bt_mesh_dfd_start_params *params)
1010 {
1011 int err, i;
1012 struct bt_mesh_dfu_cli_xfer xfer = { 0 };
1013
1014 if (!srv->target_cnt) {
1015 return BT_MESH_DFD_ERR_RECEIVERS_LIST_EMPTY;
1016 }
1017
1018 if (!bt_mesh_app_key_exists(params->app_idx)) {
1019 return BT_MESH_DFD_ERR_INVALID_APPKEY_INDEX;
1020 }
1021
1022 xfer.mode = params->xfer_mode;
1023 xfer.slot = bt_mesh_dfu_slot_at(params->slot_idx);
1024 if (!xfer.slot) {
1025 return BT_MESH_DFD_ERR_FW_NOT_FOUND;
1026 }
1027
1028 if (srv->inputs.app_idx == params->app_idx &&
1029 srv->inputs.timeout_base == params->timeout_base &&
1030 srv->inputs.group == params->group && srv->inputs.ttl == params->ttl &&
1031 srv->dfu.xfer.blob.mode == xfer.mode && srv->apply == params->apply &&
1032 srv->slot_idx == params->slot_idx) {
1033 if (is_busy(srv) ||
1034 srv->phase == BT_MESH_DFD_PHASE_COMPLETED) {
1035 LOG_WRN("Already completed or in progress");
1036 return BT_MESH_DFD_SUCCESS;
1037 } else if (srv->phase == BT_MESH_DFD_PHASE_TRANSFER_SUSPENDED) {
1038 bt_mesh_dfu_cli_resume(&srv->dfu);
1039 dfd_phase_set(srv, BT_MESH_DFD_PHASE_TRANSFER_ACTIVE);
1040 return BT_MESH_DFD_SUCCESS;
1041 }
1042 } else if (is_busy(srv) ||
1043 srv->phase == BT_MESH_DFD_PHASE_TRANSFER_SUSPENDED) {
1044 LOG_WRN("Busy with distribution");
1045 return BT_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION;
1046 }
1047
1048 if (srv->phase == BT_MESH_DFD_PHASE_CANCELING_UPDATE) {
1049 LOG_WRN("Canceling distribution");
1050 return BT_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION;
1051 }
1052
1053 srv->io = NULL;
1054 err = srv->cb->send(srv, xfer.slot, &srv->io);
1055 if (err || !srv->io) {
1056 return BT_MESH_DFD_ERR_INTERNAL;
1057 }
1058
1059 sys_slist_init(&srv->inputs.targets);
1060 for (i = 0; i < srv->target_cnt; i++) {
1061 uint16_t addr = srv->targets[i].blob.addr;
1062
1063 memset(&srv->targets[i].blob, 0, sizeof(struct bt_mesh_blob_target));
1064 memset(&srv->pull_ctxs[i], 0, sizeof(struct bt_mesh_blob_target_pull));
1065 srv->targets[i].blob.addr = addr;
1066 srv->targets[i].blob.pull = &srv->pull_ctxs[i];
1067
1068 sys_slist_append(&srv->inputs.targets, &srv->targets[i].blob.n);
1069 }
1070
1071 srv->slot_idx = params->slot_idx;
1072 srv->inputs.app_idx = params->app_idx;
1073 srv->inputs.timeout_base = params->timeout_base;
1074 srv->inputs.group = params->group;
1075 srv->inputs.ttl = params->ttl;
1076 srv->apply = params->apply;
1077
1078 LOG_DBG("Distribution Start: slot: %d, appidx: %d, tb: %d, addr: %04X, ttl: %d, apply: %d",
1079 params->slot_idx, params->app_idx, params->timeout_base, params->group, params->ttl,
1080 params->apply);
1081
1082 /* DFD Server will always retrieve targets' capabilities before distributing a firmware.*/
1083 xfer.blob_params = NULL;
1084
1085 dfd_phase_set(srv, BT_MESH_DFD_PHASE_TRANSFER_ACTIVE);
1086 err = bt_mesh_dfu_cli_send(&srv->dfu, &srv->inputs, srv->io, &xfer);
1087 if (err) {
1088 dfd_phase_set(srv, BT_MESH_DFD_PHASE_IDLE);
1089 return BT_MESH_DFD_ERR_INTERNAL;
1090 }
1091
1092 return BT_MESH_DFD_SUCCESS;
1093 }
1094
bt_mesh_dfd_srv_suspend(struct bt_mesh_dfd_srv * srv)1095 enum bt_mesh_dfd_status bt_mesh_dfd_srv_suspend(struct bt_mesh_dfd_srv *srv)
1096 {
1097 int err;
1098
1099 if (srv->phase == BT_MESH_DFD_PHASE_TRANSFER_SUSPENDED) {
1100 return BT_MESH_DFD_SUCCESS;
1101 }
1102
1103 if (srv->phase != BT_MESH_DFD_PHASE_TRANSFER_ACTIVE) {
1104 return BT_MESH_DFD_ERR_WRONG_PHASE;
1105 }
1106
1107 err = bt_mesh_dfu_cli_suspend(&srv->dfu);
1108 if (err) {
1109 return BT_MESH_DFD_ERR_SUSPEND_FAILED;
1110 }
1111
1112 srv->phase = BT_MESH_DFD_PHASE_TRANSFER_SUSPENDED;
1113 return BT_MESH_DFD_SUCCESS;
1114 }
1115
bt_mesh_dfd_srv_cancel(struct bt_mesh_dfd_srv * srv,struct bt_mesh_msg_ctx * ctx)1116 enum bt_mesh_dfd_status bt_mesh_dfd_srv_cancel(struct bt_mesh_dfd_srv *srv,
1117 struct bt_mesh_msg_ctx *ctx)
1118 {
1119 enum bt_mesh_dfd_phase prev_phase;
1120 int err;
1121
1122 if (srv->phase == BT_MESH_DFD_PHASE_CANCELING_UPDATE ||
1123 srv->phase == BT_MESH_DFD_PHASE_IDLE) {
1124 if (ctx != NULL) {
1125 status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS);
1126 }
1127 return BT_MESH_DFD_SUCCESS;
1128 }
1129
1130 if (srv->phase == BT_MESH_DFD_PHASE_COMPLETED ||
1131 srv->phase == BT_MESH_DFD_PHASE_FAILED) {
1132 dfd_phase_set(srv, BT_MESH_DFD_PHASE_IDLE);
1133 if (ctx != NULL) {
1134 status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS);
1135 }
1136 return BT_MESH_DFD_SUCCESS;
1137 }
1138
1139 /* Phase TRANSFER_ACTIVE, TRANSFER_SUSPENDED, TRANSFER_SUCCESS, APPLYING_UPDATE: */
1140
1141 prev_phase = srv->phase;
1142 dfd_phase_set(srv, BT_MESH_DFD_PHASE_CANCELING_UPDATE);
1143 err = bt_mesh_dfu_cli_cancel(&srv->dfu, NULL);
1144 if (err) {
1145 if (ctx != NULL) {
1146 status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL);
1147 }
1148 return BT_MESH_DFD_ERR_INTERNAL;
1149 }
1150
1151 if (prev_phase == BT_MESH_DFD_PHASE_APPLYING_UPDATE && ctx) {
1152 /* Disable randomization for the Firmware Distribution State message to avoid
1153 * reordering when Firmware Distribution Server sends 2 messages in a row when
1154 * cancelling the update (see section 6.2.3.10 of MshDFUv1.0).
1155 */
1156 ctx->rnd_delay = false;
1157 }
1158
1159 if (ctx != NULL) {
1160 status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS);
1161 }
1162
1163 if (prev_phase == BT_MESH_DFD_PHASE_APPLYING_UPDATE) {
1164 dfd_phase_set(srv, BT_MESH_DFD_PHASE_IDLE);
1165 if (ctx != NULL) {
1166 status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS);
1167 }
1168 }
1169
1170 return BT_MESH_DFD_SUCCESS;
1171 }
1172
bt_mesh_dfd_srv_apply(struct bt_mesh_dfd_srv * srv)1173 enum bt_mesh_dfd_status bt_mesh_dfd_srv_apply(struct bt_mesh_dfd_srv *srv)
1174 {
1175 int err;
1176
1177 if (srv->phase == BT_MESH_DFD_PHASE_IDLE ||
1178 srv->phase == BT_MESH_DFD_PHASE_CANCELING_UPDATE ||
1179 srv->phase == BT_MESH_DFD_PHASE_TRANSFER_ACTIVE ||
1180 srv->phase == BT_MESH_DFD_PHASE_TRANSFER_SUSPENDED ||
1181 srv->phase == BT_MESH_DFD_PHASE_FAILED) {
1182 return BT_MESH_DFD_ERR_WRONG_PHASE;
1183 }
1184
1185 if (srv->phase == BT_MESH_DFD_PHASE_APPLYING_UPDATE ||
1186 srv->phase == BT_MESH_DFD_PHASE_COMPLETED) {
1187 return BT_MESH_DFD_SUCCESS;
1188 }
1189
1190 err = bt_mesh_dfu_cli_apply(&srv->dfu);
1191 if (err) {
1192 return BT_MESH_DFD_ERR_INTERNAL;
1193 }
1194
1195 dfd_phase_set(srv, BT_MESH_DFD_PHASE_APPLYING_UPDATE);
1196 return BT_MESH_DFD_SUCCESS;
1197 }
1198
bt_mesh_dfd_srv_fw_delete(struct bt_mesh_dfd_srv * srv,size_t * fwid_len,const uint8_t ** fwid)1199 enum bt_mesh_dfd_status bt_mesh_dfd_srv_fw_delete(struct bt_mesh_dfd_srv *srv, size_t *fwid_len,
1200 const uint8_t **fwid)
1201 {
1202 struct bt_mesh_dfu_slot *slot;
1203 int idx, err;
1204
1205 if (srv->phase != BT_MESH_DFD_PHASE_IDLE) {
1206 *fwid = NULL;
1207 *fwid_len = 0;
1208 return BT_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION;
1209 }
1210
1211 idx = bt_mesh_dfu_slot_get(*fwid, *fwid_len, &slot);
1212 if (idx < 0) {
1213 return BT_MESH_DFD_SUCCESS;
1214 }
1215
1216 err = slot_del(srv, slot);
1217 if (err) {
1218 *fwid = NULL;
1219 *fwid_len = 0;
1220 return BT_MESH_DFD_ERR_INTERNAL;
1221 } else {
1222 return BT_MESH_DFD_SUCCESS;
1223 }
1224 }
1225
bt_mesh_dfd_srv_fw_delete_all(struct bt_mesh_dfd_srv * srv)1226 enum bt_mesh_dfd_status bt_mesh_dfd_srv_fw_delete_all(struct bt_mesh_dfd_srv *srv)
1227 {
1228 if (srv->phase != BT_MESH_DFD_PHASE_IDLE) {
1229 return BT_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION;
1230 }
1231
1232 bt_mesh_dfu_slot_foreach(slot_del_cb, srv);
1233
1234 bt_mesh_dfu_slot_del_all();
1235
1236 return BT_MESH_DFD_SUCCESS;
1237 }
1238
1239 #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD
bt_mesh_dfd_srv_oob_check_complete(struct bt_mesh_dfd_srv * srv,const struct bt_mesh_dfu_slot * slot,int status,uint8_t * fwid,size_t fwid_len)1240 int bt_mesh_dfd_srv_oob_check_complete(struct bt_mesh_dfd_srv *srv,
1241 const struct bt_mesh_dfu_slot *slot, int status,
1242 uint8_t *fwid, size_t fwid_len)
1243 {
1244 int err;
1245
1246 if (slot != srv->upload.slot || !srv->upload.is_oob ||
1247 srv->upload.phase == BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE ||
1248 !srv->upload.is_pending_oob_check) {
1249 /* This should not happen, unless the application calls the function with a
1250 * "wrong" pointer or at a wrong time.
1251 */
1252 return -EINVAL;
1253 }
1254
1255 srv->upload.is_pending_oob_check = false;
1256
1257 if (status != BT_MESH_DFD_SUCCESS) {
1258 bt_mesh_dfu_slot_release(srv->upload.slot);
1259 upload_status_rsp(srv, &srv->upload.oob.ctx, status);
1260 return -ECANCELED;
1261 }
1262
1263 err = set_upload_fwid(srv, &srv->upload.oob.ctx, fwid, fwid_len);
1264
1265 if (err) {
1266 return err;
1267 }
1268
1269 upload_status_rsp(srv, &srv->upload.oob.ctx, BT_MESH_DFD_SUCCESS);
1270 return 0;
1271 }
1272
bt_mesh_dfd_srv_oob_store_complete(struct bt_mesh_dfd_srv * srv,const struct bt_mesh_dfu_slot * slot,bool success,size_t size,const uint8_t * metadata,size_t metadata_len)1273 int bt_mesh_dfd_srv_oob_store_complete(struct bt_mesh_dfd_srv *srv,
1274 const struct bt_mesh_dfu_slot *slot, bool success,
1275 size_t size, const uint8_t *metadata, size_t metadata_len)
1276 {
1277 int err = 0;
1278
1279 if (srv->upload.phase != BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE ||
1280 srv->upload.slot != slot || !srv->upload.is_oob) {
1281 return -EINVAL;
1282 }
1283
1284 if (!success) {
1285 goto error;
1286 }
1287
1288 err = bt_mesh_dfu_slot_info_set(srv->upload.slot, size, metadata, metadata_len);
1289 if (err) {
1290 goto error;
1291 }
1292
1293 err = bt_mesh_dfu_slot_commit(srv->upload.slot);
1294 if (err) {
1295 goto error;
1296 }
1297
1298 srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_SUCCESS;
1299 return 0;
1300
1301 error:
1302 srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ERROR;
1303 bt_mesh_dfu_slot_release(srv->upload.slot);
1304 return err;
1305 }
1306 #endif /* CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD */
1307