Lines Matching refs:cli
18 #define TARGETS_FOR_EACH(cli, target) \ argument
19 SYS_SLIST_FOR_EACH_CONTAINER((sys_slist_t *)&(cli)->inputs->targets, \
25 #define CLIENT_TIMEOUT_MSEC(cli) (10 * MSEC_PER_SEC * (cli->inputs->timeout_base + 2) + \ argument
26 100 * cli->inputs->ttl)
30 #define SENDING_CHUNKS_IN_PULL_MODE(cli) ((cli)->state == BT_MESH_BLOB_CLI_STATE_BLOCK_SEND && \ argument
31 (cli)->xfer->mode == BT_MESH_BLOB_XFER_MODE_PULL)
32 #define UNICAST_MODE(cli) ((cli)->inputs->group == BT_MESH_ADDR_UNASSIGNED || \ argument
33 (cli)->tx.ctx.force_unicast)
56 static struct bt_mesh_blob_target *next_target(struct bt_mesh_blob_cli *cli,
58 static void transfer_cancel(struct bt_mesh_blob_cli *cli);
60 static void start_retry_timer(struct bt_mesh_blob_cli *cli) in start_retry_timer() argument
64 if (SENDING_CHUNKS_IN_PULL_MODE(cli)) { in start_retry_timer()
65 int64_t next_timeout_ms = cli->tx.cli_timestamp; in start_retry_timer()
68 TARGETS_FOR_EACH(cli, target) { in start_retry_timer()
82 next_timeout = K_MSEC(CLIENT_TIMEOUT_MSEC(cli) / in start_retry_timer()
86 (void)k_work_reschedule(&cli->tx.retry, next_timeout); in start_retry_timer()
89 static void cli_state_reset(struct bt_mesh_blob_cli *cli) in cli_state_reset() argument
91 k_work_cancel_delayable(&cli->tx.retry); in cli_state_reset()
92 cli->xfer = NULL; in cli_state_reset()
93 cli->state = BT_MESH_BLOB_CLI_STATE_NONE; in cli_state_reset()
94 cli->tx.ctx.is_inited = 0; in cli_state_reset()
95 cli->tx.cli_timestamp = 0ll; in cli_state_reset()
96 cli->tx.sending = 0; in cli_state_reset()
99 static struct bt_mesh_blob_target *target_get(struct bt_mesh_blob_cli *cli, in target_get() argument
104 TARGETS_FOR_EACH(cli, target) { in target_get()
114 static void target_drop(struct bt_mesh_blob_cli *cli, in target_drop() argument
121 if (cli->cb && cli->cb->lost_target) { in target_drop()
122 cli->cb->lost_target(cli, target, reason); in target_drop()
126 static uint32_t targets_reset(struct bt_mesh_blob_cli *cli) in targets_reset() argument
131 TARGETS_FOR_EACH(cli, target) { in targets_reset()
141 static bool targets_active(struct bt_mesh_blob_cli *cli) in targets_active() argument
145 TARGETS_FOR_EACH(cli, target) { in targets_active()
154 static bool targets_timedout(struct bt_mesh_blob_cli *cli) in targets_timedout() argument
158 TARGETS_FOR_EACH(cli, target) { in targets_timedout()
167 static int io_open(struct bt_mesh_blob_cli *cli) in io_open() argument
169 if (!cli->io->open) { in io_open()
173 return cli->io->open(cli->io, cli->xfer, BT_MESH_BLOB_READ); in io_open()
176 static void io_close(struct bt_mesh_blob_cli *cli) in io_close() argument
178 if (!cli->io->close) { in io_close()
182 cli->io->close(cli->io, cli->xfer); in io_close()
185 static uint16_t next_missing_chunk(struct bt_mesh_blob_cli *cli, in next_missing_chunk() argument
193 } while (++idx < cli->block.chunk_count); in next_missing_chunk()
199 static void update_missing_chunks(struct bt_mesh_blob_cli *cli) in update_missing_chunks() argument
203 memset(cli->block.missing, 0, sizeof(cli->block.missing)); in update_missing_chunks()
205 TARGETS_FOR_EACH(cli, target) { in update_missing_chunks()
210 for (size_t idx = 0; idx < cli->block.chunk_count; idx++) { in update_missing_chunks()
211 bool missing = blob_chunk_missing_get(cli->block.missing, idx) || in update_missing_chunks()
213 blob_chunk_missing_set(cli->block.missing, idx, missing); in update_missing_chunks()
264 static void block_set(struct bt_mesh_blob_cli *cli, uint16_t block_idx) in block_set() argument
266 cli->block.number = block_idx; in block_set()
267 cli->block.offset = block_idx * (1UL << cli->xfer->block_size_log); in block_set()
268 cli->block.size = blob_block_size(cli->xfer->size, cli->xfer->block_size_log, in block_set()
270 cli->block.chunk_count = in block_set()
271 DIV_ROUND_UP(cli->block.size, cli->xfer->chunk_size); in block_set()
273 if (cli->xfer->mode == BT_MESH_BLOB_XFER_MODE_PUSH) { in block_set()
274 blob_chunk_missing_set_all(&cli->block); in block_set()
279 memset(cli->block.missing, 0, sizeof(cli->block.missing)); in block_set()
281 TARGETS_FOR_EACH(cli, target) { in block_set()
286 LOG_DBG("%u size: %u chunks: %u", block_idx, cli->block.size, in block_set()
287 cli->block.chunk_count); in block_set()
290 static void suspend(struct bt_mesh_blob_cli *cli) in suspend() argument
292 cli->state = BT_MESH_BLOB_CLI_STATE_SUSPENDED; in suspend()
294 if (cli->cb && cli->cb->suspended) { in suspend()
295 cli->cb->suspended(cli); in suspend()
299 static void end(struct bt_mesh_blob_cli *cli, bool success) in end() argument
301 const struct bt_mesh_blob_xfer *xfer = cli->xfer; in end()
305 io_close(cli); in end()
306 cli_state_reset(cli); in end()
307 if (cli->cb && cli->cb->end) { in end()
308 cli->cb->end(cli, xfer, success); in end()
312 static enum bt_mesh_blob_status caps_adjust(struct bt_mesh_blob_cli *cli, in caps_adjust() argument
315 if (!(in->modes & cli->caps.modes)) { in caps_adjust()
319 if ((in->min_block_size_log > cli->caps.max_block_size_log) || in caps_adjust()
320 (in->max_block_size_log < cli->caps.min_block_size_log)) { in caps_adjust()
324 cli->caps.min_block_size_log = in caps_adjust()
325 MAX(cli->caps.min_block_size_log, in->min_block_size_log); in caps_adjust()
326 cli->caps.max_block_size_log = in caps_adjust()
327 MIN(cli->caps.max_block_size_log, in->max_block_size_log); in caps_adjust()
328 cli->caps.max_chunks = MIN(cli->caps.max_chunks, in->max_chunks); in caps_adjust()
329 cli->caps.mtu_size = MIN(cli->caps.mtu_size, in->mtu_size); in caps_adjust()
330 cli->caps.max_chunk_size = MIN(cli->caps.max_chunk_size, in->max_chunk_size); in caps_adjust()
331 cli->caps.modes &= in->modes; in caps_adjust()
332 cli->caps.max_size = MIN(cli->caps.max_size, in->max_size); in caps_adjust()
348 static struct bt_mesh_blob_target *next_target(struct bt_mesh_blob_cli *cli, in next_target() argument
355 (sys_slist_t *)&cli->inputs->targets, *current, n); in next_target()
365 if (SENDING_CHUNKS_IN_PULL_MODE(cli) && in next_target()
367 !blob_chunk_missing_get((*current)->pull->missing, cli->chunk_idx))) { in next_target()
383 static void send(struct bt_mesh_blob_cli *cli) in send() argument
385 cli->tx.sending = 1U; in send()
386 if (UNICAST_MODE(cli)) { in send()
387 cli->tx.ctx.send(cli, cli->tx.target->addr); in send()
389 cli->tx.ctx.send(cli, cli->inputs->group); in send()
393 static void broadcast_complete(struct bt_mesh_blob_cli *cli) in broadcast_complete() argument
395 LOG_DBG("%s", cli->tx.cancelled ? "cancelling" : "continuing"); in broadcast_complete()
397 cli->tx.ctx.is_inited = 0; in broadcast_complete()
398 k_work_cancel_delayable(&cli->tx.retry); in broadcast_complete()
400 if (cli->tx.cancelled) { in broadcast_complete()
401 transfer_cancel(cli); in broadcast_complete()
403 __ASSERT(cli->tx.ctx.next, "No next callback"); in broadcast_complete()
404 cli->tx.ctx.next(cli); in broadcast_complete()
411 struct bt_mesh_blob_cli *cli = CONTAINER_OF(dwork, struct bt_mesh_blob_cli, tx.complete); in tx_complete() local
413 if (!cli->tx.ctx.is_inited || !cli->tx.sending) { in tx_complete()
417 cli->tx.sending = 0U; in tx_complete()
419 if (cli->tx.cancelled) { in tx_complete()
420 broadcast_complete(cli); in tx_complete()
424 if (cli->tx.ctx.send_complete) { in tx_complete()
425 cli->tx.ctx.send_complete(cli, cli->tx.target->addr); in tx_complete()
428 if (UNICAST_MODE(cli) && next_target(cli, &cli->tx.target)) { in tx_complete()
429 send(cli); in tx_complete()
433 if (cli->tx.ctx.acked && cli->tx.pending) { in tx_complete()
434 start_retry_timer(cli); in tx_complete()
438 broadcast_complete(cli); in tx_complete()
441 static void drop_remaining_targets(struct bt_mesh_blob_cli *cli) in drop_remaining_targets() argument
447 cli->tx.pending = 0; in drop_remaining_targets()
449 TARGETS_FOR_EACH(cli, target) { in drop_remaining_targets()
453 target_drop(cli, target, BT_MESH_BLOB_ERR_INTERNAL); in drop_remaining_targets()
458 if (SENDING_CHUNKS_IN_PULL_MODE(cli)) { in drop_remaining_targets()
459 update_missing_chunks(cli); in drop_remaining_targets()
465 struct bt_mesh_blob_cli *cli = in retry_timeout() local
474 if (SENDING_CHUNKS_IN_PULL_MODE(cli)) { in retry_timeout()
475 if (k_uptime_get() >= cli->tx.cli_timestamp) { in retry_timeout()
478 if (!cli->tx.ctx.optional) { in retry_timeout()
479 drop_remaining_targets(cli); in retry_timeout()
483 broadcast_complete(cli); in retry_timeout()
487 LOG_DBG("%u", cli->tx.retries); in retry_timeout()
489 cli->tx.retries--; in retry_timeout()
490 cli->tx.target = NULL; in retry_timeout()
492 __ASSERT(!cli->tx.sending, "still sending"); in retry_timeout()
493 __ASSERT(cli->tx.ctx.is_inited, "ctx is not initialized"); in retry_timeout()
495 if (!cli->tx.retries) { in retry_timeout()
498 if (!cli->tx.ctx.optional) { in retry_timeout()
499 drop_remaining_targets(cli); in retry_timeout()
502 broadcast_complete(cli); in retry_timeout()
506 if (!cli->tx.ctx.acked || !next_target(cli, &cli->tx.target) || cli->tx.cancelled) { in retry_timeout()
507 broadcast_complete(cli); in retry_timeout()
511 send(cli); in retry_timeout()
514 void blob_cli_broadcast(struct bt_mesh_blob_cli *cli, in blob_cli_broadcast() argument
517 if (cli->tx.ctx.is_inited || cli->tx.sending) { in blob_cli_broadcast()
522 cli->tx.cancelled = 0U; in blob_cli_broadcast()
523 cli->tx.retries = CONFIG_BT_MESH_BLOB_CLI_BLOCK_RETRIES; in blob_cli_broadcast()
524 cli->tx.ctx = *ctx; in blob_cli_broadcast()
525 cli->tx.ctx.is_inited = 1U; in blob_cli_broadcast()
527 cli->tx.pending = targets_reset(cli); in blob_cli_broadcast()
529 LOG_DBG("%u targets", cli->tx.pending); in blob_cli_broadcast()
531 cli->tx.target = NULL; in blob_cli_broadcast()
532 if (!next_target(cli, &cli->tx.target)) { in blob_cli_broadcast()
534 broadcast_complete(cli); in blob_cli_broadcast()
538 send(cli); in blob_cli_broadcast()
541 void blob_cli_broadcast_tx_complete(struct bt_mesh_blob_cli *cli) in blob_cli_broadcast_tx_complete() argument
543 k_work_schedule(&cli->tx.complete, K_MSEC(cli->tx.ctx.post_send_delay_ms)); in blob_cli_broadcast_tx_complete()
546 void blob_cli_broadcast_rsp(struct bt_mesh_blob_cli *cli, in blob_cli_broadcast_rsp() argument
553 LOG_DBG("0x%04x, pending: %d", target->addr, cli->tx.pending); in blob_cli_broadcast_rsp()
557 if (!--cli->tx.pending && !cli->tx.sending) { in blob_cli_broadcast_rsp()
558 broadcast_complete(cli); in blob_cli_broadcast_rsp()
562 void blob_cli_broadcast_abort(struct bt_mesh_blob_cli *cli) in blob_cli_broadcast_abort() argument
564 if (!cli->tx.ctx.is_inited) { in blob_cli_broadcast_abort()
568 if ((cli)->state >= BT_MESH_BLOB_CLI_STATE_START) { in blob_cli_broadcast_abort()
569 io_close(cli); in blob_cli_broadcast_abort()
572 cli_state_reset(cli); in blob_cli_broadcast_abort()
578 static int tx(struct bt_mesh_blob_cli *cli, uint16_t addr, in tx() argument
586 .app_idx = cli->inputs->app_idx, in tx()
588 .send_ttl = cli->inputs->ttl, in tx()
592 err = bt_mesh_model_send(cli->mod, &ctx, buf, &end_cb, cli); in tx()
595 send_end(err, cli); in tx()
612 struct bt_mesh_blob_cli *cli = user_data; in send_end() local
614 if (!cli->tx.ctx.is_inited) { in send_end()
618 blob_cli_broadcast_tx_complete(cli); in send_end()
625 static void info_get_tx(struct bt_mesh_blob_cli *cli, uint16_t dst) in info_get_tx() argument
630 tx(cli, dst, &buf); in info_get_tx()
633 static void xfer_start_tx(struct bt_mesh_blob_cli *cli, uint16_t dst) in xfer_start_tx() argument
637 net_buf_simple_add_u8(&buf, cli->xfer->mode << 6); in xfer_start_tx()
638 net_buf_simple_add_le64(&buf, cli->xfer->id); in xfer_start_tx()
639 net_buf_simple_add_le32(&buf, cli->xfer->size); in xfer_start_tx()
640 net_buf_simple_add_u8(&buf, cli->xfer->block_size_log); in xfer_start_tx()
643 tx(cli, dst, &buf); in xfer_start_tx()
646 static void xfer_get_tx(struct bt_mesh_blob_cli *cli, uint16_t dst) in xfer_get_tx() argument
651 tx(cli, dst, &buf); in xfer_get_tx()
654 static void xfer_cancel_tx(struct bt_mesh_blob_cli *cli, uint16_t dst) in xfer_cancel_tx() argument
658 net_buf_simple_add_le64(&buf, cli->xfer->id); in xfer_cancel_tx()
660 tx(cli, dst, &buf); in xfer_cancel_tx()
663 static void block_start_tx(struct bt_mesh_blob_cli *cli, uint16_t dst) in block_start_tx() argument
667 net_buf_simple_add_le16(&buf, cli->block.number); in block_start_tx()
668 net_buf_simple_add_le16(&buf, cli->xfer->chunk_size); in block_start_tx()
670 tx(cli, dst, &buf); in block_start_tx()
673 static void chunk_tx(struct bt_mesh_blob_cli *cli, uint16_t dst) in chunk_tx() argument
680 net_buf_simple_add_le16(&buf, cli->chunk_idx); in chunk_tx()
682 chunk.size = chunk_size(cli->xfer, &cli->block, cli->chunk_idx); in chunk_tx()
683 chunk.offset = cli->xfer->chunk_size * cli->chunk_idx; in chunk_tx()
686 err = cli->io->rd(cli->io, cli->xfer, &cli->block, &chunk); in chunk_tx()
687 if (err || cli->state == BT_MESH_BLOB_CLI_STATE_NONE) { in chunk_tx()
688 bt_mesh_blob_cli_cancel(cli); in chunk_tx()
692 tx(cli, dst, &buf); in chunk_tx()
695 static void block_get_tx(struct bt_mesh_blob_cli *cli, uint16_t dst) in block_get_tx() argument
700 tx(cli, dst, &buf); in block_get_tx()
777 static void caps_collected(struct bt_mesh_blob_cli *cli);
778 static void block_start(struct bt_mesh_blob_cli *cli);
779 static void chunk_send(struct bt_mesh_blob_cli *cli);
780 static void block_check(struct bt_mesh_blob_cli *cli);
781 static void block_check_end(struct bt_mesh_blob_cli *cli);
782 static void block_report_wait(struct bt_mesh_blob_cli *cli);
783 static void chunk_send_end(struct bt_mesh_blob_cli *cli);
784 static void confirm_transfer(struct bt_mesh_blob_cli *cli);
785 static void transfer_complete(struct bt_mesh_blob_cli *cli);
787 static void caps_get(struct bt_mesh_blob_cli *cli) in caps_get() argument
795 cli->state = BT_MESH_BLOB_CLI_STATE_CAPS_GET; in caps_get()
796 blob_cli_broadcast(cli, &ctx); in caps_get()
799 static void caps_collected(struct bt_mesh_blob_cli *cli) in caps_collected() argument
804 cli->state = BT_MESH_BLOB_CLI_STATE_NONE; in caps_collected()
806 cli_state_reset(cli); in caps_collected()
808 TARGETS_FOR_EACH(cli, target) { in caps_collected()
816 (1UL << cli->caps.max_block_size_log) > in caps_collected()
817 (cli->caps.max_chunk_size * cli->caps.max_chunks)) { in caps_collected()
818 cli->caps.max_block_size_log--; in caps_collected()
821 if (cli->cb && cli->cb->caps) { in caps_collected()
822 cli->cb->caps(cli, success ? &cli->caps : NULL); in caps_collected()
826 static int xfer_start(struct bt_mesh_blob_cli *cli) in xfer_start() argument
835 err = io_open(cli); in xfer_start()
840 cli->state = BT_MESH_BLOB_CLI_STATE_START; in xfer_start()
842 blob_cli_broadcast(cli, &ctx); in xfer_start()
846 static void block_start(struct bt_mesh_blob_cli *cli) in block_start() argument
856 if (!targets_active(cli)) { in block_start()
857 if (targets_timedout(cli)) { in block_start()
858 suspend(cli); in block_start()
862 end(cli, false); in block_start()
866 LOG_DBG("%u (%u chunks, %u/%u)", cli->block.number, in block_start()
867 cli->block.chunk_count, cli->block.number + 1, cli->block_count); in block_start()
869 cli->chunk_idx = 0; in block_start()
870 cli->state = BT_MESH_BLOB_CLI_STATE_BLOCK_START; in block_start()
875 cli->tx.cli_timestamp = 0ll; in block_start()
877 TARGETS_FOR_EACH(cli, target) { in block_start()
880 if (cli->xfer->mode == BT_MESH_BLOB_XFER_MODE_PULL) { in block_start()
885 if (cli->io->block_start) { in block_start()
886 cli->io->block_start(cli->io, cli->xfer, &cli->block); in block_start()
887 if (cli->state == BT_MESH_BLOB_CLI_STATE_NONE) { in block_start()
892 blob_cli_broadcast(cli, &ctx); in block_start()
895 static void chunk_tx_complete(struct bt_mesh_blob_cli *cli, uint16_t dst) in chunk_tx_complete() argument
897 if (cli->xfer->mode != BT_MESH_BLOB_XFER_MODE_PULL) { in chunk_tx_complete()
904 uint16_t chunk_idx = next_missing_chunk(cli, cli->tx.target->pull->missing, in chunk_tx_complete()
905 cli->chunk_idx + 1); in chunk_tx_complete()
906 if (chunk_idx < cli->block.chunk_count) { in chunk_tx_complete()
916 if (!UNICAST_MODE(cli)) { in chunk_tx_complete()
920 TARGETS_FOR_EACH(cli, target) { in chunk_tx_complete()
926 cli->tx.target->pull->block_report_timestamp = timestamp; in chunk_tx_complete()
929 static void chunk_send(struct bt_mesh_blob_cli *cli) in chunk_send() argument
935 .post_send_delay_ms = cli->chunk_interval_ms, in chunk_send()
938 if (cli->xfer->mode == BT_MESH_BLOB_XFER_MODE_PULL) { in chunk_send()
942 if (!targets_active(cli)) { in chunk_send()
943 if (targets_timedout(cli)) { in chunk_send()
944 suspend(cli); in chunk_send()
948 end(cli, false); in chunk_send()
952 LOG_DBG("%u / %u size: %u", cli->chunk_idx + 1, cli->block.chunk_count, in chunk_send()
953 chunk_size(cli->xfer, &cli->block, cli->chunk_idx)); in chunk_send()
955 cli->state = BT_MESH_BLOB_CLI_STATE_BLOCK_SEND; in chunk_send()
956 blob_cli_broadcast(cli, &ctx); in chunk_send()
959 static void chunk_send_end(struct bt_mesh_blob_cli *cli) in chunk_send_end() argument
965 if (cli->xfer->mode == BT_MESH_BLOB_XFER_MODE_PUSH) { in chunk_send_end()
966 blob_chunk_missing_set(cli->block.missing, cli->chunk_idx, false); in chunk_send_end()
969 cli->chunk_idx = next_missing_chunk(cli, cli->block.missing, cli->chunk_idx + 1); in chunk_send_end()
970 if (cli->chunk_idx < cli->block.chunk_count) { in chunk_send_end()
971 chunk_send(cli); in chunk_send_end()
975 if (cli->xfer->mode == BT_MESH_BLOB_XFER_MODE_PUSH) { in chunk_send_end()
976 block_check(cli); in chunk_send_end()
978 block_report_wait(cli); in chunk_send_end()
985 static void block_check(struct bt_mesh_blob_cli *cli) in block_check() argument
993 cli->state = BT_MESH_BLOB_CLI_STATE_BLOCK_CHECK; in block_check()
997 blob_cli_broadcast(cli, &ctx); in block_check()
1000 static void block_report_wait(struct bt_mesh_blob_cli *cli) in block_report_wait() argument
1008 if (next_missing_chunk(cli, cli->block.missing, 0) >= cli->block.chunk_count) { in block_report_wait()
1009 block_check_end(cli); in block_report_wait()
1014 cli->tx.ctx = ctx; in block_report_wait()
1017 if (!cli->tx.cli_timestamp) { in block_report_wait()
1018 cli->tx.cli_timestamp = k_uptime_get() + CLIENT_TIMEOUT_MSEC(cli); in block_report_wait()
1021 start_retry_timer(cli); in block_report_wait()
1024 static void block_check_end(struct bt_mesh_blob_cli *cli) in block_check_end() argument
1028 if (!targets_active(cli)) { in block_check_end()
1029 if (targets_timedout(cli)) { in block_check_end()
1030 suspend(cli); in block_check_end()
1034 end(cli, false); in block_check_end()
1038 cli->chunk_idx = next_missing_chunk(cli, cli->block.missing, 0); in block_check_end()
1039 if (cli->chunk_idx < cli->block.chunk_count) { in block_check_end()
1040 chunk_send(cli); in block_check_end()
1044 LOG_DBG("No more missing chunks for block %u", cli->block.number); in block_check_end()
1046 if (cli->io->block_end) { in block_check_end()
1047 cli->io->block_end(cli->io, cli->xfer, &cli->block); in block_check_end()
1048 if (cli->state == BT_MESH_BLOB_CLI_STATE_NONE) { in block_check_end()
1053 if (cli->block.number == cli->block_count - 1) { in block_check_end()
1056 TARGETS_FOR_EACH(cli, target) { in block_check_end()
1060 confirm_transfer(cli); in block_check_end()
1064 block_set(cli, cli->block.number + 1); in block_check_end()
1065 block_start(cli); in block_check_end()
1068 static void confirm_transfer(struct bt_mesh_blob_cli *cli) in confirm_transfer() argument
1078 cli->state = BT_MESH_BLOB_CLI_STATE_XFER_CHECK; in confirm_transfer()
1080 blob_cli_broadcast(cli, &ctx); in confirm_transfer()
1083 static void progress_checked(struct bt_mesh_blob_cli *cli) in progress_checked() argument
1087 cli->state = BT_MESH_BLOB_CLI_STATE_NONE; in progress_checked()
1089 if (cli->cb && cli->cb->end) { in progress_checked()
1090 cli->cb->xfer_progress_complete(cli); in progress_checked()
1094 static void check_transfer(struct bt_mesh_blob_cli *cli) in check_transfer() argument
1104 cli->state = BT_MESH_BLOB_CLI_STATE_XFER_PROGRESS_GET; in check_transfer()
1106 blob_cli_broadcast(cli, &ctx); in check_transfer()
1109 static void transfer_cancel(struct bt_mesh_blob_cli *cli) in transfer_cancel() argument
1119 cli->state = BT_MESH_BLOB_CLI_STATE_CANCEL; in transfer_cancel()
1121 blob_cli_broadcast(cli, &ctx); in transfer_cancel()
1124 static void transfer_complete(struct bt_mesh_blob_cli *cli) in transfer_complete() argument
1126 bool success = targets_active(cli) && in transfer_complete()
1127 cli->state == BT_MESH_BLOB_CLI_STATE_XFER_CHECK; in transfer_complete()
1129 end(cli, success); in transfer_complete()
1136 static void rx_block_status(struct bt_mesh_blob_cli *cli, in rx_block_status() argument
1140 if (cli->state != BT_MESH_BLOB_CLI_STATE_BLOCK_START && in rx_block_status()
1141 cli->state != BT_MESH_BLOB_CLI_STATE_BLOCK_SEND && in rx_block_status()
1142 cli->state != BT_MESH_BLOB_CLI_STATE_BLOCK_CHECK) { in rx_block_status()
1143 LOG_WRN("Invalid state %u", cli->state); in rx_block_status()
1150 target_drop(cli, target, block->status); in rx_block_status()
1151 blob_cli_broadcast_rsp(cli, target); in rx_block_status()
1155 if (block->block.number != cli->block.number) { in rx_block_status()
1156 LOG_DBG("Invalid block num (expected %u)", cli->block.number); in rx_block_status()
1163 if (cli->xfer->mode == BT_MESH_BLOB_XFER_MODE_PULL) { in rx_block_status()
1165 update_missing_chunks(cli); in rx_block_status()
1170 blob_chunk_missing_set_all(&cli->block); in rx_block_status()
1171 } else if (cli->xfer->mode == BT_MESH_BLOB_XFER_MODE_PULL) { in rx_block_status()
1174 LOG_DBG("Missing: %s", bt_hex(target->pull->missing, cli->block.chunk_count)); in rx_block_status()
1176 update_missing_chunks(cli); in rx_block_status()
1184 cli->block.missing[i] |= block->block.missing[i]; in rx_block_status()
1188 if (SENDING_CHUNKS_IN_PULL_MODE(cli)) { in rx_block_status()
1189 if (!cli->tx.sending) { in rx_block_status()
1194 broadcast_complete(cli); in rx_block_status()
1203 blob_cli_broadcast_rsp(cli, target); in rx_block_status()
1209 struct bt_mesh_blob_cli *cli = mod->rt->user_data; in handle_xfer_status() local
1236 if (cli->state != BT_MESH_BLOB_CLI_STATE_START && in handle_xfer_status()
1237 cli->state != BT_MESH_BLOB_CLI_STATE_XFER_CHECK && in handle_xfer_status()
1238 cli->state != BT_MESH_BLOB_CLI_STATE_CANCEL && in handle_xfer_status()
1239 cli->state != BT_MESH_BLOB_CLI_STATE_XFER_PROGRESS_GET) { in handle_xfer_status()
1240 LOG_WRN("Wrong state: %d", cli->state); in handle_xfer_status()
1244 target = target_get(cli, ctx->addr); in handle_xfer_status()
1249 if (cli->state == BT_MESH_BLOB_CLI_STATE_START) { in handle_xfer_status()
1251 } else if (cli->state == BT_MESH_BLOB_CLI_STATE_XFER_CHECK) { in handle_xfer_status()
1253 } else if (cli->state != BT_MESH_BLOB_CLI_STATE_XFER_PROGRESS_GET) { in handle_xfer_status()
1256 blob_cli_broadcast_rsp(cli, target); in handle_xfer_status()
1257 if (cli->cb && cli->cb->xfer_progress) { in handle_xfer_status()
1258 cli->cb->xfer_progress(cli, target, &info); in handle_xfer_status()
1264 target_drop(cli, target, info.status); in handle_xfer_status()
1269 info.id != cli->xfer->id) { in handle_xfer_status()
1270 target_drop(cli, target, BT_MESH_BLOB_ERR_WRONG_BLOB_ID); in handle_xfer_status()
1273 blob_cli_broadcast_rsp(cli, target); in handle_xfer_status()
1281 struct bt_mesh_blob_cli *cli = mod->rt->user_data; in handle_block_report() local
1284 .block.number = cli->block.number, in handle_block_report()
1290 if (!cli->xfer) { in handle_block_report()
1294 if (cli->xfer->mode == BT_MESH_BLOB_XFER_MODE_PUSH) { in handle_block_report()
1301 target = target_get(cli, ctx->addr); in handle_block_report()
1320 if (next_missing_chunk(cli, target->pull->missing, 0) >= cli->block.chunk_count) { in handle_block_report()
1325 cli->tx.cli_timestamp = k_uptime_get() + CLIENT_TIMEOUT_MSEC(cli); in handle_block_report()
1327 rx_block_status(cli, target, &status); in handle_block_report()
1335 struct bt_mesh_blob_cli *cli = mod->rt->user_data; in handle_block_status() local
1343 target = target_get(cli, ctx->addr); in handle_block_status()
1354 DIV_ROUND_UP(cli->block.size, chunk_size); in handle_block_status()
1398 rx_block_status(cli, target, &status); in handle_block_status()
1406 struct bt_mesh_blob_cli *cli = mod->rt->user_data; in handle_info_status() local
1411 if (cli->state != BT_MESH_BLOB_CLI_STATE_CAPS_GET) { in handle_info_status()
1437 target = target_get(cli, ctx->addr); in handle_info_status()
1442 status = caps_adjust(cli, &caps); in handle_info_status()
1444 target_drop(cli, target, status); in handle_info_status()
1447 blob_cli_broadcast_rsp(cli, target); in handle_info_status()
1462 struct bt_mesh_blob_cli *cli = mod->rt->user_data; in blob_cli_init() local
1464 cli->mod = mod; in blob_cli_init()
1466 bt_mesh_blob_cli_set_chunk_interval_ms(cli, CONFIG_BT_MESH_TX_BLOB_CHUNK_SEND_INTERVAL); in blob_cli_init()
1467 cli->tx.cli_timestamp = 0ll; in blob_cli_init()
1468 k_work_init_delayable(&cli->tx.retry, retry_timeout); in blob_cli_init()
1469 k_work_init_delayable(&cli->tx.complete, tx_complete); in blob_cli_init()
1476 struct bt_mesh_blob_cli *cli = mod->rt->user_data; in blob_cli_reset() local
1478 cli_state_reset(cli); in blob_cli_reset()
1487 int bt_mesh_blob_cli_caps_get(struct bt_mesh_blob_cli *cli, in bt_mesh_blob_cli_caps_get() argument
1490 if (bt_mesh_blob_cli_is_busy(cli)) { in bt_mesh_blob_cli_caps_get()
1494 cli->inputs = inputs; in bt_mesh_blob_cli_caps_get()
1496 cli->caps.min_block_size_log = 0x06; in bt_mesh_blob_cli_caps_get()
1497 cli->caps.max_block_size_log = 0x20; in bt_mesh_blob_cli_caps_get()
1498 cli->caps.max_chunks = CONFIG_BT_MESH_BLOB_CHUNK_COUNT_MAX; in bt_mesh_blob_cli_caps_get()
1499 cli->caps.max_chunk_size = BLOB_TX_CHUNK_SIZE; in bt_mesh_blob_cli_caps_get()
1500 cli->caps.max_size = 0xffffffff; in bt_mesh_blob_cli_caps_get()
1501 cli->caps.mtu_size = 0xffff; in bt_mesh_blob_cli_caps_get()
1502 cli->caps.modes = BT_MESH_BLOB_XFER_MODE_ALL; in bt_mesh_blob_cli_caps_get()
1504 if (!targets_reset(cli)) { in bt_mesh_blob_cli_caps_get()
1509 caps_get(cli); in bt_mesh_blob_cli_caps_get()
1514 int bt_mesh_blob_cli_send(struct bt_mesh_blob_cli *cli, in bt_mesh_blob_cli_send() argument
1519 if (bt_mesh_blob_cli_is_busy(cli)) { in bt_mesh_blob_cli_send()
1531 cli->xfer = xfer; in bt_mesh_blob_cli_send()
1532 cli->inputs = inputs; in bt_mesh_blob_cli_send()
1533 cli->io = io; in bt_mesh_blob_cli_send()
1535 if (cli->xfer->block_size_log == 0x20) { in bt_mesh_blob_cli_send()
1536 cli->block_count = 1; in bt_mesh_blob_cli_send()
1538 cli->block_count = DIV_ROUND_UP(cli->xfer->size, (1U << cli->xfer->block_size_log)); in bt_mesh_blob_cli_send()
1541 block_set(cli, 0); in bt_mesh_blob_cli_send()
1543 if (cli->block.chunk_count > CONFIG_BT_MESH_BLOB_CHUNK_COUNT_MAX) { in bt_mesh_blob_cli_send()
1548 if (!targets_reset(cli)) { in bt_mesh_blob_cli_send()
1555 cli->xfer->block_size_log, cli->xfer->chunk_size, in bt_mesh_blob_cli_send()
1556 cli->xfer->size, cli->xfer->mode); in bt_mesh_blob_cli_send()
1558 return xfer_start(cli); in bt_mesh_blob_cli_send()
1561 int bt_mesh_blob_cli_suspend(struct bt_mesh_blob_cli *cli) in bt_mesh_blob_cli_suspend() argument
1563 if (cli->state == BT_MESH_BLOB_CLI_STATE_SUSPENDED) { in bt_mesh_blob_cli_suspend()
1567 if (cli->state != BT_MESH_BLOB_CLI_STATE_BLOCK_START && in bt_mesh_blob_cli_suspend()
1568 cli->state != BT_MESH_BLOB_CLI_STATE_BLOCK_SEND && in bt_mesh_blob_cli_suspend()
1569 cli->state != BT_MESH_BLOB_CLI_STATE_BLOCK_CHECK) { in bt_mesh_blob_cli_suspend()
1570 LOG_WRN("BLOB xfer not started: %d", cli->state); in bt_mesh_blob_cli_suspend()
1574 cli->state = BT_MESH_BLOB_CLI_STATE_SUSPENDED; in bt_mesh_blob_cli_suspend()
1575 (void)k_work_cancel_delayable(&cli->tx.retry); in bt_mesh_blob_cli_suspend()
1576 cli->tx.ctx.is_inited = 0; in bt_mesh_blob_cli_suspend()
1577 cli->tx.sending = 0; in bt_mesh_blob_cli_suspend()
1578 cli->tx.cli_timestamp = 0ll; in bt_mesh_blob_cli_suspend()
1582 int bt_mesh_blob_cli_resume(struct bt_mesh_blob_cli *cli) in bt_mesh_blob_cli_resume() argument
1586 if (cli->state != BT_MESH_BLOB_CLI_STATE_SUSPENDED) { in bt_mesh_blob_cli_resume()
1592 TARGETS_FOR_EACH(cli, target) { in bt_mesh_blob_cli_resume()
1599 if (!targets_reset(cli)) { in bt_mesh_blob_cli_resume()
1604 block_set(cli, 0); in bt_mesh_blob_cli_resume()
1605 return xfer_start(cli); in bt_mesh_blob_cli_resume()
1608 void bt_mesh_blob_cli_cancel(struct bt_mesh_blob_cli *cli) in bt_mesh_blob_cli_cancel() argument
1610 if (!bt_mesh_blob_cli_is_busy(cli)) { in bt_mesh_blob_cli_cancel()
1617 if (cli->state == BT_MESH_BLOB_CLI_STATE_CAPS_GET || in bt_mesh_blob_cli_cancel()
1618 cli->state == BT_MESH_BLOB_CLI_STATE_SUSPENDED) { in bt_mesh_blob_cli_cancel()
1619 cli_state_reset(cli); in bt_mesh_blob_cli_cancel()
1623 cli->tx.cancelled = 1U; in bt_mesh_blob_cli_cancel()
1624 cli->state = BT_MESH_BLOB_CLI_STATE_CANCEL; in bt_mesh_blob_cli_cancel()
1627 int bt_mesh_blob_cli_xfer_progress_get(struct bt_mesh_blob_cli *cli, in bt_mesh_blob_cli_xfer_progress_get() argument
1630 if (bt_mesh_blob_cli_is_busy(cli)) { in bt_mesh_blob_cli_xfer_progress_get()
1634 cli->inputs = inputs; in bt_mesh_blob_cli_xfer_progress_get()
1636 check_transfer(cli); in bt_mesh_blob_cli_xfer_progress_get()
1641 uint8_t bt_mesh_blob_cli_xfer_progress_active_get(struct bt_mesh_blob_cli *cli) in bt_mesh_blob_cli_xfer_progress_active_get() argument
1643 if (cli->state < BT_MESH_BLOB_CLI_STATE_START) { in bt_mesh_blob_cli_xfer_progress_active_get()
1647 return (100U * cli->block.number) / cli->block_count; in bt_mesh_blob_cli_xfer_progress_active_get()
1650 bool bt_mesh_blob_cli_is_busy(struct bt_mesh_blob_cli *cli) in bt_mesh_blob_cli_is_busy() argument
1652 return cli->state != BT_MESH_BLOB_CLI_STATE_NONE; in bt_mesh_blob_cli_is_busy()
1655 void bt_mesh_blob_cli_set_chunk_interval_ms(struct bt_mesh_blob_cli *cli, uint32_t interval_ms) in bt_mesh_blob_cli_set_chunk_interval_ms() argument
1657 cli->chunk_interval_ms = interval_ms; in bt_mesh_blob_cli_set_chunk_interval_ms()