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