From a1a5cda1825467002641f3f34ea8f4534ebcd897 Mon Sep 17 00:00:00 2001 From: Luo Xu Date: Mon, 9 Feb 2026 17:43:18 +0800 Subject: [PATCH] feat(ble_mesh): refuse to suspend dfu client when the last chunk sent (cherry picked from commit e039b33bb172370f5d7411f79643f1648484e059) Co-authored-by: luoxu --- .../bt/esp_ble_mesh/v1.1/mbt/blob_cli.c | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/components/bt/esp_ble_mesh/v1.1/mbt/blob_cli.c b/components/bt/esp_ble_mesh/v1.1/mbt/blob_cli.c index 985c46b92ac..4e47629f857 100644 --- a/components/bt/esp_ble_mesh/v1.1/mbt/blob_cli.c +++ b/components/bt/esp_ble_mesh/v1.1/mbt/blob_cli.c @@ -1,6 +1,6 @@ /* * SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA - * SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -53,6 +53,7 @@ _Static_assert((BLOB_BLOCK_STATUS_MSG_MAXLEN + BLE_MESH_MODEL_OP_LEN(BT_MESH_BLO NET_BUF_SIMPLE_DEFINE_STATIC(chunk_buf, BLOB_CHUNK_SDU_LEN(CHUNK_SIZE_MAX)); static bool chunk_sending; +static bool last_chunk_sent; struct block_status { enum bt_mesh_blob_status status; @@ -568,7 +569,8 @@ void blob_cli_broadcast_rsp(struct bt_mesh_blob_cli *cli, void blob_cli_broadcast_abort(struct bt_mesh_blob_cli *cli) { - if (!cli->tx.ctx.is_inited) { + if (!cli->tx.ctx.is_inited && + cli->state != BT_MESH_BLOB_CLI_STATE_SUSPENDED) { return; } @@ -711,6 +713,13 @@ static void chunk_tx(struct bt_mesh_blob_cli *cli, uint16_t dst) chunk.offset = cli->xfer->chunk_size * cli->chunk_idx; chunk.data = net_buf_simple_add(&chunk_buf, chunk.size); + if ((cli->block.number == cli->block_count - 1) && + (cli->chunk_idx < cli->block.chunk_count)) { + last_chunk_sent = true; + } else { + last_chunk_sent = false; + } + err = cli->io->rd(cli->io, cli->xfer, &cli->block, &chunk); if (err || cli->state == BT_MESH_BLOB_CLI_STATE_NONE) { bt_mesh_blob_cli_cancel(cli); @@ -1619,6 +1628,16 @@ int bt_mesh_blob_cli_suspend(struct bt_mesh_blob_cli *cli) return -EINVAL; } + /* After the last chunk data is sent, if the server + * successfully receives the chunk, it will be in the + * complete state. At this time, if the client resumes + * from suspend and restarts the transmission, an error + * will occur, resulting in lost target */ + if (last_chunk_sent) { + BT_WARN("About to end, refuse to suspend"); + return -EINVAL; + } + cli->state = BT_MESH_BLOB_CLI_STATE_SUSPENDED; (void)k_work_cancel_delayable(&cli->tx.retry); cli->tx.ctx.is_inited = 0;