Merge branch 'feat/ble_mesh_dfu_supported_v5.5' into 'release/v5.5'

Feat/ble mesh dfu supported v5.5

See merge request espressif/esp-idf!44132
This commit is contained in:
Island
2025-12-29 15:37:35 +08:00
56 changed files with 16517 additions and 306 deletions

View File

@@ -47,6 +47,9 @@ set(ble_mesh_v11_include_dirs
"esp_ble_mesh/v1.1/api/core/include"
"esp_ble_mesh/v1.1/api/models/include"
"esp_ble_mesh/v1.1/btc/include"
"esp_ble_mesh/v1.1/include"
"esp_ble_mesh/v1.1/dfu"
"esp_ble_mesh/v1.1/mbt"
)
if(CONFIG_IDF_DOC_BUILD)
@@ -622,9 +625,13 @@ if(CONFIG_BT_ENABLED)
"esp_ble_mesh/v1.1/api/core/esp_ble_mesh_sar_model_api.c"
"esp_ble_mesh/v1.1/api/core/esp_ble_mesh_srpl_model_api.c"
"esp_ble_mesh/v1.1/api/models/esp_ble_mesh_mbt_model_api.c"
"esp_ble_mesh/v1.1/api/models/esp_ble_mesh_dfu_model_api.c"
"esp_ble_mesh/v1.1/api/models/esp_ble_mesh_dfu_slot_api.c"
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_agg_model.c"
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_brc_model.c"
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_df_model.c"
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_dfu_model.c"
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_dfu_slot.c"
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_lcd_model.c"
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_mbt_model.c"
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_odp_model.c"
@@ -632,6 +639,14 @@ if(CONFIG_BT_ENABLED)
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_rpr_model.c"
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_sar_model.c"
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_srpl_model.c"
"esp_ble_mesh/v1.1/mbt/blob_srv.c"
"esp_ble_mesh/v1.1/mbt/blob_cli.c"
"esp_ble_mesh/v1.1/dfu/dfu_cli.c"
"esp_ble_mesh/v1.1/dfu/dfu_srv.c"
"esp_ble_mesh/v1.1/dfu/dfu_slot.c"
"esp_ble_mesh/v1.1/dfu/dfu_metadata.c"
"esp_ble_mesh/v1.1/dfu/dfd_srv.c"
"esp_ble_mesh/v1.1/dfu/dfd_cli.c"
"esp_ble_mesh/lib/ext.c")
if(CONFIG_BLE_MESH_SAR_ENHANCEMENT)

View File

@@ -89,6 +89,7 @@
#include "btc_ble_mesh_rpr_model.h"
#include "btc_ble_mesh_sar_model.h"
#include "btc_ble_mesh_srpl_model.h"
#include "btc_ble_mesh_dfu_model.h"
#endif /* CONFIG_BLE_MESH_V11_SUPPORT */
#endif /* #if CONFIG_BLE_MESH */
@@ -262,6 +263,12 @@ static const btc_func_t profile_tab[BTC_PID_NUM] = {
#if CONFIG_BLE_MESH_MBT_SRV
[BTC_PID_MBT_SERVER] = {btc_ble_mesh_mbt_server_call_handler, btc_ble_mesh_mbt_server_cb_handler },
#endif /* CONFIG_BLE_MESH_MBT_SRV */
#if CONFIG_BLE_MESH_DFU_CLI
[BTC_PID_DFU_CLIENT] = {btc_ble_mesh_dfu_client_call_handler, btc_ble_mesh_dfu_client_cb_handler},
#endif /* CONFIG_BLE_MESH_DFU_CLI */
#if CONFIG_BLE_MESH_DFD_CLI
[BTC_PID_DFD_CLIENT] = {btc_ble_mesh_dfd_client_call_handler, btc_ble_mesh_dfd_client_cb_handler},
#endif /* CONFIG_BLE_MESH_DFD_CLI */
#if CONFIG_BLE_MESH_BLE_COEX_SUPPORT || CONFIG_BLE_MESH_USE_BLE_50
[BTC_PID_BLE_MESH_BLE_COEX] = {btc_ble_mesh_ble_call_handler, btc_ble_mesh_ble_cb_handler },
#endif /* CONFIG_BLE_MESH_BLE_COEX_SUPPORT || CONFIG_BLE_MESH_USE_BLE_50 */

View File

@@ -106,6 +106,12 @@ typedef enum {
BTC_PID_TIME_SCENE_SERVER,
BTC_PID_MBT_CLIENT,
BTC_PID_MBT_SERVER,
BTC_PID_BLOB_CLIENT,
BTC_PID_BLOB_SERVER,
BTC_PID_DFU_CLIENT,
BTC_PID_DFU_SERVER,
BTC_PID_DFD_CLIENT,
BTC_PID_DFD_SERVER,
BTC_PID_BLE_MESH_BLE_COEX,
#endif /* CONFIG_BLE_MESH */
#if (BLE_FEAT_ISO_EN == TRUE)

View File

@@ -141,7 +141,9 @@
#define LOG_LOCAL_LEVEL_MAPPING LOG_LOCAL_LEVEL
#endif
#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
#define BT_LOG_LEVEL_CHECK(LAYER, LEVEL) (MAX(LAYER##_INITIAL_TRACE_LEVEL, LOG_LOCAL_LEVEL_MAPPING) >= BT_TRACE_LEVEL_##LEVEL)

View File

@@ -1636,11 +1636,13 @@ if BLE_MESH
Enable support for Lighting server models.
config BLE_MESH_MBT_CLI
bool "BLOB Transfer Client model"
bool "BLOB Transfer Client model(Deprecated)"
depends on BLE_MESH_V11_SUPPORT
default n
help
Enable support for BLOB Transfer Client model.
Warn: This version of the Mesh Binary Large Object Transfer Model will be deprecated,
and a new version will be released in the future.
if BLE_MESH_MBT_CLI
@@ -1655,11 +1657,259 @@ if BLE_MESH
endif # BLE_MESH_MBT_CLI
config BLE_MESH_MBT_SRV
bool "BLOB Transfer Server model"
bool "BLOB Transfer Server model(Deprecated)"
depends on BLE_MESH_V11_SUPPORT
default n
help
Enable support for BLOB Transfer Server model.
Warn: This version of the Mesh Binary Large Object Transfer Model will be deprecated,
and a new version will be released in the future.
menu "Binary Larger Object Transfer model"
config BLE_MESH_BLOB_SRV
bool "Support for BLOB Transfer Server model"
depends on BLE_MESH_V11_SUPPORT
help
Enable the Binary Large Object (BLOB) Transfer Server model.
if BLE_MESH_BLOB_SRV
config BLE_MESH_BLOB_SRV_PULL_REQ_COUNT
int "Number of chunks to request for each pull"
default 4
range 1 16
help
In Pull mode (Pull BLOB Transfer Mode), the BLOB Transfer Server
requests a fixed number of chunks from the Client. Use this option to
control the chunk count in the request. If the BLOB Transfer Server
is instantiated on a Low Power node, the pull request count will be
trimmed to not overflow the Friend queue.
config BLE_MESH_BLOB_SIZE_MAX
int "Largest BLOB size in bytes"
default 524288
range 1 3257617792
help
The maximum object size a BLOB Transfer Server can receive.
config BLE_MESH_BLOB_BLOCK_SIZE_MIN
int "Minimum block size"
default 4096
range 64 1048576 # 2^6 - 2^20
help
Minimum acceptable block size in a BLOB transfer. The transfer block
size will be some number that is a power of two, and is between block
size min and block size max. If no such number exists, a compile
time warning will be issued.
config BLE_MESH_BLOB_BLOCK_SIZE_MAX
int "Maximum block size"
default 4096
range BLE_MESH_BLOB_BLOCK_SIZE_MIN 1048576
help
Maximum acceptable block size in a BLOB transfer. The transfer block
size will be some number that is a power of two, and is between block
size min and block size max. If no such number exists, a compile
time warning will be issued.
config BLE_MESH_BLOB_REPORT_TIMEOUT
int "Partial Block Report interval in Pull mode"
default 10
range 1 31
help
The timer value that Pull BLOB Transfer Server uses to report missed chunks.
config BLE_MESH_RX_BLOB_CHUNK_SIZE
depends on !BLE_MESH_ALIGN_CHUNK_SIZE_TO_MAX_SEGMENT
int "BLOB Server chunk size"
default 8
range 8 377
help
Set the chunk size for the BLOB Server.
The actual maximum chunk size depends on how many segments are
possible and will be clamped to the max possible if set above.
see also: BLE_MESH_RX_SEG_MAX,
and the maximum SDU a node can receive.
endif # BLE_MESH_BLOB_SRV
config BLE_MESH_BLOB_CLI
bool "Support for BLOB Transfer Client model"
depends on BLE_MESH_V11_SUPPORT
help
Enable the Binary Large Object (BLOB) Transfer Client model.
if BLE_MESH_BLOB_CLI
config BLE_MESH_BLOB_CLI_BLOCK_RETRIES
int "Number of retries per block"
default 5
help
Controls the number of times the client will attempt to resend missing
chunks to the BLOB receivers for every block.
config BLE_MESH_TX_BLOB_CHUNK_SIZE
depends on !BLE_MESH_ALIGN_CHUNK_SIZE_TO_MAX_SEGMENT
int "BLOB Client chunk size"
default 8
range 1 377
help
Set the chunk size for the BLOB Client.
The actual maximum chunk size depends on how many segments are
possible and will be clamped to the max possible if set above.
see also: BLE_MESH_TX_SEG_MAX,
and the maximum SDU a node can receive.
config BLE_MESH_TX_BLOB_CHUNK_SEND_INTERVAL
int "BLOB Client chunk send interval"
default 0
range 0 2147483647
help
Set the interval in milliseconds in which chunks are sent during the BLOB transfer.
Note: Without a delay between each sent chunk, the network might become too busy with the
BLOB transfer for other communications to succeed.
Note: Timing restrictions, like the timeout base, should be considered or changed
accordingly when setting this interval. Otherwise, the interval might be too big for the
timeout settings and cause timeouts.
endif # BLE_MESH_BLOB_CLI
menu "BLOB models common configuration"
visible if BLE_MESH_BLOB_SRV || BLE_MESH_BLOB_CLI
config BLE_MESH_BLOB_CHUNK_COUNT_MAX
int "Maximum chunk count per block"
default 256
range 1 2992
help
A BLOB transfer contains several blocks. Each block is made up of
several chunks. This option controls the maximum chunk count per
block.
config BLE_MESH_ALIGN_CHUNK_SIZE_TO_MAX_SEGMENT
bool "Align chunk size to max segmented message size"
default y
endmenu #BLOB models common configuration
endmenu # Binary Larger Object Transfer model
menu "Device Firmware Update model"
config BLE_MESH_DFU_SRV
bool "Support for Firmware Update Server model"
depends on BLE_MESH_BLOB_SRV
help
Enable the Firmware Update Server model.
config BLE_MESH_DFU_CLI
bool "Support for Firmware Update Client model"
depends on BLE_MESH_BLOB_CLI
help
Enable the Firmware Update Client model.
menu "Firmware Update model configuration"
visible if BLE_MESH_DFU_SRV || BLE_MESH_DFU_CLI
config BLE_MESH_DFU_FWID_MAXLEN
int "DFU FWID max length"
default 16
range 0 106
help
This value defines the maximum length of an image's firmware ID.
config BLE_MESH_DFU_METADATA_MAXLEN
int "DFU metadata max length"
default 32
range 18 255 if BLE_MESH_DFU_METADATA
range 0 255
help
This value defines the maximum length of an image's metadata.
config BLE_MESH_DFU_METADATA
bool "Support for the default metadata format"
help
This option adds a set of functions that can be used to encode and decode a firmware
metadata using the format defined in the Bluetooth mesh DFU subsystem.
config BLE_MESH_DFU_URI_MAXLEN
int "DFU URI max length"
default 32
range 0 255
help
This value defines the maximum length of an image's URI, not including
a string terminator.
endmenu #Firmware Update model configuration
config BLE_MESH_DFU_SLOTS
bool "Firmware image slot manager"
default y if BLE_MESH_DFU_CLI
help
Enable the DFU image slot manager, for managing firmware distribution slots
for the Firmware Update Client model.
if BLE_MESH_DFU_SLOTS
config BLE_MESH_DFU_SLOT_CNT
int "Number of firmware image slots"
default 1
range 1 32767
help
This value defines the number of firmware slots the DFU image slot manager
can keep simultaneously.
endif #BLE_MESH_DFU_SLOTS
config BLE_MESH_DFD_CLI
bool "Support for Device Distribution Client model"
help
Enable the Device Distribution Client model
config BLE_MESH_DFD_SRV
bool "Support for Firmware Distribution Server model"
depends on BLE_MESH_BLOB_SRV
depends on BLE_MESH_DFU_CLI
help
Enable the Firmware Distribution Server model.
if BLE_MESH_DFD_SRV
config BLE_MESH_DFD_SRV_SLOT_MAX_SIZE
int "Largest DFU image that can be stored"
default BLE_MESH_BLOB_SIZE_MAX
range 0 BLE_MESH_BLOB_SIZE_MAX
help
This value defines the largest DFU image a single slot can store.
config BLE_MESH_DFD_SRV_SLOT_SPACE
int "Total DFU image storage space"
default BLE_MESH_DFD_SRV_SLOT_MAX_SIZE
range 0 4294967295
help
This value defines the total storage space dedicated to storing DFU
images on the Firmware Distribution Server.
config BLE_MESH_DFD_SRV_TARGETS_MAX
int "Maximum Target node count"
default 8
range 1 65535
help
This value defines the maximum number of Target nodes the Firmware
Distribution Server can target simultaneously.
config BLE_MESH_DFD_SRV_OOB_UPLOAD
bool "Support for DFU image OOB upload"
help
This enables support for OOB upload of firmware images for
distribution. This makes several callbacks and use of the init
macro BLE_MESH_DFD_SRV_INIT_OOB mandatory. See the API documentation
for bt_mesh_dfd_srv_cb for details about the mandatory callbacks.
endif #BLE_MESH_DFD_SRV
endmenu # Device Firmware Update model
endmenu #Support for BLE Mesh Client/Server models

View File

@@ -1982,9 +1982,14 @@ typedef union {
#define ESP_BLE_MESH_MODEL_ID_LIGHT_LC_SRV 0x130f
#define ESP_BLE_MESH_MODEL_ID_LIGHT_LC_SETUP_SRV 0x1310
#define ESP_BLE_MESH_MODEL_ID_LIGHT_LC_CLI 0x1311
#define ESP_BLE_MESH_MODEL_ID_MBT_SRV 0x1400
#define ESP_BLE_MESH_MODEL_ID_MBT_CLI 0x1401
#define ESP_BLE_MESH_MODEL_ID_MBT_SRV 0x14fe
#define ESP_BLE_MESH_MODEL_ID_MBT_CLI 0x14ff
#define ESP_BLE_MESH_MODEL_ID_BLOB_SRV 0x1400
#define ESP_BLE_MESH_MODEL_ID_BLOB_CLI 0x1401
#define ESP_BLE_MESH_MODEL_ID_DFU_SRV 0x1402
#define ESP_BLE_MESH_MODEL_ID_DFU_CLI 0x1403
#define ESP_BLE_MESH_MODEL_ID_DFD_SRV 0x1404
#define ESP_BLE_MESH_MODEL_ID_DFD_CLI 0x1405
/**
* esp_ble_mesh_opcode_config_client_get_t belongs to esp_ble_mesh_opcode_t, this typedef is only
* used to locate the opcodes used by esp_ble_mesh_config_client_get_state.

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -1410,6 +1410,31 @@ typedef bt_mesh_client_user_data_t bt_mesh_mbt_client_t;
extern const struct bt_mesh_model_op bt_mesh_mbt_cli_op[];
extern const struct bt_mesh_model_cb bt_mesh_mbt_cli_cb;
#endif /* CONFIG_BLE_MESH_MBT_CLI */
#if CONFIG_BLE_MESH_BLOB_SRV
extern const struct bt_mesh_model_op _bt_mesh_blob_srv_op[];
extern const struct bt_mesh_model_cb _bt_mesh_blob_srv_cb;
#endif /* CONFIG_BLE_MESH_BLOB_SRV */
#if CONFIG_BLE_MESH_BLOB_CLI
typedef bt_mesh_client_user_data_t bt_mesh_blob_client_t;
extern const struct bt_mesh_model_op _bt_mesh_blob_cli_op[];
extern const struct bt_mesh_model_cb _bt_mesh_blob_cli_cb;
#endif /* CONFIG_BLE_MESH_BLOB_CLI */
#if CONFIG_BLE_MESH_DFU_SRV
extern const struct bt_mesh_model_op _bt_mesh_dfu_srv_op[];
extern const struct bt_mesh_model_cb _bt_mesh_dfu_srv_cb;
#endif /* CONFIG_BLE_MESH_DFU_SRV */
#if CONFIG_BLE_MESH_DFU_CLI
extern const struct bt_mesh_model_op _bt_mesh_dfu_cli_op[];
extern const struct bt_mesh_model_cb _bt_mesh_dfu_cli_cb;
#endif /* CONFIG_BLE_MESH_DFU_CLI */
#if CONFIG_BLE_MESH_DFD_SRV
extern const struct bt_mesh_model_op _bt_mesh_dfd_srv_op[];
extern const struct bt_mesh_model_cb _bt_mesh_dfd_srv_cb;
#endif /* CONFIG_BLE_MESH_DFD_SRV */
#if CONFIG_BLE_MESH_DFD_CLI
extern const struct bt_mesh_model_op _bt_mesh_dfd_cli_op[];
extern const struct bt_mesh_model_cb _bt_mesh_dfd_cli_cb;
#endif /* CONFIG_BLE_MESH_DFD_CLI */
static void btc_ble_mesh_model_op_set(esp_ble_mesh_model_t *model)
{
@@ -2205,9 +2230,9 @@ static void btc_ble_mesh_model_op_set(esp_ble_mesh_model_t *model)
case BLE_MESH_MODEL_ID_MBT_CLI:
model->op = (esp_ble_mesh_model_op_t *)bt_mesh_mbt_cli_op;
model->cb = (esp_ble_mesh_model_cbs_t *)&bt_mesh_mbt_cli_cb;
bt_mesh_mbt_client_t *cli = (bt_mesh_mbt_client_t *)model->user_data;
if (cli) {
cli->publish_status = btc_ble_mesh_mbt_client_publish_callback;
bt_mesh_mbt_client_t *mbt_cli = (bt_mesh_mbt_client_t *)model->user_data;
if (mbt_cli) {
mbt_cli->publish_status = btc_ble_mesh_mbt_client_publish_callback;
}
break;
#endif /* CONFIG_BLE_MESH_MBT_CLI */
@@ -2220,6 +2245,61 @@ static void btc_ble_mesh_model_op_set(esp_ble_mesh_model_t *model)
}
break;
#endif /* CONFIG_BLE_MESH_MBT_SRV */
#if CONFIG_BLE_MESH_BLOB_CLI
case BLE_MESH_MODEL_ID_BLOB_CLI:
model->op = (esp_ble_mesh_model_op_t *)_bt_mesh_blob_cli_op;
model->cb = (esp_ble_mesh_model_cbs_t *)&_bt_mesh_blob_cli_cb;
bt_mesh_blob_client_t *blob_cli = (bt_mesh_blob_client_t *)model->user_data;
if (blob_cli) {
/* TBD: do we need publish callback for Blob Transfer Client model? */
}
break;
#endif /* CONFIG_BLE_MESH_BLOB_CLI */
#if CONFIG_BLE_MESH_BLOB_SRV
case BLE_MESH_MODEL_ID_BLOB_SRV:
model->op = (esp_ble_mesh_model_op_t *)_bt_mesh_blob_srv_op;
model->cb = (esp_ble_mesh_model_cbs_t *)&_bt_mesh_blob_srv_cb;
if (model->pub) {
model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update;
}
break;
#endif /* CONFIG_BLE_MESH_BLOB_SRV */
#if CONFIG_BLE_MESH_DFU_CLI
case BLE_MESH_MODEL_ID_DFU_CLI:
model->op = (esp_ble_mesh_model_op_t *)_bt_mesh_dfu_cli_op;
model->cb = (esp_ble_mesh_model_cbs_t *)&_bt_mesh_dfu_cli_cb;
if (model->pub) {
model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update;
}
break;
#endif /* CONFIG_BLE_MESH_DFU_CLI */
#if CONFIG_BLE_MESH_DFU_SRV
case BLE_MESH_MODEL_ID_DFU_SRV:
model->op = (esp_ble_mesh_model_op_t *)_bt_mesh_dfu_srv_op;
model->cb = (esp_ble_mesh_model_cbs_t *)&_bt_mesh_dfu_srv_cb;
if (model->pub) {
model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update;
}
break;
#endif /* CONFIG_BLE_MESH_DFU_SRV */
#if CONFIG_BLE_MESH_DFD_SRV
case BLE_MESH_MODEL_ID_DFD_SRV:
model->op = (esp_ble_mesh_model_op_t *)_bt_mesh_dfd_srv_op;
model->cb = (esp_ble_mesh_model_cbs_t *)&_bt_mesh_dfd_srv_cb;
if (model->pub) {
model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update;
}
break;
#endif /* CONFIG_BLE_MESH_DFD_SRV */
#if CONFIG_BLE_MESH_DFD_CLI
case BLE_MESH_MODEL_ID_DFD_CLI:
model->op = (esp_ble_mesh_model_op_t *)_bt_mesh_dfd_cli_op;
model->cb = (esp_ble_mesh_model_cbs_t *)&_bt_mesh_dfd_cli_cb;
if (model->pub) {
model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update;
}
break;
#endif /* CONFIG_BLE_MESH_DFD_SRV */
default:
goto set_vnd_op;
}

View File

@@ -17,6 +17,45 @@
extern "C" {
#endif
static inline void btc_ble_mesh_msg_ctx_copy(struct bt_mesh_msg_ctx *dst,
const struct bt_mesh_msg_ctx *src,
bool use_dev_key)
{
if (dst == NULL ||
src == NULL) {
return;
}
dst->net_idx = src->net_idx;
dst->app_idx = use_dev_key ? BLE_MESH_KEY_DEV : src->app_idx;
dst->addr = src->addr;
dst->send_szmic = src->send_szmic;
dst->send_ttl = src->send_ttl;
dst->send_cred = src->send_cred;
dst->send_tag = src->send_tag;
if (src->enh.adv_cfg_used) {
dst->enh.adv_cfg_used = src->enh.adv_cfg_used;
dst->enh.adv_cfg.adv_cnt = src->enh.adv_cfg.adv_cnt;
dst->enh.adv_cfg.adv_itvl = src->enh.adv_cfg.adv_itvl;
dst->enh.adv_cfg.channel_map = src->enh.adv_cfg.channel_map;
}
#if CONFIG_BLE_MESH_EXT_ADV
if (src->enh.ext_adv_cfg_used) {
dst->enh.ext_adv_cfg_used = src->enh.ext_adv_cfg_used;
dst->enh.ext_adv_cfg.primary_phy = src->enh.ext_adv_cfg.primary_phy;
dst->enh.ext_adv_cfg.secondary_phy = src->enh.ext_adv_cfg.secondary_phy;
dst->enh.ext_adv_cfg.include_tx_power = src->enh.ext_adv_cfg.include_tx_power;
dst->enh.ext_adv_cfg.tx_power = src->enh.ext_adv_cfg.tx_power;
}
#if CONFIG_BLE_MESH_LONG_PACKET
if (src->enh.long_pkt_cfg_used) {
dst->enh.long_pkt_cfg_used = src->enh.long_pkt_cfg_used;
dst->enh.long_pkt_cfg = src->enh.long_pkt_cfg;
}
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
#endif /* CONFIG_BLE_MESH_EXT_ADV */
}
static inline void btc_ble_mesh_set_client_common_param(esp_ble_mesh_client_common_param_t *input,
bt_mesh_client_common_param_t *output,
bool use_dev_key)
@@ -24,35 +63,8 @@ static inline void btc_ble_mesh_set_client_common_param(esp_ble_mesh_client_comm
if (input && output) {
output->opcode = input->opcode;
output->model = (struct bt_mesh_model *)input->model;
output->ctx.net_idx = input->ctx.net_idx;
output->ctx.app_idx = use_dev_key ? BLE_MESH_KEY_DEV : input->ctx.app_idx;
output->ctx.addr = input->ctx.addr;
output->ctx.send_szmic = input->ctx.send_szmic;
output->ctx.send_ttl = input->ctx.send_ttl;
output->ctx.send_cred = input->ctx.send_cred;
output->ctx.send_tag = input->ctx.send_tag;
output->msg_timeout = input->msg_timeout;
if (input->ctx.enh.adv_cfg_used) {
output->ctx.enh.adv_cfg_used = input->ctx.enh.adv_cfg_used;
output->ctx.enh.adv_cfg.adv_cnt = input->ctx.enh.adv_cfg.adv_cnt;
output->ctx.enh.adv_cfg.adv_itvl = input->ctx.enh.adv_cfg.adv_itvl;
output->ctx.enh.adv_cfg.channel_map = input->ctx.enh.adv_cfg.channel_map;
}
#if CONFIG_BLE_MESH_EXT_ADV
if (input->ctx.enh.ext_adv_cfg_used) {
output->ctx.enh.ext_adv_cfg_used = input->ctx.enh.ext_adv_cfg_used;
output->ctx.enh.ext_adv_cfg.primary_phy = input->ctx.enh.ext_adv_cfg.primary_phy;
output->ctx.enh.ext_adv_cfg.secondary_phy = input->ctx.enh.ext_adv_cfg.secondary_phy;
output->ctx.enh.ext_adv_cfg.include_tx_power = input->ctx.enh.ext_adv_cfg.include_tx_power;
output->ctx.enh.ext_adv_cfg.tx_power = input->ctx.enh.ext_adv_cfg.tx_power;
}
#if CONFIG_BLE_MESH_LONG_PACKET
if (input->ctx.enh.long_pkt_cfg_used) {
output->ctx.enh.long_pkt_cfg_used = input->ctx.enh.long_pkt_cfg_used;
output->ctx.enh.long_pkt_cfg = input->ctx.enh.long_pkt_cfg;
}
#endif
#endif
btc_ble_mesh_msg_ctx_copy(&output->ctx, (const struct bt_mesh_msg_ctx *)&input->ctx, use_dev_key);
}
}

View File

@@ -37,7 +37,7 @@ extern "C" {
#endif
#endif
#define BLE_MESH_ADV_TASK_STACK_SIZE 3072
#define BLE_MESH_ADV_TASK_STACK_SIZE (3072)
#define BLE_MESH_ADV_TASK_NAME "mesh_adv_task"
#define BLE_MESH_ADV_TASK_PRIO (configMAX_PRIORITIES - 5)

View File

@@ -1,6 +1,6 @@
/*
* SPDX-FileCopyrightText: 2016 Wind River Systems, Inc.
* SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -49,6 +49,8 @@ struct k_work;
*/
typedef void (*k_work_handler_t)(struct k_work *work);
typedef int32_t k_timeout_t;
struct k_work {
k_work_handler_t handler;
int index;
@@ -141,6 +143,65 @@ struct k_work {
*/
#define K_FOREVER (-1)
/**
* @brief Define for delayable work type.
*
* This macro maps the Zephyr delayable work type `k_work_delayable`
* to the ESP-IDF type `k_delayed_work`.
*/
#define k_work_delayable k_delayed_work
/**
* @brief Reschedule a delayable work item.
*
* This macro maps to `k_delayed_work_submit`, which cancels
* any existing pending submission of the work item and reschedules
* it with the new timeout delay.
*
* @param work Pointer to delayable work item.
* @param delay Timeout delay value.
* @return See implementation of `k_delayed_work_submit`.
*/
#define k_work_reschedule k_delayed_work_submit
/**
* @brief Schedule a delayable work item.
*
* This macro maps to `k_delayed_work_submit`,
* which schedules a work item to be processed
* after the specified timeout delay. If the work
* is already pending, the new delay is applied.
*
* @param work Pointer to delayable work item.
* @param delay Timeout delay value.
* @return See implementation of `k_delayed_work_submit`.
*/
#define k_work_schedule k_delayed_work_submit
/**
* @brief Cancel a delayable work item.
*
* This macro maps to `k_delayed_work_cancel`,
* which cancels a pending work submission
* associated with a delayable work item.
*
* @param work Pointer to delayable work item.
* @return See implementation of `k_delayed_work_cancel`.
*/
#define k_work_cancel_delayable k_delayed_work_cancel
/**
* @brief Initialize a delayable work item.
*
* This macro maps to `k_delayed_work_init`,
* which initializes a delayable work item with
* the provided handler function.
*
* @param work Pointer to delayable work item.
* @param handler Work item handler function.
*/
#define k_work_init_delayable k_delayed_work_init
/**
* @brief Get system uptime (32-bit version).
*
@@ -160,6 +221,27 @@ struct k_delayed_work {
struct k_work work;
};
#define _K_DELAYABLE_WORK_INITIALIZER(work_handler) { \
.work = { \
.handler = work_handler, \
}, \
}
/**
* @brief Convert a work item to its containing delayable work structure.
*
* This function uses container_of to derive the address of the containing
* k_work_delayable structure from the address of the embedded k_work structure.
*
* @param work Pointer to the embedded k_work structure within a k_work_delayable.
* @return Pointer to the containing k_work_delayable structure.
*/
static inline struct k_work_delayable *
k_work_delayable_from_work(struct k_work *work)
{
return CONTAINER_OF(work, struct k_work_delayable, work);
}
/**
* @brief Submit a delayed work item to the system workqueue.
*
@@ -209,6 +291,21 @@ int k_delayed_work_submit_periodic(struct k_delayed_work *work, int32_t period);
*/
int32_t k_delayed_work_remaining_get(struct k_delayed_work *work);
/**
* @brief Check if a delayable work item is pending execution.
*
* This function checks whether a delayable work item has been scheduled
* and is waiting to be processed. It returns true if the work item is in
* pending state (waiting for timeout expiration or being in work queue).
*
* @param dwork Pointer to delayable work item.
* @return true if work is pending, false otherwise.
*/
static inline bool k_work_delayable_is_pending(struct k_work_delayable *dwork)
{
return k_delayed_work_remaining_get(dwork);
}
/**
* @brief Submit a work item to the system workqueue.
*
@@ -267,10 +364,45 @@ int k_delayed_work_init(struct k_delayed_work *work, k_work_handler_t handler);
* @return Current uptime.
*/
int64_t k_uptime_get(void);
int64_t k_uptime_delta(int64_t *reftime);
void bt_mesh_timer_init(void);
void bt_mesh_timer_deinit(void);
/**
* @brief Initialize a statically-defined work item.
*
* This macro can be used to initialize a statically-defined workqueue work
* item, prior to its first use. For example,
*
* @code static K_WORK_DEFINE(<work>, <work_handler>); @endcode
*
* @param work Symbol name for work item object
* @param work_handler Function to invoke each time work item is processed.
*/
#define K_WORK_DEFINE(work, work_handler) \
struct k_work work = _K_WORK_INITIALIZER(work_handler)
/**
* @brief Initialize a statically-defined delayable work item.
*
* This macro can be used to initialize a statically-defined delayable
* work item, prior to its first use. For example,
*
* @code static K_WORK_DELAYABLE_DEFINE(<dwork>, <work_handler>); @endcode
*
* Note that if the runtime dependencies support initialization with
* k_work_init_delayable() using that will eliminate the initialized
* object in ROM that is produced by this macro and copied in at
* system startup.
*
* @param work Symbol name for delayable work item object
* @param work_handler Function to invoke each time work item is processed.
*/
#define K_WORK_DELAYABLE_DEFINE(work, work_handler) \
struct k_delayed_work work \
= _K_DELAYABLE_WORK_INITIALIZER(work_handler)
#ifdef __cplusplus
}
#endif

View File

@@ -15,6 +15,8 @@
#define _BLE_MESH_UTILS_H_
#include <stddef.h>
#include <sys/cdefs.h>
#include <errno.h>
#include "esp_bit_defs.h"
#include "mesh/types.h"
#include "utils_loops.h"
@@ -94,6 +96,81 @@ extern "C" {
#define WB_DN(x) ROUND_DOWN(x, sizeof(void *))
#endif
/**
* @brief Whether @p ptr is an element of @p array
*
* This macro can be seen as a slightly stricter version of @ref PART_OF_ARRAY
* in that it also ensures that @p ptr is aligned to an array-element boundary
* of @p array.
*
* In C, passing a pointer as @p array causes a compile error.
*
* @param array the array in question
* @param ptr the pointer to check
*
* @return 1 if @p ptr is part of @p array, 0 otherwise
*/
#define IS_ARRAY_ELEMENT(array, ptr) \
((ptr) && POINTER_TO_UINT(array) <= POINTER_TO_UINT(ptr) && \
POINTER_TO_UINT(ptr) < POINTER_TO_UINT(&(array)[ARRAY_SIZE(array)]) && \
(POINTER_TO_UINT(ptr) - POINTER_TO_UINT(array)) % sizeof((array)[0]) == 0)
/**
* @brief Index of @p ptr within @p array
*
* With `CONFIG_ASSERT=y`, this macro will trigger a runtime assertion
* when @p ptr does not fall into the range of @p array or when @p ptr
* is not aligned to an array-element boundary of @p array.
*
* In C, passing a pointer as @p array causes a compile error.
*
* @param array the array in question
* @param ptr pointer to an element of @p array
*
* @return the array index of @p ptr within @p array, on success
*/
#define ARRAY_INDEX(array, ptr) \
({ \
__ASSERT_NO_MSG(IS_ARRAY_ELEMENT(array, ptr)); \
(__typeof__((array)[0]) *)(ptr) - (array); \
})
/**
* @brief Divide and round up.
*
* Example:
* @code{.c}
* DIV_ROUND_UP(1, 2); // 1
* DIV_ROUND_UP(3, 2); // 2
* @endcode
*
* @param n Numerator.
* @param d Denominator.
*
* @return The result of @p n / @p d, rounded up.
*/
#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
/**
* @brief Divide and round to the nearest integer.
*
* Example:
* @code{.c}
* DIV_ROUND_CLOSEST(5, 2); // 3
* DIV_ROUND_CLOSEST(5, -2); // -3
* DIV_ROUND_CLOSEST(5, 3); // 2
* @endcode
*
* @param n Numerator.
* @param d Denominator.
*
* @return The result of @p n / @p d, rounded to the nearest integer.
*/
#define DIV_ROUND_CLOSEST(n, d) \
((((n) < 0) ^ ((d) < 0)) ? ((n) - ((d) / 2)) / (d) : \
((n) + ((d) / 2)) / (d))
#ifndef ceiling_fraction
#define ceiling_fraction(numerator, divider) \
(((numerator) + ((divider) - 1)) / (divider))
@@ -125,6 +202,21 @@ extern "C" {
#define BIT(n) (1UL << (n))
#endif
/**
* @brief Set or clear a bit depending on a boolean value
*
* The argument @p var is a variable whose value is written to as a
* side effect.
*
* @param var Variable to be altered
* @param bit Bit number
* @param set if 0, clears @p bit in @p var; any other value sets @p bit
*/
#ifndef WRITE_BIT
#define WRITE_BIT(var, bit, set) \
((var) = (set) ? ((var) | BIT(bit)) : ((var) & ~BIT(bit)))
#endif
#ifndef BIT_MASK
#define BIT_MASK(n) (BIT(n) - 1)
#endif
@@ -219,6 +311,20 @@ const char *bt_hex(const void *buf, size_t len);
void mem_rcopy(uint8_t *dst, uint8_t const *src, uint16_t len);
/**
* @brief Checks if a value is within range.
*
* @note @p val is evaluated twice.
*
* @param val Value to be checked.
* @param min Lower bound (inclusive).
* @param max Upper bound (inclusive).
*
* @retval true If value is within range
* @retval false If the value is not within range
*/
#define IN_RANGE(val, min, max) ((val) >= (min) && (val) <= (max))
#ifdef __cplusplus
}
#endif

View File

@@ -1,7 +1,7 @@
/*
* SPDX-FileCopyrightText: 2016 Intel Corporation
* SPDX-FileCopyrightText: 2016 Wind River Systems, Inc.
* SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -43,6 +43,28 @@ uint32_t k_uptime_get_32(void)
return (uint32_t)(esp_timer_get_time() / 1000);
}
/**
* @brief Get elapsed time.
*
* This routine computes the elapsed time between the current system uptime
* and an earlier reference time, in milliseconds.
*
* @param reftime Pointer to a reference time, which is updated to the current
* uptime upon return.
*
* @return Elapsed time.
*/
int64_t k_uptime_delta(int64_t *reftime)
{
int64_t uptime, delta;
uptime = k_uptime_get();
delta = uptime - *reftime;
*reftime = uptime;
return delta;
}
void bt_mesh_timer_init(void)
{
bm_alarm_hash_map = hash_map_new(BLE_MESH_ALARM_HASH_MAP_SIZE,

View File

@@ -37,7 +37,7 @@
extern const struct bt_mesh_comp *comp_0;
static uint16_t dev_primary_addr;
static int model_send(struct bt_mesh_model *model,
static int model_send(const struct bt_mesh_model *model,
struct bt_mesh_net_tx *tx, bool implicit_bind,
struct net_buf_simple *msg,
const struct bt_mesh_send_cb *cb, void *cb_data);
@@ -331,7 +331,7 @@ static void mod_publish(struct k_work *work)
}
}
struct bt_mesh_elem *bt_mesh_model_elem(struct bt_mesh_model *mod)
struct bt_mesh_elem *bt_mesh_model_elem(const struct bt_mesh_model *mod)
{
BT_DBG("ModelElem, ElemIdx %u", mod->elem_idx);
@@ -605,6 +605,25 @@ struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr)
return NULL;
}
bool bt_mesh_has_addr(uint16_t addr)
{
uint16_t index;
if (BLE_MESH_ADDR_IS_UNICAST(addr)) {
return bt_mesh_elem_find(addr) != NULL;
}
for (index = 0; index < comp_0->elem_count; index++) {
struct bt_mesh_elem *elem = &comp_0->elem[index];
if (bt_mesh_elem_find_group(elem, addr)) {
return true;
}
}
return false;
}
uint8_t bt_mesh_elem_count(void)
{
BT_DBG("ElemCount %u", comp_0->elem_count);
@@ -612,7 +631,7 @@ uint8_t bt_mesh_elem_count(void)
return comp_0->elem_count;
}
static bool model_has_key(struct bt_mesh_model *mod, uint16_t key)
static bool model_has_key(const struct bt_mesh_model *mod, uint16_t key)
{
int i;
@@ -702,7 +721,7 @@ static int get_opcode(struct net_buf_simple *buf, uint32_t *opcode, bool pull_bu
if (pull_buf) {
*opcode = net_buf_simple_pull_u8(buf) << 16;
/* Using LE for the CID since the model layer is defined as
* little-endian in the mesh spec and using BT_MESH_MODEL_OP_3
* little-endian in the mesh spec and using BLE_MESH_MODEL_OP_3
* will declare the opcode in this way.
*/
*opcode |= net_buf_simple_pull_le16(buf);
@@ -871,7 +890,7 @@ void bt_mesh_model_msg_init(struct net_buf_simple *msg, uint32_t opcode)
case 3:
net_buf_simple_add_u8(msg, ((opcode >> 16) & 0xff));
/* Using LE for the CID since the model layer is defined as
* little-endian in the mesh spec and using BT_MESH_MODEL_OP_3
* little-endian in the mesh spec and using BLE_MESH_MODEL_OP_3
* will declare the opcode in this way.
*/
net_buf_simple_add_le16(msg, opcode & 0xffff);
@@ -1043,7 +1062,7 @@ void bt_mesh_choose_better_security_cred(struct bt_mesh_net_tx *tx)
}
#endif /* !CONFIG_BLE_MESH_V11_SUPPORT */
static int model_send(struct bt_mesh_model *model,
static int model_send(const struct bt_mesh_model *model,
struct bt_mesh_net_tx *tx, bool implicit_bind,
struct net_buf_simple *msg,
const struct bt_mesh_send_cb *cb, void *cb_data)
@@ -1136,7 +1155,7 @@ int bt_mesh_model_send_implicit(struct bt_mesh_model *model,
return model_send(model, &tx, implicit_bind, msg, cb, cb_data);
}
int bt_mesh_model_send(struct bt_mesh_model *model,
int bt_mesh_model_send(const struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *msg,
const struct bt_mesh_send_cb *cb, void *cb_data)

View File

@@ -29,6 +29,8 @@ uint8_t bt_mesh_elem_count(void);
/* Find local element based on unicast or group address */
struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr);
bool bt_mesh_has_addr(uint16_t addr);
uint16_t *bt_mesh_model_find_group(struct bt_mesh_model *mod, uint16_t addr);
int bt_mesh_get_opcode(struct net_buf_simple *buf,

View File

@@ -14,6 +14,7 @@
#include "mesh/config.h"
#include "mesh/buf.h"
#include "mesh/timer.h"
#include "sys/types.h"
/**
* @brief Bluetooth Mesh Access Layer
@@ -151,8 +152,15 @@ struct bt_mesh_elem {
#define BLE_MESH_MODEL_ID_LIGHT_LC_SRV 0x130f
#define BLE_MESH_MODEL_ID_LIGHT_LC_SETUP_SRV 0x1310
#define BLE_MESH_MODEL_ID_LIGHT_LC_CLI 0x1311
#define BLE_MESH_MODEL_ID_MBT_SRV 0x1400
#define BLE_MESH_MODEL_ID_MBT_CLI 0x1401
#define BLE_MESH_MODEL_ID_BLOB_SRV 0x1400
#define BLE_MESH_MODEL_ID_BLOB_CLI 0x1401
#define BLE_MESH_MODEL_ID_DFU_SRV 0x1402
#define BLE_MESH_MODEL_ID_DFU_CLI 0x1403
#define BLE_MESH_MODEL_ID_DFD_SRV 0x1404
#define BLE_MESH_MODEL_ID_DFD_CLI 0x1405
#define BLE_MESH_MODEL_ID_MBT_SRV BLE_MESH_MODEL_ID_BLOB_SRV
#define BLE_MESH_MODEL_ID_MBT_CLI BLE_MESH_MODEL_ID_BLOB_CLI
typedef struct {
uint32_t adv_itvl;
@@ -520,6 +528,8 @@ struct bt_mesh_model_pub {
.update = _update, \
}
typedef ssize_t (*settings_read_cb)(void *cb_arg, void *data, size_t len);
/** Model callback functions. */
struct bt_mesh_model_cb {
/** @brief Model init callback.
@@ -613,7 +623,7 @@ void bt_mesh_model_msg_init(struct net_buf_simple *msg, uint32_t opcode);
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_model_send(struct bt_mesh_model *model,
int bt_mesh_model_send(const struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *msg,
const struct bt_mesh_send_cb *cb,
@@ -642,7 +652,7 @@ int bt_mesh_model_publish(struct bt_mesh_model *model);
*
* @return Pointer to the element that the given model belongs to.
*/
struct bt_mesh_elem *bt_mesh_model_elem(struct bt_mesh_model *mod);
struct bt_mesh_elem *bt_mesh_model_elem(const struct bt_mesh_model *mod);
/** @brief Find a SIG model.
*

View File

@@ -1,6 +1,6 @@
/*
* SPDX-FileCopyrightText: 2018 Intel Corporation
* SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -45,10 +45,12 @@
* key: "mesh/s/xxxx/b" -> write/read to set/get SIG MODEL Bind AppKey List
* key: "mesh/s/xxxx/s" -> write/read to set/get SIG MODEL Subscription List
* key: "mesh/s/xxxx/p" -> write/read to set/get SIG MODEL Publication
* key: "mesh/s/xxxx/d" -> write/read to set/get SIG MODEL Data
* key: "mesh/vnd" -> write/read to set/get all VENDOR MODEL model_keys.
* key: "mesh/v/xxxx/b" -> write/read to set/get VENDOR MODEL Bind AppKey List
* key: "mesh/v/xxxx/s" -> write/read to set/get VENDOR MODEL Subscription List
* key: "mesh/v/xxxx/p" -> write/read to set/get VENDOR MODEL Publication
* key: "mesh/v/xxxx/d" -> write/read to set/get VENDOR MODEL Data
* key: "mesh/vaddr" -> write/read to set/get all virtual addresses
* key: "mesh/va/xxxx" -> write/read to set/get the "xxxx" virtual address
* key: "mesh/dkca" -> write/read to set/get Device Key Candidate
@@ -2937,3 +2939,40 @@ void bt_mesh_settings_reset(bool erase)
}
#endif /* CONFIG_BLE_MESH_SETTINGS */
#define SETTINGS_MAX_DIR_DEPTH 8
int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd,
const char *name, const void *data,
size_t data_len)
{
int err = 0;
char path[30] = {'\0'};
uint16_t model_key = 0U;
model_key = BLE_MESH_GET_MODEL_KEY(mod->elem_idx, mod->model_idx);
sprintf(path, "mesh/%s/%04x/d", vnd ? "v" : "s", model_key);
if (name) {
strcat(path, "/");
strncat(path, name, SETTINGS_MAX_DIR_DEPTH);
}
if (data_len) {
err = bt_mesh_save_core_settings(path, data, data_len);
if (err) {
BT_ERR("Failed to store %s", path);
return err;
}
err = bt_mesh_add_core_settings_item(vnd ? "mesh/vnd" : "mesh/sig", model_key);
if (err) {
BT_ERR("Failed to add model data to %s, model_key 0x%04x",
vnd ? "mesh/vnd" : "mesh/sig", model_key);
}
} else {
bt_mesh_erase_core_settings(path);
bt_mesh_remove_core_settings_item(vnd ? "mesh/vnd" : "mesh/sig", model_key);
}
return err;
}

View File

@@ -35,6 +35,10 @@ void bt_mesh_store_mod_sub(struct bt_mesh_model *mod);
void bt_mesh_store_mod_pub(struct bt_mesh_model *mod);
void bt_mesh_store_label(void);
int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd,
const char *name, const void *data,
size_t data_len);
void bt_mesh_clear_role(void);
void bt_mesh_clear_net(void);
void bt_mesh_clear_subnet(struct bt_mesh_subnet *sub);

View File

@@ -11,6 +11,7 @@
#define _TRANSPORT_H_
#include "net.h"
#include "access.h"
#ifdef __cplusplus
extern "C" {

View File

@@ -0,0 +1,249 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include "btc/btc_manage.h"
#include "btc_ble_mesh_dfu_model.h"
#include "esp_ble_mesh_dfu_model_api.h"
#if CONFIG_BLE_MESH_DFU_CLI
static bool is_get_param_needed(esp_ble_mesh_opcode_t opcode)
{
switch (opcode) {
case ESP_BLE_MESH_DFU_OP_UPDATE_INFO_GET:
case ESP_BLE_MESH_DFU_OP_UPDATE_METADATA_CHECK:
case ESP_BLE_MESH_DFU_OP_UPDATE_START:
return true;
default:
return false;
}
}
esp_err_t esp_ble_mesh_dfu_client_get_state(esp_ble_mesh_client_common_param_t *params,
esp_ble_mesh_dfu_client_get_t *get)
{
btc_ble_mesh_dfu_client_args_t arg = {0};
btc_msg_t msg = {0};
if (params == NULL || params->model == NULL ||
params->ctx.net_idx == ESP_BLE_MESH_KEY_UNUSED ||
!ESP_BLE_MESH_ADDR_IS_UNICAST(params->ctx.addr) ||
(is_get_param_needed(params->opcode) && get == NULL)) {
return ESP_ERR_INVALID_ARG;
}
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_DFU_CLIENT;
msg.act = BTC_BLE_MESH_ACT_DFU_CLIENT_GET_STATE;
arg.dfu_get.params = params;
arg.dfu_get.get = get;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_dfu_client_args_t),
btc_ble_mesh_dfu_client_arg_deep_copy,
btc_ble_mesh_dfu_client_arg_deep_free) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_dfu_cli_img_send(esp_ble_mesh_dfu_cli_t *cli,
esp_ble_mesh_blob_cli_inputs_t *inputs,
esp_ble_mesh_blob_io_t *io,
esp_ble_mesh_dfu_cli_xfer_t *xfer)
{
btc_ble_mesh_dfu_client_args_t arg = {0};
btc_msg_t msg = {0};
if (cli == NULL || inputs == NULL ||
io == NULL || xfer == NULL) {
return ESP_ERR_INVALID_ARG;
}
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_DFU_CLIENT;
msg.act = BTC_BLE_MESH_ACT_DFU_CLIENT_IMG_SEND;
arg.send_arg.cli = cli;
arg.send_arg.inputs = inputs;
arg.send_arg.io = io;
arg.send_arg.xfer = xfer;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_dfu_client_args_t),
NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
uint8_t esp_ble_mesh_dfu_cli_progress(esp_ble_mesh_dfu_cli_t *cli)
{
if (!cli) {
return 0;
}
return btc_ble_mesh_dfu_cli_progress(cli);
}
esp_err_t esp_ble_mesh_register_dfu_client_callback(esp_ble_mesh_dfu_client_cb_t callback)
{
return (btc_profile_cb_set(BTC_PID_DFU_CLIENT, callback) == 0 ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_DFU_CLI */
#if CONFIG_BLE_MESH_DFU_SRV
void esp_ble_mesh_dfu_srv_verified(esp_ble_mesh_dfu_srv_t *srv)
{
if (!srv) {
return;
}
btc_ble_mesh_dfu_srv_verified(srv);
}
void esp_ble_mesh_dfu_srv_rejected(esp_ble_mesh_dfu_srv_t *srv)
{
if (!srv) {
return;
}
btc_ble_mesh_dfu_srv_rejected(srv);
}
void esp_ble_mesh_dfu_srv_cancel(esp_ble_mesh_dfu_srv_t *srv)
{
if (!srv) {
return;
}
btc_ble_mesh_dfu_srv_cancel(srv);
}
void esp_ble_mesh_dfu_srv_applied(esp_ble_mesh_dfu_srv_t *srv)
{
if (!srv) {
return;
}
btc_ble_mesh_dfu_srv_applied(srv);
}
bool esp_ble_mesh_dfu_srv_is_busy(const esp_ble_mesh_dfu_srv_t *srv)
{
if (!srv) {
return false;
}
return btc_ble_mesh_dfu_srv_is_busy(srv);
}
uint8_t esp_ble_mesh_dfu_srv_progress(const esp_ble_mesh_dfu_srv_t *srv)
{
if (!srv) {
return 0;
}
return btc_ble_mesh_dfu_srv_progress(srv);
}
#endif /* CONFIG_BLE_MESH_DFU_SRV */
#if CONFIG_BLE_MESH_DFD_CLI
esp_err_t esp_ble_mesh_register_dfd_cli_callback(esp_ble_mesh_dfd_client_cb_t callback)
{
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
return (btc_profile_cb_set(BTC_PID_DFD_CLIENT, callback) == 0 ? ESP_OK : ESP_FAIL);
}
static bool dfd_client_opcode_need_param(esp_ble_mesh_opcode_t opcode)
{
switch (opcode)
{
/* Get opcode */
case ESP_BLE_MESH_DFD_OP_RECEIVERS_GET:
case ESP_BLE_MESH_DFD_OP_FW_GET:
case ESP_BLE_MESH_DFD_OP_FW_GET_BY_INDEX:
/* Set opcode */
case ESP_BLE_MESH_DFD_OP_RECEIVERS_ADD:
case ESP_BLE_MESH_DFD_OP_START:
case ESP_BLE_MESH_DFD_OP_UPLOAD_START:
case ESP_BLE_MESH_DFD_OP_UPLOAD_START_OOB:
case ESP_BLE_MESH_DFD_OP_FW_DELETE:
return true;
default:
return false;
}
}
esp_err_t esp_ble_mesh_dfd_cli_get(esp_ble_mesh_client_common_param_t *params,
esp_ble_mesh_dfd_client_get_param_t *get_param)
{
btc_ble_mesh_dfd_client_args_t arg = {0};
btc_msg_t msg = {0};
if (params == NULL || params->model == NULL ||
params->ctx.net_idx == ESP_BLE_MESH_KEY_UNUSED ||
!ESP_BLE_MESH_ADDR_IS_UNICAST(params->ctx.addr) ||
(dfd_client_opcode_need_param(params->opcode) && get_param == NULL)) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_DFD_CLIENT;
msg.act = ESP_BLE_MESH_ACT_DFD_CLIENT_GET;
arg.dfd_client_get.params = params;
arg.dfd_client_get.get = get_param;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_dfd_client_args_t), btc_ble_mesh_dfd_client_arg_deep_copy,
btc_ble_mesh_dfd_client_arg_deep_free) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_dfd_cli_set(esp_ble_mesh_client_common_param_t *params,
esp_ble_mesh_dfd_client_set_param_t *set_param)
{
btc_ble_mesh_dfd_client_args_t arg = {0};
btc_msg_t msg = {0};
if (params == NULL || params->model == NULL ||
params->ctx.net_idx == ESP_BLE_MESH_KEY_UNUSED ||
!ESP_BLE_MESH_ADDR_IS_UNICAST(params->ctx.addr) ||
(dfd_client_opcode_need_param(params->opcode) && set_param == NULL)) {
return ESP_ERR_INVALID_ARG;
}
switch (params->opcode) {
case ESP_BLE_MESH_DFD_OP_RECEIVERS_ADD:
if (set_param->receivers_add.receivers_cnt == 0) {
return ESP_ERR_INVALID_ARG;
}
break;
case ESP_BLE_MESH_DFD_OP_UPLOAD_START:
if (set_param->dist_upload_start.fw_size == 0) {
return ESP_ERR_INVALID_ARG;
}
if (set_param->dist_upload_start.fwid == NULL) {
return ESP_ERR_INVALID_ARG;
}
break;
case ESP_BLE_MESH_DFD_OP_UPLOAD_START_OOB:
if (set_param->dist_upload_oob_start.url == NULL) {
return ESP_ERR_INVALID_ARG;
}
break;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_DFD_CLIENT;
msg.act = ESP_BLE_MESH_ACT_DFD_CLIENT_SET;
arg.dfd_client_set.params = params;
arg.dfd_client_set.set = set_param;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_dfd_client_args_t), btc_ble_mesh_dfd_client_arg_deep_copy,
btc_ble_mesh_dfd_client_arg_deep_free) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_DFD_CLI */

View File

@@ -0,0 +1,102 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include "esp_ble_mesh_dfu_slot_api.h"
#include "btc_ble_mesh_dfu_slot.h"
int esp_ble_mesh_dfu_slot_count(void)
{
return btc_ble_mesh_dfu_slot_count();
}
esp_ble_mesh_dfu_slot_t *esp_ble_mesh_dfu_slot_reserve(void)
{
return btc_ble_mesh_dfu_slot_reserve();
}
int esp_ble_mesh_dfu_slot_info_set(esp_ble_mesh_dfu_slot_t *dfu_slot, size_t size,
const uint8_t *metadata, size_t metadata_len)
{
if (!dfu_slot || !metadata ||
metadata_len == 0 ||
metadata_len > CONFIG_BLE_MESH_DFU_METADATA_MAXLEN) {
return ESP_ERR_INVALID_ARG;
}
return btc_ble_mesh_dfu_slot_info_set(dfu_slot, size,
metadata, metadata_len);
}
int esp_ble_mesh_dfu_slot_fwid_set(esp_ble_mesh_dfu_slot_t *dfu_slot,
const uint8_t *fwid, size_t fwid_len)
{
if (!dfu_slot || !fwid || fwid_len == 0 ||
fwid_len > CONFIG_BLE_MESH_DFU_FWID_MAXLEN) {
return ESP_ERR_INVALID_ARG;
}
return btc_ble_mesh_dfu_slot_fwid_set(dfu_slot, fwid,
fwid_len);
}
int esp_ble_mesh_dfu_slot_commit(esp_ble_mesh_dfu_slot_t *dfu_slot)
{
if (!dfu_slot) {
return ESP_ERR_INVALID_ARG;
}
return btc_ble_mesh_dfu_slot_commit(dfu_slot);
}
void esp_ble_mesh_dfu_slot_release(const esp_ble_mesh_dfu_slot_t *dfu_slot)
{
if (!dfu_slot) {
return;
}
btc_ble_mesh_dfu_slot_release(dfu_slot);
}
int esp_ble_mesh_dfu_slot_del(const esp_ble_mesh_dfu_slot_t *slot)
{
if (!slot) {
return ESP_ERR_INVALID_ARG;
}
return btc_ble_mesh_dfu_slot_del(slot);
}
void esp_ble_mesh_dfu_slot_del_all(void)
{
btc_ble_mesh_dfu_slot_del_all();
}
const esp_ble_mesh_dfu_slot_t *esp_ble_mesh_dfu_slot_at(uint16_t img_idx)
{
return btc_ble_mesh_dfu_slot_at(img_idx);
}
int esp_ble_mesh_dfu_slot_get(const uint8_t *fwid, size_t fwid_len, esp_ble_mesh_dfu_slot_t **slot)
{
if (!fwid || fwid_len == 0 ||
fwid_len > CONFIG_BLE_MESH_DFU_FWID_MAXLEN ||
!slot || !*slot) {
return ESP_ERR_INVALID_ARG;
}
return btc_ble_mesh_dfu_slot_get(fwid, fwid_len, slot);
}
int esp_ble_mesh_dfu_slot_img_idx_get(const esp_ble_mesh_dfu_slot_t *slot)
{
if (!slot) {
return ESP_ERR_INVALID_ARG;
}
return btc_ble_mesh_dfu_slot_img_idx_get(slot);
}

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -20,20 +20,20 @@ extern int bt_mesh_get_transfer_progress(void *model, uint16_t unicast_addr,
uint8_t *block_percent, uint8_t *chunk_percent);
extern int bt_mesh_get_blob_reception_progress(void *model, uint8_t *reception_progress);
esp_err_t esp_ble_mesh_register_mbt_client_callback(esp_ble_mesh_mbt_client_cb_t callback)
esp_err_t esp_ble_mesh_register_mbt_client_callback(esp_ble_mesh_mbt_client_cb_t callback) __attribute__((deprecated))
{
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
return (btc_profile_cb_set(BTC_PID_MBT_CLIENT, callback) == 0 ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_client_retrieve_capabilities(esp_ble_mesh_retrieve_capabilities_t *input)
esp_err_t esp_ble_mesh_mbt_client_retrieve_capabilities(esp_ble_mesh_retrieve_capabilities_t *input) __attribute__((deprecated))
{
btc_ble_mesh_mbt_client_args_t arg = {0};
btc_msg_t msg = {0};
if (input == NULL || input->model == NULL ||
(input->unicast_addr_count && input->unicast_addr == NULL)) {
(input->unicast_addr_count && input->unicast_addr == NULL)) {
return ESP_ERR_INVALID_ARG;
}
@@ -51,14 +51,14 @@ esp_err_t esp_ble_mesh_mbt_client_retrieve_capabilities(esp_ble_mesh_retrieve_ca
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_client_transfer_blob(esp_ble_mesh_transfer_blob_t *input)
esp_err_t esp_ble_mesh_mbt_client_transfer_blob(esp_ble_mesh_transfer_blob_t *input) __attribute__((deprecated))
{
btc_ble_mesh_mbt_client_args_t arg = {0};
btc_msg_t msg = {0};
if (input == NULL || input->model == NULL ||
(input->unicast_addr_count && input->unicast_addr == NULL) ||
input->blob_data == NULL) {
(input->unicast_addr_count && input->unicast_addr == NULL) ||
input->blob_data == NULL) {
return ESP_ERR_INVALID_ARG;
}
@@ -76,7 +76,7 @@ esp_err_t esp_ble_mesh_mbt_client_transfer_blob(esp_ble_mesh_transfer_blob_t *in
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_client_send_block(esp_ble_mesh_send_block_t *input)
esp_err_t esp_ble_mesh_mbt_client_send_block(esp_ble_mesh_send_block_t *input) __attribute__((deprecated))
{
btc_ble_mesh_mbt_client_args_t arg = {0};
btc_msg_t msg = {0};
@@ -97,7 +97,7 @@ esp_err_t esp_ble_mesh_mbt_client_send_block(esp_ble_mesh_send_block_t *input)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_client_send_data(esp_ble_mesh_send_data_t *input)
esp_err_t esp_ble_mesh_mbt_client_send_data(esp_ble_mesh_send_data_t *input) __attribute__((deprecated))
{
btc_ble_mesh_mbt_client_args_t arg = {0};
btc_msg_t msg = {0};
@@ -118,7 +118,7 @@ esp_err_t esp_ble_mesh_mbt_client_send_data(esp_ble_mesh_send_data_t *input)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_client_determine_block_status(esp_ble_mesh_determine_block_status_t *input)
esp_err_t esp_ble_mesh_mbt_client_determine_block_status(esp_ble_mesh_determine_block_status_t *input) __attribute__((deprecated))
{
btc_ble_mesh_mbt_client_args_t arg = {0};
btc_msg_t msg = {0};
@@ -139,13 +139,13 @@ esp_err_t esp_ble_mesh_mbt_client_determine_block_status(esp_ble_mesh_determine_
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_client_determine_transfer_status(esp_ble_mesh_determine_transfer_status_t *input)
esp_err_t esp_ble_mesh_mbt_client_determine_transfer_status(esp_ble_mesh_determine_transfer_status_t *input) __attribute__((deprecated))
{
btc_ble_mesh_mbt_client_args_t arg = {0};
btc_msg_t msg = {0};
if (input == NULL || input->model == NULL ||
(input->unicast_addr_count && input->unicast_addr == NULL)) {
(input->unicast_addr_count && input->unicast_addr == NULL)) {
return ESP_ERR_INVALID_ARG;
}
@@ -163,13 +163,13 @@ esp_err_t esp_ble_mesh_mbt_client_determine_transfer_status(esp_ble_mesh_determi
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_client_cancel_transfer(esp_ble_mesh_cancel_transfer_t *input)
esp_err_t esp_ble_mesh_mbt_client_cancel_transfer(esp_ble_mesh_cancel_transfer_t *input) __attribute__((deprecated))
{
btc_ble_mesh_mbt_client_args_t arg = {0};
btc_msg_t msg = {0};
if (input == NULL || input->model == NULL ||
(input->unicast_addr_count && input->unicast_addr == NULL)) {
(input->unicast_addr_count && input->unicast_addr == NULL)) {
return ESP_ERR_INVALID_ARG;
}
@@ -188,13 +188,13 @@ esp_err_t esp_ble_mesh_mbt_client_cancel_transfer(esp_ble_mesh_cancel_transfer_t
}
const esp_ble_mesh_blob_receiver_t *esp_ble_mesh_mbt_client_get_blob_receiver(esp_ble_mesh_model_t *model,
uint16_t unicast_addr)
uint16_t unicast_addr) __attribute__((deprecated))
{
return (const esp_ble_mesh_blob_receiver_t *)bt_mesh_get_blob_receiver((struct bt_mesh_model *)model,
unicast_addr);
}
const esp_ble_mesh_blob_receiver_t **esp_ble_mesh_mbt_client_get_active_blob_receiver(esp_ble_mesh_model_t *model)
const esp_ble_mesh_blob_receiver_t **esp_ble_mesh_mbt_client_get_active_blob_receiver(esp_ble_mesh_model_t *model) __attribute__((deprecated))
{
return (const esp_ble_mesh_blob_receiver_t **)bt_mesh_get_active_blob_receiver((struct bt_mesh_model *)model);
}
@@ -202,14 +202,14 @@ const esp_ble_mesh_blob_receiver_t **esp_ble_mesh_mbt_client_get_active_blob_rec
esp_err_t esp_ble_mesh_mbt_client_get_transfer_progress(esp_ble_mesh_model_t *model,
uint16_t unicast_addr,
uint8_t *block_percent,
uint8_t *chunk_percent)
uint8_t *chunk_percent) __attribute__((deprecated))
{
return (bt_mesh_get_transfer_progress((struct bt_mesh_model *)model, unicast_addr,
block_percent, chunk_percent) == 0 ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_client_set_transfer_ttl(esp_ble_mesh_model_t *model,
uint8_t transfer_ttl)
uint8_t transfer_ttl) __attribute__((deprecated))
{
btc_ble_mesh_mbt_client_args_t arg = {0};
btc_msg_t msg = {0};
@@ -231,7 +231,7 @@ esp_err_t esp_ble_mesh_mbt_client_set_transfer_ttl(esp_ble_mesh_model_t *model,
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_client_clear_transfer_ttl(esp_ble_mesh_model_t *model)
esp_err_t esp_ble_mesh_mbt_client_clear_transfer_ttl(esp_ble_mesh_model_t *model) __attribute__((deprecated))
{
btc_ble_mesh_mbt_client_args_t arg = {0};
btc_msg_t msg = {0};
@@ -253,7 +253,7 @@ esp_err_t esp_ble_mesh_mbt_client_clear_transfer_ttl(esp_ble_mesh_model_t *model
}
esp_err_t esp_ble_mesh_mbt_client_set_app_idx(esp_ble_mesh_model_t *model,
uint16_t app_idx)
uint16_t app_idx) __attribute__((deprecated))
{
btc_ble_mesh_mbt_client_args_t arg = {0};
btc_msg_t msg = {0};
@@ -275,7 +275,7 @@ esp_err_t esp_ble_mesh_mbt_client_set_app_idx(esp_ble_mesh_model_t *model,
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_client_clear_app_idx(esp_ble_mesh_model_t *model)
esp_err_t esp_ble_mesh_mbt_client_clear_app_idx(esp_ble_mesh_model_t *model) __attribute__((deprecated))
{
btc_ble_mesh_mbt_client_args_t arg = {0};
btc_msg_t msg = {0};
@@ -297,7 +297,7 @@ esp_err_t esp_ble_mesh_mbt_client_clear_app_idx(esp_ble_mesh_model_t *model)
}
esp_err_t esp_ble_mesh_mbt_client_set_multicast_addr(esp_ble_mesh_model_t *model,
uint16_t multicast_addr)
uint16_t multicast_addr) __attribute__((deprecated))
{
btc_ble_mesh_mbt_client_args_t arg = {0};
btc_msg_t msg = {0};
@@ -319,7 +319,7 @@ esp_err_t esp_ble_mesh_mbt_client_set_multicast_addr(esp_ble_mesh_model_t *model
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_client_clear_multicast_addr(esp_ble_mesh_model_t *model)
esp_err_t esp_ble_mesh_mbt_client_clear_multicast_addr(esp_ble_mesh_model_t *model) __attribute__((deprecated))
{
btc_ble_mesh_mbt_client_args_t arg = {0};
btc_msg_t msg = {0};
@@ -342,14 +342,14 @@ esp_err_t esp_ble_mesh_mbt_client_clear_multicast_addr(esp_ble_mesh_model_t *mod
#endif /* CONFIG_BLE_MESH_MBT_CLI */
#if CONFIG_BLE_MESH_MBT_SRV
esp_err_t esp_ble_mesh_register_mbt_server_callback(esp_ble_mesh_mbt_server_cb_t callback)
esp_err_t esp_ble_mesh_register_mbt_server_callback(esp_ble_mesh_mbt_server_cb_t callback) __attribute__((deprecated))
{
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
return (btc_profile_cb_set(BTC_PID_MBT_SERVER, callback) == 0 ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_server_initialize_blob_receive(esp_ble_mesh_initialize_blob_receive_t *input)
esp_err_t esp_ble_mesh_mbt_server_initialize_blob_receive(esp_ble_mesh_initialize_blob_receive_t *input) __attribute__((deprecated))
{
btc_ble_mesh_mbt_server_args_t arg = {0};
btc_msg_t msg = {0};
@@ -370,7 +370,7 @@ esp_err_t esp_ble_mesh_mbt_server_initialize_blob_receive(esp_ble_mesh_initializ
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_server_cancel_blob_receive(esp_ble_mesh_cancel_blob_receive_t *input)
esp_err_t esp_ble_mesh_mbt_server_cancel_blob_receive(esp_ble_mesh_cancel_blob_receive_t *input) __attribute__((deprecated))
{
btc_ble_mesh_mbt_server_args_t arg = {0};
btc_msg_t msg = {0};
@@ -391,7 +391,7 @@ esp_err_t esp_ble_mesh_mbt_server_cancel_blob_receive(esp_ble_mesh_cancel_blob_r
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_server_set_blob_capabilities(esp_ble_mesh_set_blob_capabilities_t *input)
esp_err_t esp_ble_mesh_mbt_server_set_blob_capabilities(esp_ble_mesh_set_blob_capabilities_t *input) __attribute__((deprecated))
{
btc_ble_mesh_mbt_server_args_t arg = {0};
btc_msg_t msg = {0};
@@ -413,7 +413,7 @@ esp_err_t esp_ble_mesh_mbt_server_set_blob_capabilities(esp_ble_mesh_set_blob_ca
}
esp_err_t esp_ble_mesh_mbt_server_get_blob_reception_progress(esp_ble_mesh_model_t *model,
uint8_t *reception_progress)
uint8_t *reception_progress) __attribute__((deprecated))
{
return (bt_mesh_get_blob_reception_progress((struct bt_mesh_model *)model,
reception_progress) == 0 ? ESP_OK : ESP_FAIL);

View File

@@ -0,0 +1,696 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _ESP_BLE_MESH_BLOB_MODEL_API_H_
#define _ESP_BLE_MESH_BLOB_MODEL_API_H_
#include "esp_ble_mesh_defs.h"
#include "esp_ble_mesh_blob_model_api.h"
#if CONFIG_BLE_MESH_BLOB_CLI || CONFIG_BLE_MESH_BLOB_SRV
#ifndef _BLE_MESH_BLOB_DEPRECATE_WARN
#define _BLE_MESH_BLOB_DEPRECATE_WARN
#warning Please note: All APIs published in this document are in Preview version and may undergo significant changes in the future.
#endif
#endif /* CONFIG_BLE_MESH_BLOB_CLI || CONFIG_BLE_MESH_BLOB_SRV */
#ifdef __cplusplus
extern "C" {
#endif
#define ESP_BLE_MESH_BLOB_ID_SIZE 8
/** @def ESP_BLE_MESH_MODEL_BLOB_CLI
*
* @brief Define a new BLOB Transfer Client model.
*
* @note This API needs to be called for each element on which
* the application needs to have a BLOB Transfer Client model.
*
* @param cli_pub Pointer to the unique struct esp_ble_mesh_model_pub_t.
* @param cli_data Pointer to the unique struct esp_ble_mesh_client_t.
*
* @return New BLOB Transfer Client model instance.
*/
#define ESP_BLE_MESH_MODEL_BLOB_CLI(cli_pub, cli_data) \
ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_BLOB_CLI, \
NULL, cli_pub, cli_data)
/** @def ESP_BLE_MESH_MODEL_BLOB_SRV
*
* @brief Define a new BLOB Transfer Server model.
*
* @note This API needs to be called for each element on which
* the application needs to have a BLOB Transfer Server model.
*
* @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t.
* @param srv_data Pointer to the unique struct esp_ble_mesh_blob_trans_srv_t.
*
* @return New BLOB Transfer Server model instance.
*/
#define ESP_BLE_MESH_MODEL_BLOB_SRV(srv_pub, srv_data) \
ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_BLOB_SRV, \
NULL, srv_pub, srv_data)
/** BLOB stream. */
typedef struct esp_ble_mesh_blob_io esp_ble_mesh_blob_io_t;
/** @brief BLOB Transfer Server instance. */
typedef struct esp_ble_mesh_blob_srv esp_ble_mesh_blob_srv_t;
/** @brief BLOB Transfer Server model event handlers. */
typedef struct esp_ble_mesh_blob_srv_cb esp_ble_mesh_blob_srv_cb_t;
/** Target node's Pull mode (Pull BLOB Transfer Mode) context used
* while sending chunks to the Target node.
*/
typedef struct esp_ble_mesh_blob_target_pull esp_ble_mesh_blob_target_pull_t;
/** BLOB Transfer Client Target node. */
typedef struct esp_ble_mesh_blob_target esp_ble_mesh_blob_target_t;
/** BLOB transfer information. */
typedef struct esp_ble_mesh_blob_xfer_info esp_ble_mesh_blob_xfer_info_t;
/** BLOB Transfer Client transfer inputs. */
typedef struct esp_ble_mesh_blob_cli_inputs esp_ble_mesh_blob_cli_inputs_t;
/** Transfer capabilities of a Target node. */
typedef struct esp_ble_mesh_blob_cli_caps esp_ble_mesh_blob_cli_caps_t;
/**
* @brief BLOB Transfer Client model instance.
* @note Preview version, the contents of this struct may change in the future.
*/
typedef struct esp_ble_mesh_blob_cli esp_ble_mesh_blob_cli_t;
/** Event handler callbacks for the BLOB Transfer Client model. */
typedef struct esp_ble_mesh_blob_cli_cb esp_ble_mesh_blob_cli_cb_t;
/** BLOB transfer. */
typedef struct esp_ble_mesh_blob_xfer esp_ble_mesh_blob_xfer_t;
/** BLOB transfer data block. */
typedef struct esp_ble_mesh_blob_block esp_ble_mesh_blob_block_t;
/** BLOB data chunk. */
typedef struct esp_ble_mesh_blob_chunk esp_ble_mesh_blob_chunk_t;
/** Transfer phase. */
typedef enum esp_ble_mesh_blob_xfer_phase {
ESP_BLE_MESH_BLOB_XFER_PHASE_INACTIVE, /*!< The BLOB Transfer Server is awaiting configuration. */
ESP_BLE_MESH_BLOB_XFER_PHASE_WAITING_FOR_START, /*!< The BLOB Transfer Server is ready to receive a BLOB transfer. */
ESP_BLE_MESH_BLOB_XFER_PHASE_WAITING_FOR_BLOCK, /*!< The BLOB Transfer Server is waiting for the next block of data. */
ESP_BLE_MESH_BLOB_XFER_PHASE_WAITING_FOR_CHUNK, /*!< The BLOB Transfer Server is waiting for the next chunk of data. */
ESP_BLE_MESH_BLOB_XFER_PHASE_COMPLETE, /*!< The BLOB was transferred successfully. */
ESP_BLE_MESH_BLOB_XFER_PHASE_SUSPENDED, /*!< The BLOB transfer is paused. */
} esp_ble_mesh_blob_xfer_phase_t;
/** BLOB transfer mode. */
typedef enum esp_ble_mesh_blob_xfer_mode {
ESP_BLE_MESH_BLOB_XFER_MODE_NONE, /*!< No valid transfer mode. */
ESP_BLE_MESH_BLOB_XFER_MODE_PUSH, /*!< Push mode (Push BLOB Transfer Mode). */
ESP_BLE_MESH_BLOB_XFER_MODE_PULL, /*!< Pull mode (Pull BLOB Transfer Mode). */
ESP_BLE_MESH_BLOB_XFER_MODE_ALL, /*!< Both modes are valid. */
} esp_ble_mesh_blob_xfer_mode_t;
/** BLOB model status codes. */
typedef enum esp_ble_mesh_blob_status {
/** The message was processed successfully. */
ESP_BLE_MESH_BLOB_SUCCESS,
/** The Block Number field value is not within the range of blocks being
* transferred.
*/
ESP_BLE_MESH_BLOB_ERR_INVALID_BLOCK_NUM,
/** The block size is smaller than the size indicated by the Min Block
* Size Log state or is larger than the size indicated by the Max Block
* Size Log state.
*/
ESP_BLE_MESH_BLOB_ERR_INVALID_BLOCK_SIZE,
/** The chunk size exceeds the size indicated by the Max Chunk Size
* state, or the number of chunks exceeds the number specified by the
* Max Total Chunks state.
*/
ESP_BLE_MESH_BLOB_ERR_INVALID_CHUNK_SIZE,
/** The operation cannot be performed while the server is in the current
* phase.
*/
ESP_BLE_MESH_BLOB_ERR_WRONG_PHASE,
/** A parameter value in the message cannot be accepted. */
ESP_BLE_MESH_BLOB_ERR_INVALID_PARAM,
/** The message contains a BLOB ID value that is not expected. */
ESP_BLE_MESH_BLOB_ERR_WRONG_BLOB_ID,
/** There is not enough space available in memory to receive the BLOB.
*/
ESP_BLE_MESH_BLOB_ERR_BLOB_TOO_LARGE,
/** The transfer mode is not supported by the BLOB Transfer Server
* model.
*/
ESP_BLE_MESH_BLOB_ERR_UNSUPPORTED_MODE,
/** An internal error occurred on the node. */
ESP_BLE_MESH_BLOB_ERR_INTERNAL,
/** The requested information cannot be provided while the server is in
* the current phase.
*/
ESP_BLE_MESH_BLOB_ERR_INFO_UNAVAILABLE,
} esp_ble_mesh_blob_status_t;
/** BLOB Transfer Client state. */
typedef enum esp_ble_mesh_blob_cli_state {
ESP_BLE_MESH_BLOB_CLI_STATE_NONE, /*!< No transfer is active. */
ESP_BLE_MESH_BLOB_CLI_STATE_CAPS_GET, /*!< Retrieving transfer capabilities. */
ESP_BLE_MESH_BLOB_CLI_STATE_START, /*!< Sending transfer start. */
ESP_BLE_MESH_BLOB_CLI_STATE_BLOCK_START, /*!< Sending block start. */
ESP_BLE_MESH_BLOB_CLI_STATE_BLOCK_SEND, /*!< Sending block chunks. */
ESP_BLE_MESH_BLOB_CLI_STATE_BLOCK_CHECK, /*!< Checking block status. */
ESP_BLE_MESH_BLOB_CLI_STATE_XFER_CHECK, /*!< Checking transfer status. */
ESP_BLE_MESH_BLOB_CLI_STATE_CANCEL, /*!< Cancelling transfer. */
ESP_BLE_MESH_BLOB_CLI_STATE_SUSPENDED, /*!< Transfer is suspended. */
ESP_BLE_MESH_BLOB_CLI_STATE_XFER_PROGRESS_GET, /*!< Checking transfer progress. */
} esp_ble_mesh_blob_cli_state_t;
/** BLOB stream interaction mode. */
typedef enum esp_ble_mesh_blob_io_mode {
ESP_BLE_MESH_BLOB_READ, /*!< Read data from the stream. */
ESP_BLE_MESH_BLOB_WRITE, /*!< Write data to the stream. */
} esp_ble_mesh_blob_io_mode_t;
/** BLOB transfer. */
struct esp_ble_mesh_blob_xfer {
uint64_t id; /*!< BLOB ID. */
size_t size; /*!< Total BLOB size in bytes. */
esp_ble_mesh_blob_xfer_mode_t mode; /*!< BLOB transfer mode. */
uint8_t block_size_log; /*!< Logarithmic representation of the block size. */
uint16_t chunk_size; /*!< Base chunk size. May be smaller for the last chunk. */
};
/** BLOB transfer data block. */
struct esp_ble_mesh_blob_block {
size_t size; /*!< Block size in bytes */
off_t offset; /*!< Offset in bytes from the start of the BLOB. */
uint16_t number; /*!< Block number */
uint16_t chunk_count; /*!< Number of chunks in block. */
uint8_t missing[DIV_ROUND_UP(CONFIG_BLE_MESH_BLOB_CHUNK_COUNT_MAX,
8)]; /*!< Bitmap of missing chunks. */
};
/** BLOB data chunk. */
struct esp_ble_mesh_blob_chunk {
off_t offset; /*!< Offset of the chunk data from the start of the block. */
size_t size; /*!< Chunk data size. */
uint8_t *data; /*!< Chunk data. */
};
/** BLOB stream. */
struct esp_ble_mesh_blob_io {
/** @brief Open callback.
*
* Called when the reader is opened for reading.
*
* @param io BLOB stream.
* @param xfer BLOB transfer.
* @param mode Direction of the stream (read/write).
*
* @return 0 on success, or (negative) error code otherwise.
*/
int (*open)(const esp_ble_mesh_blob_io_t *io,
const esp_ble_mesh_blob_xfer_t *xfer,
esp_ble_mesh_blob_io_mode_t mode);
/** @brief Close callback.
*
* Called when the reader is closed.
*
* @param io BLOB stream.
* @param xfer BLOB transfer.
*/
void (*close)(const esp_ble_mesh_blob_io_t *io,
const esp_ble_mesh_blob_xfer_t *xfer);
/** @brief Block start callback.
*
* Called when a new block is opened for sending. Each block is only
* sent once, and are always sent in increasing order. The data chunks
* inside a single block may be requested out of order and multiple
* times.
*
* @param io BLOB stream.
* @param xfer BLOB transfer.
* @param block Block that was started.
*/
int (*block_start)(const esp_ble_mesh_blob_io_t *io,
const esp_ble_mesh_blob_xfer_t *xfer,
const esp_ble_mesh_blob_block_t *block);
/** @brief Block end callback.
*
* Called when the current block has been transmitted in full.
* No data from this block will be requested again, and the application
* data associated with this block may be discarded.
*
* @param io BLOB stream.
* @param xfer BLOB transfer.
* @param block Block that finished sending.
*/
void (*block_end)(const esp_ble_mesh_blob_io_t *io,
const esp_ble_mesh_blob_xfer_t *xfer,
const esp_ble_mesh_blob_block_t *block);
/** @brief Chunk data write callback.
*
* Used by the BLOB Transfer Server on incoming data.
*
* Each block is divided into chunks of data. This callback is called
* when a new chunk of data is received. Chunks may be received in
* any order within their block.
*
* If the callback returns successfully, this chunk will be marked as
* received, and will not be received again unless the block is
* restarted due to a transfer suspension. If the callback returns a
* non-zero value, the chunk remains unreceived, and the BLOB Transfer
* Client will attempt to resend it later.
*
* Note that the Client will only perform a limited number of attempts
* at delivering a chunk before dropping a Target node from the transfer.
* The number of retries performed by the Client is implementation
* specific.
*
* @param io BLOB stream.
* @param xfer BLOB transfer.
* @param block Block the chunk is part of.
* @param chunk Received chunk.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int (*write)(const esp_ble_mesh_blob_io_t *io,
const esp_ble_mesh_blob_xfer_t *xfer,
const esp_ble_mesh_blob_block_t *block,
const esp_ble_mesh_blob_chunk_t *chunk);
/** @brief Chunk data read callback.
*
* Used by the BLOB Transfer Client to fetch outgoing data.
*
* The Client calls the chunk data request callback to populate a chunk
* message going out to the Target nodes. The data request callback
* may be called out of order and multiple times for each offset, and
* cannot be used as an indication of progress.
*
* Returning a non-zero status code on the chunk data request callback
* results in termination of the transfer.
*
* @param io BLOB stream.
* @param xfer BLOB transfer.
* @param block Block the chunk is part of.
* @param chunk Chunk to get the data of. The buffer pointer to by the
* @c data member should be filled by the callback.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int (*read)(const esp_ble_mesh_blob_io_t *io,
const esp_ble_mesh_blob_xfer_t *xfer,
const esp_ble_mesh_blob_block_t *block,
const esp_ble_mesh_blob_chunk_t *chunk);
};
/** @brief BLOB Transfer Server model event handlers.
*
* All callbacks are optional.
*/
struct esp_ble_mesh_blob_srv_cb {
/** @brief Transfer start callback.
*
* Called when the transfer has started with the prepared BLOB ID.
*
* @param srv BLOB Transfer Server instance.
* @param ctx Message context for the incoming start message. The
* entire transfer will be sent from the same source
* address.
* @param xfer Transfer parameters.
*
* @return 0 on success, or (negative) error code to reject the
* transfer.
*/
int (*start)(esp_ble_mesh_blob_srv_t *srv, esp_ble_mesh_msg_ctx_t *ctx,
esp_ble_mesh_blob_xfer_t *xfer);
/** @brief Transfer end callback.
*
* Called when the transfer ends, either because it was cancelled, or
* because it finished successfully. A new transfer may be prepared.
*
* @note The transfer may end before it's started if the start
* parameters are invalid.
*
* @param srv BLOB Transfer Server instance.
* @param id BLOB ID of the cancelled transfer.
* @param success Whether the transfer was successful.
*/
void (*end)(esp_ble_mesh_blob_srv_t *srv, uint64_t id, bool success);
/** @brief Transfer suspended callback.
*
* Called if the Server timed out while waiting for a transfer packet.
* A suspended transfer may resume later from the start of the current
* block. Any received chunks in the current block should be discarded,
* they will be received again if the transfer resumes.
*
* The transfer will call @c resumed again when resuming.
*
* @note The BLOB Transfer Server does not run a timer in the suspended state,
* and it's up to the application to determine whether the
* transfer should be permanently cancelled. Without interaction,
* the transfer will be suspended indefinitely, and the BLOB Transfer
* Server will not accept any new transfers.
*
* @param srv BLOB Transfer Server instance.
*/
void (*suspend)(esp_ble_mesh_blob_srv_t *srv);
/** @brief Transfer resume callback.
*
* Called if the transfer is resumed after being suspended.
*
* @param srv BLOB Transfer Server instance.
*/
void (*resume)(esp_ble_mesh_blob_srv_t *srv);
/** @brief Transfer recovery callback.
*
* Called when the Bluetooth mesh subsystem is started if the device is rebooted
* in the middle of a transfer.
*
* Transfers will not be resumed after a reboot if this callback is not
* defined.
*
* @param srv BLOB Transfer Server instance.
* @param xfer Transfer to resume.
* @param io BLOB stream return parameter. Must be set to a valid
* BLOB stream by the callback.
*
* @return 0 on success, or (negative) error code to abandon the
* transfer.
*/
int (*recover)(esp_ble_mesh_blob_srv_t *srv,
esp_ble_mesh_blob_xfer_t *xfer,
esp_ble_mesh_blob_io_t **io);
};
#if defined(CONFIG_BLE_MESH_BLOB_SRV)
#define ESP_BLE_MESH_BLOB_BLOCKS_MAX \
(DIV_ROUND_UP(CONFIG_BLE_MESH_BLOB_SIZE_MAX, \
CONFIG_BLE_MESH_BLOB_BLOCK_SIZE_MIN))
#else
#define ESP_BLE_MESH_BLOB_BLOCKS_MAX 1
#endif
/** @brief BLOB Transfer Server instance. */
struct esp_ble_mesh_blob_srv {
/** Event handler callbacks. */
esp_ble_mesh_blob_srv_cb_t *cb;
/** Runtime state: */
esp_ble_mesh_blob_io_t *io;
struct k_delayed_work rx_timeout;
esp_ble_mesh_blob_block_t block;
esp_ble_mesh_model_t *mod;
esp_ble_mesh_blob_xfer_phase_t phase;
/** State of blob serber. */
struct esp_ble_mesh_blob_srv_state {
esp_ble_mesh_blob_xfer_t xfer;
uint16_t cli;
uint16_t app_idx;
uint16_t timeout_base;
uint16_t mtu_size;
uint8_t ttl;
/* Bitfield of pending blocks. */
BLE_MESH_ATOMIC_DEFINE(blocks, ESP_BLE_MESH_BLOB_BLOCKS_MAX);
} state;
/* Pull mode (Pull BLOB Transfer Mode) behavior. */
struct {
uint16_t chunk_idx;
struct k_delayed_work report;
} pull;
};
/** Target node's Pull mode (Pull BLOB Transfer Mode) context used
* while sending chunks to the Target node.
*/
struct esp_ble_mesh_blob_target_pull {
int64_t block_report_timestamp; /*!< Timestamp when the Block Report Timeout Timer expires for this Target node. */
uint8_t missing[DIV_ROUND_UP(CONFIG_BLE_MESH_BLOB_CHUNK_COUNT_MAX, 8)]; /*!< Missing chunks reported by this Target node. */
};
/** BLOB Transfer Client Target node. */
struct esp_ble_mesh_blob_target {
sys_snode_t n; /*!< Linked list node */
uint16_t addr; /*!< Target node address. */
/** Target node's Pull mode context.
* Needs to be initialized when sending a BLOB in Pull mode.
*/
esp_ble_mesh_blob_target_pull_t *pull;
uint8_t status; /*!< BLOB transfer status, see esp_ble_mesh_blob_status. */
uint8_t procedure_complete: 1, /*!< Procedure has been completed. */
acked: 1, /*!< Message has been acknowledged. Not used when sending. */
timedout: 1, /*!< Target node didn't respond after specified timeout. */
skip: 1; /*!< Skip Target node from broadcast. */
};
/** BLOB transfer information. */
struct esp_ble_mesh_blob_xfer_info {
esp_ble_mesh_blob_status_t status; /*!< BLOB transfer status. */
esp_ble_mesh_blob_xfer_mode_t mode; /*!< BLOB transfer mode. */
esp_ble_mesh_blob_xfer_phase_t phase; /*!< BLOB transfer phase. */
uint64_t id; /*!< BLOB ID. */
uint32_t size; /*!< BLOB size in octets. */
uint8_t block_size_log; /*!< Logarithmic representation of the block size. */
uint16_t mtu_size; /*!< MTU size in octets. */
const uint8_t *missing_blocks; /*!< Bit field indicating blocks that were not received. */
};
/** BLOB Transfer Client transfer inputs. */
struct esp_ble_mesh_blob_cli_inputs {
/** Linked list of Target nodes. Each node should point to
* esp_ble_mesh_blob_target_t::n.
*/
sys_slist_t targets;
/** AppKey index to send with. */
uint16_t app_idx;
/** Group address destination for the BLOB transfer, or
* ESP_BLE_MESH_ADDR_UNASSIGNED to send every message to each Target
* node individually.
*/
uint16_t group;
/** Time to live value of BLOB transfer messages. */
uint8_t ttl;
/** Additional response time for the Target nodes, in 10-second increments.
*
* The extra time can be used to give the Target nodes more time to respond
* to messages from the Client. The actual timeout will be calculated
* according to the following formula:
*
* @verbatim
* timeout = 20 seconds + (10 seconds * timeout_base) + (100 ms * TTL)
* @endverbatim
*
* If a Target node fails to respond to a message from the Client within the
* configured transfer timeout, the Target node is dropped.
*/
uint16_t timeout_base;
};
/** Transfer capabilities of a Target node. */
struct esp_ble_mesh_blob_cli_caps {
size_t max_size; /*!< Max BLOB size. */
uint8_t min_block_size_log; /*!< Logarithmic representation of the minimum block size. */
uint8_t max_block_size_log; /*!< Logarithmic representation of the maximum block size. */
uint16_t max_chunks; /*!< Max number of chunks per block. */
uint16_t max_chunk_size; /*!< Max chunk size. */
uint16_t mtu_size; /*!< Max MTU size. */
esp_ble_mesh_blob_xfer_mode_t modes; /*!< Supported transfer modes. */
};
/** Event handler callbacks for the BLOB Transfer Client model.
*
* All handlers are optional.
*/
struct esp_ble_mesh_blob_cli_cb {
/** @brief Capabilities retrieval completion callback.
*
* Called when the capabilities retrieval procedure completes, indicating that
* a common set of acceptable transfer parameters have been established
* for the given list of Target nodes. All compatible Target nodes have
* status code ESP_BLE_MESH_BLOB_SUCCESS.
*
* @param cli BLOB Transfer Client instance.
* @param caps Safe transfer capabilities if the transfer capabilities
* of at least one Target node has satisfied the Client, or NULL otherwise.
*/
void (*caps)(esp_ble_mesh_blob_cli_t *cli,
const esp_ble_mesh_blob_cli_caps_t *caps);
/** @brief Target node loss callback.
*
* Called whenever a Target node has been lost due to some error in the
* transfer. Losing a Target node is not considered a fatal error for
* the Client until all Target nodes have been lost.
*
* @param cli BLOB Transfer Client instance.
* @param target Target node that was lost.
* @param reason Reason for the Target node loss.
*/
void (*lost_target)(esp_ble_mesh_blob_cli_t *cli,
esp_ble_mesh_blob_target_t *target,
esp_ble_mesh_blob_status_t reason);
/** @brief Transfer is suspended.
*
* Called when the transfer is suspended due to response timeout from all Target nodes.
*
* @param cli BLOB Transfer Client instance.
*/
void (*suspend)(esp_ble_mesh_blob_cli_t *cli);
/** @brief Transfer end callback.
*
* Called when the transfer ends.
*
* @param cli BLOB Transfer Client instance.
* @param xfer Completed transfer.
* @param success Status of the transfer.
* Is @c true if at least one Target
* node received the whole transfer.
*/
void (*end)(esp_ble_mesh_blob_cli_t *cli,
const esp_ble_mesh_blob_xfer_t *xfer, bool success);
/** @brief Transfer progress callback
*
* The content of @c info is invalidated upon exit from the callback.
* Therefore it needs to be copied if it is planned to be used later.
*
* @param cli BLOB Transfer Client instance.
* @param target Target node that responded to the request.
* @param info BLOB transfer information.
*/
void (*xfer_progress)(esp_ble_mesh_blob_cli_t *cli,
esp_ble_mesh_blob_target_t *target,
const esp_ble_mesh_blob_xfer_info_t *info);
/** @brief End of Get Transfer Progress procedure.
*
* Called when all Target nodes have responded or the procedure timed-out.
*
* @param cli BLOB Transfer Client instance.
*/
void (*xfer_progress_complete)(esp_ble_mesh_blob_cli_t *cli);
};
/** @cond INTERNAL_HIDDEN */
typedef struct {
/** Called for every Target node in unicast mode, or once in case of multicast mode. */
void (*send)(esp_ble_mesh_blob_cli_t *cli, uint16_t dst);
/** Called after every @ref blob_cli_broadcast_ctx::send callback. */
void (*send_complete)(esp_ble_mesh_blob_cli_t *cli, uint16_t dst);
/** If @ref blob_cli_broadcast_ctx::acked is true, called after all Target nodes
* have confirmed reception by @ref blob_cli_broadcast_rsp. Otherwise, called
* after transmission has been completed.
*/
void (*next)(esp_ble_mesh_blob_cli_t *cli);
/** If true, every transmission needs to be confirmed by @ref blob_cli_broadcast_rsp before
* @ref blob_cli_broadcast_ctx::next is called.
*/
bool acked;
/** If true, the message is always sent in a unicast way. */
bool force_unicast;
/** If true, non-responsive Target nodes won't be dropped after transfer has timed out. */
bool optional;
/** Set to true by the BLOB Transfer Client between blob_cli_broadcast
* and broadcast_complete calls.
*/
bool is_inited;
/* Defines a time in ms by which the broadcast API postpones sending the message to a next
* target or completing the broadcast.
*/
uint32_t post_send_delay_ms;
} esp_blob_cli_broadcast_ctx_t;
/** INTERNAL_HIDDEN @endcond */
/**
* @brief BLOB Transfer Client model instance.
* @note Preview version, the contents of this struct may change in the future.
*/
struct esp_ble_mesh_blob_cli {
/** Event handler callbacks */
const esp_ble_mesh_blob_cli_cb_t *cb;
/** Runtime state */
const esp_ble_mesh_model_t *mod;
/** Firmware transfer information */
struct {
esp_ble_mesh_blob_target_t *target;
esp_blob_cli_broadcast_ctx_t ctx;
struct k_delayed_work retry;
/* Represents Client Timeout timer in a timestamp. Used in Pull mode only. */
int64_t cli_timestamp;
struct k_work complete;
uint16_t pending;
uint8_t retries;
uint8_t sending : 1,
cancelled : 1;
} tx;
/** Firmware IO operation callbacks */
const esp_ble_mesh_blob_io_t *io;
/** BLOB Transfer Client transfer inputs. */
const esp_ble_mesh_blob_cli_inputs_t *inputs;
/** BLOB transfer. */
const esp_ble_mesh_blob_xfer_t *xfer;
/** Interval between chunk transmissions, in milliseconds. */
uint32_t chunk_interval_ms;
/** BLOCK count */
uint16_t block_count;
/** CHUNK index */
uint16_t chunk_idx;
/** Max Transfer Unit Size of BLOB Transfer */
uint16_t mtu_size;
/** State of blob client mode transfer */
esp_ble_mesh_blob_cli_state_t state;
/** BLOB transfer data block. */
esp_ble_mesh_blob_block_t block;
/** Transfer capabilities of a Target node. */
esp_ble_mesh_blob_cli_caps_t caps;
};
#ifdef __cplusplus
}
#endif
#endif /* _ESP_BLE_MESH_BLOB_MODEL_API_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,148 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _ESP_BLE_MESH_DFU_SLOT_API_H_
#define _ESP_BLE_MESH_DFU_SLOT_API_H_
#include "esp_ble_mesh_dfu_model_api.h"
#if CONFIG_BLE_MESH_DFU_SLOTS
#ifndef _BLE_MESH_BLOB_DEPRECATE_WARN
#define _BLE_MESH_BLOB_DEPRECATE_WARN
#warning Please note: All APIs published in this document are in Preview version and may undergo significant changes in the future.
#endif
#endif /* CONFIG_BLE_MESH_DFU_SLOTS */
typedef struct esp_ble_mesh_dfu_slot esp_ble_mesh_dfu_slot_t;
typedef enum esp_ble_mesh_dfu_iter
(*esp_ble_mesh_dfu_slot_cb_t) (const esp_ble_mesh_dfu_slot_t *slot, void *user_data);
/** @brief Get the number of slots committed to the firmware list.
*
* @return Number of committed slots.
*/
int esp_ble_mesh_dfu_slot_count(void);
/** @brief Reserve a new DFU image slot for a distributable image.
*
* A DFU image slot represents a single distributable DFU image with all its
* metadata. The slot data must be set using esp_ble_mesh_dfu_slot_info_set and
* esp_ble_mesh_dfu_slot_fwid_set, and the slot committed using
* esp_ble_mesh_dfu_slot_commit for the slot to be considered part of the slot
* list.
*
* @return
* - slot : A pointer to the reserved slot
* - @c NULL : Slot allocation failed
*/
esp_ble_mesh_dfu_slot_t *esp_ble_mesh_dfu_slot_reserve(void);
/** @brief Set the size and metadata for a reserved slot.
*
* @param dfu_slot Pointer to the reserved slot for which to set the
* metadata.
* @param size The size of the image.
* @param metadata Metadata or NULL.
* @param metadata_len Length of the metadata, at most @c
* CONFIG_BLE_MESH_DFU_METADATA_MAXLEN.
*
* @return
* - 0 : success
* - @c ESP_ERR_INVALID_ARG : invalid slot parameter or invalid metadata parameter
* - @c ESP_ERR_INVALID_SIZE : metadata length is zero or exceeds @c CONFIG_BLE_MESH_DFU_METADATA_MAXLEN
*/
int esp_ble_mesh_dfu_slot_info_set(esp_ble_mesh_dfu_slot_t *dfu_slot, size_t size,
const uint8_t *metadata, size_t metadata_len);
/** @brief Set the new fwid for the incoming image for a reserved slot.
*
* @param dfu_slot Pointer to the reserved slot for which to set the fwid.
* @param fwid Fwid to set.
* @param fwid_len Length of the fwid, at most @c
* CONFIG_BLE_MESH_DFU_FWID_MAXLEN.
*
* @return
* - 0 : success
* - @c ESP_ERR_INVALID_ARG : invalid slot parameter or invalid fwid parameter
* - @c ESP_ERR_INVALID_SIZE : fwid length is zero or exceeds @c CONFIG_BLE_MESH_DFU_FWID_MAXLEN
*/
int esp_ble_mesh_dfu_slot_fwid_set(esp_ble_mesh_dfu_slot_t *dfu_slot,
const uint8_t *fwid, size_t fwid_len);
/** @brief Commit the reserved slot to the list of slots, and store it
* persistently.
*
* If the commit fails for any reason, the slot will still be in the reserved
* state after this call.
*
* @param dfu_slot Pointer to the reserved slot.
*
* @return
* - 0 : success
* - @c ESP_ERR_INVALID_ARG : invalid slot parameter or slot has been committed
* - @c ESP_ERR_INVALID_SIZE : slot size is zero
*/
int esp_ble_mesh_dfu_slot_commit(esp_ble_mesh_dfu_slot_t *dfu_slot);
/** @brief Release a reserved slot so that it can be reserved again.
*
* @param dfu_slot Pointer to the reserved slot.
*/
void esp_ble_mesh_dfu_slot_release(const esp_ble_mesh_dfu_slot_t *dfu_slot);
/** @brief Delete a committed DFU image slot.
*
* @param slot Slot to delete. Must be a valid pointer acquired from this
* module.
*
* @return
* - 0 : success
* - @c ESP_ERR_INVALID_ARG : invalid slot parameter
*/
int esp_ble_mesh_dfu_slot_del(const esp_ble_mesh_dfu_slot_t *slot);
/** @brief Delete all DFU image slots.
*/
void esp_ble_mesh_dfu_slot_del_all(void);
/** @brief Get the DFU image slot at the given firmware image list index.
*
* @param img_idx DFU image slot index.
*
* @return
* - slot : A pointer to the reserved slot
* - @c NULL : No slot exists with the given index
*/
const esp_ble_mesh_dfu_slot_t *esp_ble_mesh_dfu_slot_at(uint16_t img_idx);
/** @brief Get the committed DFU image slot for the image with the given
* firmware ID.
*
* @param fwid Firmware ID.
* @param fwid_len Firmware ID length.
* @param slot Slot pointer to fill.
*
* @return
* - index : Slot index
* - @c ESP_ERR_INVALID_ARG : invalid fwid parameter or invalid slot parameter
* - @c ESP_ERR_INVALID_SIZE : fwid length is zero
* - @c ESP_ERR_NOT_FOUND : no slot exists with the given firmware id
*/
int esp_ble_mesh_dfu_slot_get(const uint8_t *fwid, size_t fwid_len, esp_ble_mesh_dfu_slot_t **slot);
/** @brief Get the index in the firmware image list for the given slot.
*
* @param slot Slot to find.
*
* @return
* - index : Slot index
* - @c ESP_ERR_INVALID_ARG : invalid slot parameter
* - @c ESP_ERR_NOT_FOUND : The slot does not exist
*/
int esp_ble_mesh_dfu_slot_img_idx_get(const esp_ble_mesh_dfu_slot_t *slot);
#endif /* _ESP_BLE_MESH_FW_SLOT_API_H_ */

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -9,51 +9,86 @@
#include "esp_ble_mesh_defs.h"
#if CONFIG_BLE_MESH_MBT_SRV || CONFIG_BLE_MESH_MBT_CLI
#ifndef _BLE_MESH_MBT_DEPRECATE_WARN
#define _BLE_MESH_MBT_DEPRECATE_WARN
#warning "warning: 'All content in this document, including data structures and APIs, will be deprecated."
#endif
#endif /* CONFIG_BLE_MESH_MBT_SRV || CONFIG_BLE_MESH_MBT_CLI */
#ifdef __cplusplus
extern "C" {
#endif
#if CONFIG_IDF_CI_BUILD
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
/** @cond */
#if (CONFIG_BLE_MESH_MBT_SRV && CONFIG_BLE_MESH_BLOB_SRV) || \
(CONFIG_BLE_MESH_MBT_CLI && CONFIG_BLE_MESH_BLOB_CLI)
#error "BLOB Transfer Model and BLOB Model cannot be enabled at the same time"
#endif
/** @endcond */
/** @deprecated This macro will be deprecated in future versions. */
#define ESP_BLE_MESH_MODEL_OP_BLOB_TRANSFER_GET ESP_BLE_MESH_MODEL_OP_2(0x83, 0x00)
/** @deprecated This macro will be deprecated in future versions. */
#define ESP_BLE_MESH_MODEL_OP_BLOB_TRANSFER_START ESP_BLE_MESH_MODEL_OP_2(0x83, 0x01)
/** @deprecated This macro will be deprecated in future versions. */
#define ESP_BLE_MESH_MODEL_OP_BLOB_TRANSFER_CANCEL ESP_BLE_MESH_MODEL_OP_2(0x83, 0x02)
/** @deprecated This macro will be deprecated in future versions. */
#define ESP_BLE_MESH_MODEL_OP_BLOB_TRANSFER_STATUS ESP_BLE_MESH_MODEL_OP_2(0x83, 0x03)
/** @deprecated This macro will be deprecated in future versions. */
#define ESP_BLE_MESH_MODEL_OP_BLOB_BLOCK_GET ESP_BLE_MESH_MODEL_OP_2(0x83, 0x05)
/** @deprecated This macro will be deprecated in future versions. */
#define ESP_BLE_MESH_MODEL_OP_BLOB_BLOCK_START ESP_BLE_MESH_MODEL_OP_2(0x83, 0x04)
/** @deprecated This macro will be deprecated in future versions. */
#define ESP_BLE_MESH_MODEL_OP_BLOB_PARTIAL_BLOCK_REPORT ESP_BLE_MESH_MODEL_OP_1(0x65)
/** @deprecated This macro will be deprecated in future versions. */
#define ESP_BLE_MESH_MODEL_OP_BLOB_BLOCK_STATUS ESP_BLE_MESH_MODEL_OP_1(0x67)
/** @deprecated This macro will be deprecated in future versions. */
#define ESP_BLE_MESH_MODEL_OP_BLOB_CHUNK_TRANSFER ESP_BLE_MESH_MODEL_OP_1(0x66)
/** @deprecated This macro will be deprecated in future versions. */
#define ESP_BLE_MESH_MODEL_OP_BLOB_INFORMATION_GET ESP_BLE_MESH_MODEL_OP_2(0x83, 0x06)
/** @deprecated This macro will be deprecated in future versions. */
#define ESP_BLE_MESH_MODEL_OP_BLOB_INFORMATION_STATUS ESP_BLE_MESH_MODEL_OP_2(0x83, 0x07)
/** @deprecated This macro will be deprecated in future versions. */
#define ESP_BLE_MESH_BLOB_ID_SIZE 8
/** @def ESP_BLE_MESH_MODEL_MBT_CLI
/** @def ESP_BLE_MESH_MODEL_MBT_CLI
*
* @brief Define a new BLOB Transfer Client model.
* @brief Define a new BLOB Transfer Client model.
*
* @note This API needs to be called for each element on which
* the application needs to have a BLOB Transfer Client model.
* @note This API needs to be called for each element on which
* the application needs to have a BLOB Transfer Client model.
*
* @param cli_pub Pointer to the unique struct esp_ble_mesh_model_pub_t.
* @param cli_data Pointer to the unique struct esp_ble_mesh_client_t.
* @deprecated This macro will be deprecated in future versions.
*
* @return New BLOB Transfer Client model instance.
* @param cli_pub Pointer to unique struct esp_ble_mesh_model_pub_t.
* @param cli_data Pointer to unique struct esp_ble_mesh_client_t.
*
* @return New BLOB Transfer Client model instance.
*/
#define ESP_BLE_MESH_MODEL_MBT_CLI(cli_pub, cli_data) \
ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_MBT_CLI, \
NULL, cli_pub, cli_data)
/** @def ESP_BLE_MESH_MODEL_MBT_SRV
/** @def ESP_BLE_MESH_MODEL_MBT_SRV
*
* @brief Define a new BLOB Transfer Server model.
* @brief Define a new BLOB Transfer Server model.
*
* @note This API needs to be called for each element on which
* the application needs to have a BLOB Transfer Server model.
* @note This API needs to be called for each element on which
* the application needs to have a BLOB Transfer Server model.
*
* @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t.
* @param srv_data Pointer to the unique struct esp_ble_mesh_blob_trans_srv_t.
* @deprecated This macro will be deprecated in future versions.
*
* @return New BLOB Transfer Server model instance.
* @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t.
* @param srv_data Pointer to the unique struct esp_ble_mesh_blob_trans_srv_t.
*
* @return New BLOB Transfer Server model instance.
*/
#define ESP_BLE_MESH_MODEL_MBT_SRV(srv_pub, srv_data) \
ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_MBT_SRV, \
@@ -61,125 +96,125 @@ extern "C" {
/** BLOB Transfer Server model context */
typedef struct {
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
} esp_ble_mesh_mbt_srv_t;
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
} esp_ble_mesh_mbt_srv_t __attribute__((deprecated));
/** Parameters of BLOB receiver */
typedef struct {
uint16_t unicast_addr; /*!< Unicast address of the server */
uint8_t retrieved_transfer_phase; /*!< Retrieved transfer phase of the server */
uint8_t status:4; /*!< Status of the last operation */
uint16_t blocks_not_received_len; /*!< Indicates the length which blocks were not received by the server. */
uint8_t *blocks_not_received; /*!< Indicates which blocks were not received by the server. */
uint16_t missing_chunks_len; /*!< Indicates which chunks were not received in the current block */
uint8_t *missing_chunks; /*!< Indicates which chunks were not received by the server in the current block */
/* The followings are the additional information contained in status messages. */
uint8_t transfer_mode:2; /*!< BLOB transfer mode */
uint8_t expected_blob_id[ESP_BLE_MESH_BLOB_ID_SIZE]; /*!< Expected BLOB identifier list */
uint32_t blob_size; /*!< BLOB size in octets */
uint8_t block_size_log; /*!< Indicates the block size */
uint16_t transfer_mtu_size; /*!< MTU size in octets */
bool block_status_recv; /*!< Indicate if Blob Block Status is received as a response. */
} esp_ble_mesh_blob_receiver_t; /*!< Structure of BLOB receiver */
uint16_t unicast_addr; /*!< Unicast address of the server */
uint8_t retrieved_transfer_phase; /*!< Retrieved transfer phase of the server */
uint8_t status: 4; /*!< Status of the last operation */
uint16_t blocks_not_received_len; /*!< Indicates the length which blocks were not received by the server. */
uint8_t *blocks_not_received; /*!< Indicates which blocks were not received by the server. */
uint16_t missing_chunks_len; /*!< Indicates which chunks were not received in the current block */
uint8_t *missing_chunks; /*!< Indicates which chunks were not received by the server in the current block */
/* The following are the additional information contained in status messages. */
uint8_t transfer_mode: 2; /*!< BLOB transfer mode */
uint8_t expected_blob_id[ESP_BLE_MESH_BLOB_ID_SIZE]; /*!< Expected BLOB identifier list */
uint32_t blob_size; /*!< BLOB size in octets */
uint8_t block_size_log; /*!< Indicates the block size */
uint16_t transfer_mtu_size; /*!< MTU size in octets */
bool block_status_recv; /*!< Indicate if Blob Block Status is received as a response. */
} esp_ble_mesh_blob_receiver_t __attribute__((deprecated)); /*!< Structure of BLOB receiver */
/** Parameters of BLOB Information Status */
typedef struct {
uint8_t min_block_size_log; /*!< Min Block Size Log */
uint8_t max_block_size_log; /*!< Max Block Size Log */
uint16_t max_total_chunks; /*!< Max Total Chunks */
uint16_t max_chunk_size; /*!< Max Chunk Size */
uint32_t max_blob_size; /*!< Max BLOB Size */
uint16_t server_mtu_size; /*!< Server MTU size */
uint8_t supported_transfer_mode; /*!< Supported Transfer Mode */
} esp_ble_mesh_blob_capabilities_t; /*!< Parameters of BLOB Information Status */
uint8_t min_block_size_log; /*!< Min Block Size Log */
uint8_t max_block_size_log; /*!< Max Block Size Log */
uint16_t max_total_chunks; /*!< Max Total Chunks */
uint16_t max_chunk_size; /*!< Max Chunk Size */
uint32_t max_blob_size; /*!< Max BLOB Size */
uint16_t server_mtu_size; /*!< Server MTU size */
uint8_t supported_transfer_mode; /*!< Supported Transfer Mode */
} esp_ble_mesh_blob_capabilities_t __attribute__((deprecated)); /*!< Parameters of BLOB Information Status */
/** Parameters of BLOB retrieve capabilities */
typedef struct {
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
uint8_t unicast_addr_count; /*!< The count of unicast address */
uint16_t *unicast_addr; /*!< Unicast address list */
} esp_ble_mesh_retrieve_capabilities_t; /*!< Parameters of BLOB retrieve capabilities */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
uint8_t unicast_addr_count; /*!< The count of unicast address */
uint16_t *unicast_addr; /*!< Unicast address list */
} esp_ble_mesh_retrieve_capabilities_t __attribute__((deprecated)); /*!< Parameters of BLOB retrieve capabilities */
/** Parameters of BLOB transfer */
typedef struct {
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
uint8_t unicast_addr_count; /*!< The count of unicast address */
uint16_t *unicast_addr; /*!< Unicast address list */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
uint8_t blob_id[ESP_BLE_MESH_BLOB_ID_SIZE]; /*!< BLOB identifier list */
uint32_t blob_size; /*!< BLOB size in octets */
uint8_t *blob_data; /*!< BLOB data */
uint8_t transfer_mode; /*!< BLOB transfer mode */
uint16_t client_timeout_base; /*!< Time wait for messages from the serve */
} esp_ble_mesh_transfer_blob_t; /*!< Parameters of BLOB transfer */
uint8_t unicast_addr_count; /*!< The count of unicast address */
uint16_t *unicast_addr; /*!< Unicast address list */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
uint8_t blob_id[ESP_BLE_MESH_BLOB_ID_SIZE]; /*!< BLOB identifier list */
uint32_t blob_size; /*!< BLOB size in octets */
uint8_t *blob_data; /*!< BLOB data */
uint8_t transfer_mode; /*!< BLOB transfer mode */
uint16_t client_timeout_base; /*!< Time wait for messages from the serve */
} esp_ble_mesh_transfer_blob_t __attribute__((deprecated)); /*!< Parameters of BLOB transfer */
/** Parameters of BLOB Block Status message */
typedef struct {
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
uint16_t block_number; /*!< Block number of the current block */
uint16_t chunk_size; /*!< Chunk Size (in octets) for the current block */
} esp_ble_mesh_send_block_t; /*!< BLOB Block Status message structure */
uint16_t block_number; /*!< Block number of the current block */
uint16_t chunk_size; /*!< Chunk Size (in octets) for the current block */
} esp_ble_mesh_send_block_t __attribute__((deprecated)); /*!< BLOB Block Status message structure */
/** Parameters of BLOB send message */
typedef struct {
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
} esp_ble_mesh_send_data_t; /*!< Parameters of BLOB send message */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
} esp_ble_mesh_send_data_t __attribute__((deprecated)); /*!< Parameters of BLOB send message */
/** Parameters of determine Block Status message */
typedef struct {
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
} esp_ble_mesh_determine_block_status_t; /*!< Parameters of determine Block Status message */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
} esp_ble_mesh_determine_block_status_t __attribute__((deprecated)); /*!< Parameters of determine Block Status message */
/** Parameters of determine Block Status message */
typedef struct {
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
uint8_t unicast_addr_count; /*!< The count of unicast address */
uint16_t *unicast_addr; /*!< Unicast address list */
} esp_ble_mesh_determine_transfer_status_t; /*!< Parameters of determine Block Status message */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
uint8_t unicast_addr_count; /*!< The count of unicast address */
uint16_t *unicast_addr; /*!< Unicast address list */
} esp_ble_mesh_determine_transfer_status_t __attribute__((deprecated)); /*!< Parameters of determine Block Status message */
/** Parameters of cancel transfer message */
typedef struct {
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
uint8_t unicast_addr_count; /*!< The count of unicast address */
uint16_t *unicast_addr; /*!< Unicast address list */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
uint8_t unicast_addr_count; /*!< The count of unicast address */
uint16_t *unicast_addr; /*!< Unicast address list */
uint8_t blob_id[ESP_BLE_MESH_BLOB_ID_SIZE]; /*!< BLOB identifier list */
} esp_ble_mesh_cancel_transfer_t; /*!< Parameters of cancel transfer message */
uint8_t blob_id[ESP_BLE_MESH_BLOB_ID_SIZE]; /*!< BLOB identifier list */
} esp_ble_mesh_cancel_transfer_t __attribute__((deprecated)); /*!< Parameters of cancel transfer message */
/**
* @brief BLOB Transfer Client model procedure result
@@ -193,113 +228,113 @@ typedef struct {
typedef union {
/** Retrieve capabilities status */
struct {
int error_code; /*!< Result of starting Retrieve Capabilities procedure */
esp_ble_mesh_retrieve_capabilities_t input; /*!< Input of starting Retrieve Capabilities procedure */
} retrieve_capabilities_status; /*!< Retrieve capabilities status */
int error_code; /*!< Result of starting Retrieve Capabilities procedure */
esp_ble_mesh_retrieve_capabilities_t input; /*!< Input of starting Retrieve Capabilities procedure */
} retrieve_capabilities_status; /*!< Retrieve capabilities status */
/** Transfer BLOB status */
struct {
int error_code; /*!< Result of starting Transfer BLOB procedure */
esp_ble_mesh_transfer_blob_t input; /*!< Input of starting Transfer BLOB procedure */
} transfer_blob_status; /*!< Transfer BLOB status */
int error_code; /*!< Result of starting Transfer BLOB procedure */
esp_ble_mesh_transfer_blob_t input; /*!< Input of starting Transfer BLOB procedure */
} transfer_blob_status; /*!< Transfer BLOB status */
/** Send block status */
struct {
int error_code; /*!< Result of starting Send Block sub-procedure */
esp_ble_mesh_send_block_t input; /*!< Input of starting Send Block sub-procedure */
} send_block_status; /*!< Send block status */
int error_code; /*!< Result of starting Send Block sub-procedure */
esp_ble_mesh_send_block_t input; /*!< Input of starting Send Block sub-procedure */
} send_block_status; /*!< Send block status */
/** Send data status */
struct {
int error_code; /*!< Result of starting Send Data sub-procedure */
esp_ble_mesh_send_data_t input; /*!< Input of starting Send Data sub-procedure */
} send_data_status; /*!< Send data status */
int error_code; /*!< Result of starting Send Data sub-procedure */
esp_ble_mesh_send_data_t input; /*!< Input of starting Send Data sub-procedure */
} send_data_status; /*!< Send data status */
/** Determine block status */
struct {
int error_code; /*!< Result of starting Determine Block Status sub-procedure */
esp_ble_mesh_determine_block_status_t input; /*!< Input of starting Determine Block Status sub-procedure */
} determine_block_status_status; /*!< Determine block status */
int error_code; /*!< Result of starting Determine Block Status sub-procedure */
esp_ble_mesh_determine_block_status_t input; /*!< Input of starting Determine Block Status sub-procedure */
} determine_block_status_status; /*!< Determine block status */
/** Determine transfer status */
struct {
int error_code; /*!< Result of starting Determine Transfer Status procedure */
esp_ble_mesh_determine_transfer_status_t input; /*!< Input of starting Determine Transfer Status procedure */
} determine_transfer_status_status; /*!< Determine transfer status */
int error_code; /*!< Result of starting Determine Transfer Status procedure */
esp_ble_mesh_determine_transfer_status_t input; /*!< Input of starting Determine Transfer Status procedure */
} determine_transfer_status_status; /*!< Determine transfer status */
/** Cancel transfer status */
struct {
int error_code; /*!< Result of starting Cancel Transfer procedure */
esp_ble_mesh_cancel_transfer_t input; /*!< Input of starting Cancel Transfer procedure */
} cancel_transfer_status; /*!< Cancel transfer status */
int error_code; /*!< Result of starting Cancel Transfer procedure */
esp_ble_mesh_cancel_transfer_t input; /*!< Input of starting Cancel Transfer procedure */
} cancel_transfer_status; /*!< Cancel transfer status */
/** Retrieve capabilities complete */
struct {
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Retrieve Capabilities procedure */
} retrieve_capabilities_comp; /*!< Retrieve capabilities complete */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Retrieve Capabilities procedure */
} retrieve_capabilities_comp; /*!< Retrieve capabilities complete */
/** Transfer BLOB complete */
struct {
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Transfer BLOB procedure */
} transfer_blob_comp; /*!< Transfer BLOB complete */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Transfer BLOB procedure */
} transfer_blob_comp; /*!< Transfer BLOB complete */
/** Send block complete */
struct {
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Send Block sub-procedure */
} send_block_comp; /*!< Send block complete */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Send Block sub-procedure */
} send_block_comp; /*!< Send block complete */
/** Send data complete */
struct {
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Send Data sub-procedure */
} send_data_comp; /*!< Send data complete */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Send Data sub-procedure */
} send_data_comp; /*!< Send data complete */
/** Determine block status complete */
struct {
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Determine Block Status sub-procedure */
} determine_block_status_comp; /*!< Determine block status complete */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Determine Block Status sub-procedure */
} determine_block_status_comp; /*!< Determine block status complete */
/** Determine transfer status complete */
struct {
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Determine Transfer Status procedure */
} determine_transfer_status_comp; /*!< Determine transfer status complete */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Determine Transfer Status procedure */
} determine_transfer_status_comp; /*!< Determine transfer status complete */
/** Cancel transfer complete */
struct {
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Cancel Transfer procedure */
} cancel_transfer_comp; /*!< Cancel transfer complete */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Cancel Transfer procedure */
} cancel_transfer_comp; /*!< Cancel transfer complete */
/** Set transfer TTL */
struct {
int error_code; /*!< Result of setting Transfer TTL state */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t transfer_ttl; /*!< Transfer TTL state */
} set_transfer_ttl; /*!< Set transfer TTL */
int error_code; /*!< Result of setting Transfer TTL state */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t transfer_ttl; /*!< Transfer TTL state */
} set_transfer_ttl; /*!< Set transfer TTL */
/** Clear transfer TTL */
struct {
int error_code; /*!< Result of clearing Transfer TTL state */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
} clear_transfer_ttl; /*!< Clear transfer TTL */
int error_code; /*!< Result of clearing Transfer TTL state */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
} clear_transfer_ttl; /*!< Clear transfer TTL */
/** Set application index */
struct {
int error_code; /*!< Result of setting AppKey Index state */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint16_t app_idx; /*!< AppKey Index state */
} set_app_idx; /*!< Set application index */
int error_code; /*!< Result of setting AppKey Index state */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint16_t app_idx; /*!< AppKey Index state */
} set_app_idx; /*!< Set application index */
/** Clear application index */
struct {
int error_code; /*!< Result of clearing AppKey Index state */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
} clear_app_idx; /*!< Clear application index */
int error_code; /*!< Result of clearing AppKey Index state */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
} clear_app_idx; /*!< Clear application index */
/** Set multicast address */
struct {
int error_code; /*!< Result of setting Multicast Address state */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint16_t multicast_addr; /*!< Multicast Address state */
} set_multicast_addr; /*!< Set multicast address */
int error_code; /*!< Result of setting Multicast Address state */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint16_t multicast_addr; /*!< Multicast Address state */
} set_multicast_addr; /*!< Set multicast address */
/** Clear multicast address */
struct {
int error_code; /*!< Result of clearing Multicast Address state */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
} clear_multicast_addr; /*!< Clear multicast address */
} esp_ble_mesh_mbt_client_cb_value_t; /*!< BLOB Transfer Client model callback values union */
int error_code; /*!< Result of clearing Multicast Address state */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
} clear_multicast_addr; /*!< Clear multicast address */
} esp_ble_mesh_mbt_client_cb_value_t; /*!< BLOB Transfer Client model callback values union */
/** BLOB Transfer Client model callback parameters */
typedef struct {
esp_ble_mesh_mbt_client_cb_value_t value; /*!< BLOB Transfer Client model callback values */
} esp_ble_mesh_mbt_client_cb_param_t; /*!< BLOB Transfer Client model callback parameters */
esp_ble_mesh_mbt_client_cb_value_t value; /*!< BLOB Transfer Client model callback values */
} esp_ble_mesh_mbt_client_cb_param_t __attribute__((deprecated)); /*!< BLOB Transfer Client model callback parameters */
/**
* This enum value is the event of BLOB Transfer Client model.
@@ -327,30 +362,30 @@ typedef enum {
ESP_BLE_MESH_MBT_CLIENT_SET_MULTICAST_ADDR_COMP_EVT,
ESP_BLE_MESH_MBT_CLIENT_CLEAR_MULTICAST_ADDR_COMP_EVT,
ESP_BLE_MESH_MBT_CLIENT_EVT_MAX,
} esp_ble_mesh_mbt_client_cb_event_t;
} esp_ble_mesh_mbt_client_cb_event_t __attribute__((deprecated));
/** Parameters of initialize BLOB receive */
typedef struct {
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t blob_id[ESP_BLE_MESH_BLOB_ID_SIZE]; /*!< BLOB identifier list */
uint16_t timeout; /*!< Timeout */
uint8_t transfer_ttl; /*!< Transfer TTL state */
} esp_ble_mesh_initialize_blob_receive_t; /*!< Structure of initialize BLOB receive */
uint8_t blob_id[ESP_BLE_MESH_BLOB_ID_SIZE]; /*!< BLOB identifier list */
uint16_t timeout; /*!< Timeout */
uint8_t transfer_ttl; /*!< Transfer TTL state */
} esp_ble_mesh_initialize_blob_receive_t __attribute__((deprecated)); /*!< Structure of initialize BLOB receive */
/** Parameters of cancel BLOB receive */
typedef struct {
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t blob_id[ESP_BLE_MESH_BLOB_ID_SIZE]; /*!< BLOB identifier list */
} esp_ble_mesh_cancel_blob_receive_t;/*!< */
} esp_ble_mesh_cancel_blob_receive_t __attribute__((deprecated));/*!< */
/** Parameters of cancel BLOB receive */
typedef struct {
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
esp_ble_mesh_blob_capabilities_t caps; /*!< Parameters of BLOB Information Status */
} esp_ble_mesh_set_blob_capabilities_t;/*!< */
} esp_ble_mesh_set_blob_capabilities_t __attribute__((deprecated));
/**
* @brief BLOB Transfer Server model callback value union
@@ -358,61 +393,61 @@ typedef struct {
typedef union {
/** Initialize BLOB receive complete */
struct {
int error_code; /*!< Result of initializing BLOB receive */
esp_ble_mesh_initialize_blob_receive_t input; /*!< Input of initializing BLOB receive */
} initialize_blob_receive_comp; /*!< Initialize BLOB receive complete */
int error_code; /*!< Result of initializing BLOB receive */
esp_ble_mesh_initialize_blob_receive_t input; /*!< Input of initializing BLOB receive */
} initialize_blob_receive_comp; /*!< Initialize BLOB receive complete */
/** Cancel BLOB receive complete */
struct {
int error_code; /*!< Result of canceling BLOB receive */
esp_ble_mesh_cancel_blob_receive_t input; /*!< Input of canceling BLOB receive */
} cancel_blob_receive_comp; /*!< Cancel BLOB receive complete */
int error_code; /*!< Result of canceling BLOB receive */
esp_ble_mesh_cancel_blob_receive_t input; /*!< Input of canceling BLOB receive */
} cancel_blob_receive_comp; /*!< Cancel BLOB receive complete */
/** Set BLOB capabilities complete */
struct {
int error_code; /*!< Result of setting BLOB capabilities */
esp_ble_mesh_set_blob_capabilities_t input; /*!< Input of setting BLOB capabilities */
} set_blob_capabilities_comp; /*!< Set BLOB capabilities complete */
int error_code; /*!< Result of setting BLOB capabilities */
esp_ble_mesh_set_blob_capabilities_t input; /*!< Input of setting BLOB capabilities */
} set_blob_capabilities_comp; /*!< Set BLOB capabilities complete */
/** BLOB transfer get */
struct {
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Transfer Get message context */
} blob_transfer_get; /*!< BLOB transfer get */
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Transfer Get message context */
} blob_transfer_get; /*!< BLOB transfer get */
/** BLOB transfer start */
struct {
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Transfer Start message context */
} blob_transfer_start; /*!< BLOB transfer start */
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Transfer Start message context */
} blob_transfer_start; /*!< BLOB transfer start */
/** BLOB transfer cancel */
struct {
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Transfer Cancel message context */
} blob_transfer_cancel; /*!< BLOB transfer cancel */
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Transfer Cancel message context */
} blob_transfer_cancel; /*!< BLOB transfer cancel */
/** BLOB block get */
struct {
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Block Get message context */
} blob_block_get; /*!< BLOB block get */
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Block Get message context */
} blob_block_get; /*!< BLOB block get */
/** BLOB block start */
struct {
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Block Start message context */
} blob_block_start; /*!< BLOB block start */
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Block Start message context */
} blob_block_start; /*!< BLOB block start */
/** BLOB chunk transfer */
struct {
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Chunk Transfer message context */
} blob_chunk_transfer; /*!< BLOB chunk transfer */
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Chunk Transfer message context */
} blob_chunk_transfer; /*!< BLOB chunk transfer */
/** BLOB information get */
struct {
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Information Get message context */
} blob_information_get; /*!< BLOB information get */
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Information Get message context */
} blob_information_get; /*!< BLOB information get */
/** Block receive complete */
struct {
esp_ble_mesh_msg_ctx_t ctx; /*!< Information of receiving BLOB block completely */
} block_receive_comp; /*!< Block receive complete */
esp_ble_mesh_msg_ctx_t ctx; /*!< Information of receiving BLOB block completely */
} block_receive_comp; /*!< Block receive complete */
/** BLOB receive complete */
struct {
esp_ble_mesh_msg_ctx_t ctx; /*!< Information of receiving BLOB completely */
} blob_receive_comp; /*!< BLOB receive complete */
} esp_ble_mesh_mbt_server_cb_value_t; /*!< BLOB Transfer Server model callback value union */
esp_ble_mesh_msg_ctx_t ctx; /*!< Information of receiving BLOB completely */
} blob_receive_comp; /*!< BLOB receive complete */
} esp_ble_mesh_mbt_server_cb_value_t __attribute__((deprecated)); /*!< BLOB Transfer Server model callback value union */
/** BLOB Transfer Server model callback parameters */
typedef struct {
esp_ble_mesh_mbt_server_cb_value_t value; /*!< Value of the received blob transfer messages */
} esp_ble_mesh_mbt_server_cb_param_t; /*!< BLOB Transfer Server model callback parameters */
esp_ble_mesh_mbt_server_cb_value_t value; /*!< Value of the received blob transfer messages */
} esp_ble_mesh_mbt_server_cb_param_t __attribute__((deprecated)); /*!< BLOB Transfer Server model callback parameters */
/** This enum value is the event of BLOB Transfer Server model */
typedef enum {
@@ -430,7 +465,7 @@ typedef enum {
ESP_BLE_MESH_MBT_SERVER_BLOB_RECEIVE_COMP_EVT,
ESP_BLE_MESH_MBT_SERVER_BLOB_RECEIVE_TIMEOUT_EVT,
ESP_BLE_MESH_MBT_SERVER_EVT_MAX,
} esp_ble_mesh_mbt_server_cb_event_t;
} esp_ble_mesh_mbt_server_cb_event_t __attribute__((deprecated));
/**
* @brief BLOB Transfer Client model callback function type
@@ -453,96 +488,116 @@ typedef void (* esp_ble_mesh_mbt_server_cb_t)(esp_ble_mesh_mbt_server_cb_event_t
/**
* @brief Register BLE Mesh BLOB Transfer Client model callback.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] callback: Pointer to the callback function.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_register_mbt_client_callback(esp_ble_mesh_mbt_client_cb_t callback);
esp_err_t esp_ble_mesh_register_mbt_client_callback(esp_ble_mesh_mbt_client_cb_t callback) __attribute__((deprecated));
/**
* @brief Register BLE Mesh BLOB Transfer Server model callback.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] callback: Pointer to the callback function.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_register_mbt_server_callback(esp_ble_mesh_mbt_server_cb_t callback);
esp_err_t esp_ble_mesh_register_mbt_server_callback(esp_ble_mesh_mbt_server_cb_t callback) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client starts Retrieve Capabilities procedure.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] input: The input of Retrieve Capabilities procedure.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_mbt_client_retrieve_capabilities(esp_ble_mesh_retrieve_capabilities_t *input);
esp_err_t esp_ble_mesh_mbt_client_retrieve_capabilities(esp_ble_mesh_retrieve_capabilities_t *input) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client starts Transfer BLOB procedure.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] input: The input of Transfer BLOB procedure.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_mbt_client_transfer_blob(esp_ble_mesh_transfer_blob_t *input);
esp_err_t esp_ble_mesh_mbt_client_transfer_blob(esp_ble_mesh_transfer_blob_t *input) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client starts Send Block sub-procedure.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] input: The input of Send Block sub-procedure.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_mbt_client_send_block(esp_ble_mesh_send_block_t *input);
esp_err_t esp_ble_mesh_mbt_client_send_block(esp_ble_mesh_send_block_t *input) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client starts Send Data sub-procedure.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] input: The input of Send Data sub-procedure.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_mbt_client_send_data(esp_ble_mesh_send_data_t *input);
esp_err_t esp_ble_mesh_mbt_client_send_data(esp_ble_mesh_send_data_t *input) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client starts Determine Block Status sub-procedure.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] input: The input of Determine Block Status sub-procedure.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_mbt_client_determine_block_status(esp_ble_mesh_determine_block_status_t *input);
esp_err_t esp_ble_mesh_mbt_client_determine_block_status(esp_ble_mesh_determine_block_status_t *input) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client starts Determine Transfer Status procedure.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] input: The input of Determine Transfer Status procedure.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_mbt_client_determine_transfer_status(esp_ble_mesh_determine_transfer_status_t *input);
esp_err_t esp_ble_mesh_mbt_client_determine_transfer_status(esp_ble_mesh_determine_transfer_status_t *input) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client starts Cancel Transfer procedure.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] input: The input of Cancel Transfer procedure.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_mbt_client_cancel_transfer(esp_ble_mesh_cancel_transfer_t *input);
esp_err_t esp_ble_mesh_mbt_client_cancel_transfer(esp_ble_mesh_cancel_transfer_t *input) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client gets BLOB receiver.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] model: BLOB Transfer Client model.
* @param[in] unicast_addr: Unicast address of the BLOB receiver.
*
@@ -550,21 +605,25 @@ esp_err_t esp_ble_mesh_mbt_client_cancel_transfer(esp_ble_mesh_cancel_transfer_t
*
*/
const esp_ble_mesh_blob_receiver_t *esp_ble_mesh_mbt_client_get_blob_receiver(esp_ble_mesh_model_t *model,
uint16_t unicast_addr);
uint16_t unicast_addr) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client gets active BLOB receiver list.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] model: BLOB Transfer Client model.
*
* @return Active BLOB receiver list on success or NULL on failure.
*
*/
const esp_ble_mesh_blob_receiver_t **esp_ble_mesh_mbt_client_get_active_blob_receiver(esp_ble_mesh_model_t *model);
const esp_ble_mesh_blob_receiver_t **esp_ble_mesh_mbt_client_get_active_blob_receiver(esp_ble_mesh_model_t *model) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client gets BLOB transfer progress.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] model: BLOB Transfer Client model.
* @param[in] unicast_addr: Unicast address of the BLOB receiver.
* @param[in] block_percent: Block reception percent to be updated.
@@ -576,11 +635,13 @@ const esp_ble_mesh_blob_receiver_t **esp_ble_mesh_mbt_client_get_active_blob_rec
esp_err_t esp_ble_mesh_mbt_client_get_transfer_progress(esp_ble_mesh_model_t *model,
uint16_t unicast_addr,
uint8_t *block_percent,
uint8_t *chunk_percent);
uint8_t *chunk_percent) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client sets Transfer TTL state.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] model: BLOB Transfer Client model.
* @param[in] transfer_ttl: Transfer TTL state value.
*
@@ -588,21 +649,25 @@ esp_err_t esp_ble_mesh_mbt_client_get_transfer_progress(esp_ble_mesh_model_t *mo
*
*/
esp_err_t esp_ble_mesh_mbt_client_set_transfer_ttl(esp_ble_mesh_model_t *model,
uint8_t transfer_ttl);
uint8_t transfer_ttl) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client clear Transfer TTL state.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] model: BLOB Transfer Client model.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_mbt_client_clear_transfer_ttl(esp_ble_mesh_model_t *model);
esp_err_t esp_ble_mesh_mbt_client_clear_transfer_ttl(esp_ble_mesh_model_t *model) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client sets AppKey Index state.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] model: BLOB Transfer Client model.
* @param[in] app_idx: AppKey Index state value.
*
@@ -610,21 +675,25 @@ esp_err_t esp_ble_mesh_mbt_client_clear_transfer_ttl(esp_ble_mesh_model_t *model
*
*/
esp_err_t esp_ble_mesh_mbt_client_set_app_idx(esp_ble_mesh_model_t *model,
uint16_t app_idx);
uint16_t app_idx) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client clear AppKey Index state.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] model: BLOB Transfer Client model.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_mbt_client_clear_app_idx(esp_ble_mesh_model_t *model);
esp_err_t esp_ble_mesh_mbt_client_clear_app_idx(esp_ble_mesh_model_t *model) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client sets Multicast Address state.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] model: BLOB Transfer Client model.
* @param[in] multicast_addr: Multicast Address state value.
*
@@ -632,51 +701,61 @@ esp_err_t esp_ble_mesh_mbt_client_clear_app_idx(esp_ble_mesh_model_t *model);
*
*/
esp_err_t esp_ble_mesh_mbt_client_set_multicast_addr(esp_ble_mesh_model_t *model,
uint16_t multicast_addr);
uint16_t multicast_addr) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client clear Multicast Address state.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] model: BLOB Transfer Client model.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_mbt_client_clear_multicast_addr(esp_ble_mesh_model_t *model);
esp_err_t esp_ble_mesh_mbt_client_clear_multicast_addr(esp_ble_mesh_model_t *model) __attribute__((deprecated));
/**
* @brief BLOB Transfer Server initializes BLOB receive.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] input: The input of initializing BLOB receive.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_mbt_server_initialize_blob_receive(esp_ble_mesh_initialize_blob_receive_t *input);
esp_err_t esp_ble_mesh_mbt_server_initialize_blob_receive(esp_ble_mesh_initialize_blob_receive_t *input) __attribute__((deprecated));
/**
* @brief BLOB Transfer Server cancels BLOB receive.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] input: The input of cancelling BLOB receive.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_mbt_server_cancel_blob_receive(esp_ble_mesh_cancel_blob_receive_t *input);
esp_err_t esp_ble_mesh_mbt_server_cancel_blob_receive(esp_ble_mesh_cancel_blob_receive_t *input) __attribute__((deprecated));
/**
* @brief BLOB Transfer Server sets BLOB capabilities.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] input: The input of setting BLOB capabilities.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_mbt_server_set_blob_capabilities(esp_ble_mesh_set_blob_capabilities_t *input);
esp_err_t esp_ble_mesh_mbt_server_set_blob_capabilities(esp_ble_mesh_set_blob_capabilities_t *input) __attribute__((deprecated));
/**
* @brief BLOB Transfer Server gets current BLOB reception progress.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] model: BLOB Transfer Server model.
* @param[in] reception_progress: Reception progress to be updated.
*
@@ -684,7 +763,11 @@ esp_err_t esp_ble_mesh_mbt_server_set_blob_capabilities(esp_ble_mesh_set_blob_ca
*
*/
esp_err_t esp_ble_mesh_mbt_server_get_blob_reception_progress(esp_ble_mesh_model_t *model,
uint8_t *reception_progress);
uint8_t *reception_progress) __attribute__((deprecated));
#if CONFIG_IDF_CI_BUILD
#pragma GCC diagnostic pop
#endif
#ifdef __cplusplus
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,79 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <errno.h>
#include "dfu_slot.h"
#include "esp_ble_mesh_dfu_model_api.h"
#include "esp_ble_mesh_dfu_slot_api.h"
#include "btc_ble_mesh_dfu_slot.h"
#if CONFIG_BLE_MESH_DFU_SLOTS
int btc_ble_mesh_dfu_slot_count(void)
{
return bt_mesh_dfu_slot_count();
}
struct esp_ble_mesh_dfu_slot *btc_ble_mesh_dfu_slot_reserve(void)
{
return (struct esp_ble_mesh_dfu_slot *)bt_mesh_dfu_slot_reserve();
}
int btc_ble_mesh_dfu_slot_info_set(struct esp_ble_mesh_dfu_slot *dfu_slot, size_t size,
const uint8_t *metadata, size_t metadata_len)
{
return bt_mesh_dfu_slot_info_set((struct bt_mesh_dfu_slot *) dfu_slot, size,
metadata, metadata_len);
}
int btc_ble_mesh_dfu_slot_fwid_set(struct esp_ble_mesh_dfu_slot *dfu_slot,
const uint8_t *fwid, size_t fwid_len)
{
return bt_mesh_dfu_slot_fwid_set((struct bt_mesh_dfu_slot *) dfu_slot, fwid,
fwid_len);
}
int btc_ble_mesh_dfu_slot_commit(struct esp_ble_mesh_dfu_slot *dfu_slot)
{
return bt_mesh_dfu_slot_commit((struct bt_mesh_dfu_slot *) dfu_slot);
}
void btc_ble_mesh_dfu_slot_release(const struct esp_ble_mesh_dfu_slot *dfu_slot)
{
bt_mesh_dfu_slot_release((const struct bt_mesh_dfu_slot *)dfu_slot);
}
int btc_ble_mesh_dfu_slot_del(const struct esp_ble_mesh_dfu_slot *slot)
{
return bt_mesh_dfu_slot_del((const struct bt_mesh_dfu_slot *)slot);
}
void btc_ble_mesh_dfu_slot_del_all(void)
{
bt_mesh_dfu_slot_del_all();
}
const struct esp_ble_mesh_dfu_slot *btc_ble_mesh_dfu_slot_at(uint16_t img_idx)
{
return (const struct esp_ble_mesh_dfu_slot *)bt_mesh_dfu_slot_at(img_idx);
}
int btc_ble_mesh_dfu_slot_get(const uint8_t *fwid, size_t fwid_len, struct esp_ble_mesh_dfu_slot **slot)
{
return bt_mesh_dfu_slot_get(fwid, fwid_len, (struct bt_mesh_dfu_slot **)slot);
}
int btc_ble_mesh_dfu_slot_img_idx_get(const struct esp_ble_mesh_dfu_slot *slot)
{
return bt_mesh_dfu_slot_img_idx_get((const struct bt_mesh_dfu_slot *)slot);
}
size_t btc_ble_mesh_dfu_slot_foreach(esp_ble_mesh_dfu_slot_cb_t cb, void *user_data)
{
return bt_mesh_dfu_slot_foreach((bt_mesh_dfu_slot_cb_t)cb, user_data);
}
#endif /* CONFIG_BLE_MESH_DFU_SLOTS */

View File

@@ -0,0 +1,123 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _BTC_BLE_MESH_DFU_MODEL_H_
#define _BTC_BLE_MESH_DFU_MODEL_H_
#include "btc/btc_manage.h"
#include "esp_ble_mesh_dfu_model_api.h"
#ifdef __cplusplus
extern "C" {
#endif
#if CONFIG_BLE_MESH_DFU_CLI
typedef enum {
BTC_BLE_MESH_ACT_DFU_CLIENT_GET_STATE,
BTC_BLE_MESH_ACT_DFU_CLIENT_IMG_SEND,
BTC_BLE_MESH_ACT_DFU_CLIENT_MAX,
} btc_ble_mesh_dfu_client_act_t;
typedef union {
struct {
esp_ble_mesh_client_common_param_t *params;
esp_ble_mesh_dfu_client_get_t *get;
} dfu_get;
struct {
struct esp_ble_mesh_dfu_cli *cli;
struct esp_ble_mesh_blob_cli_inputs *inputs;
struct esp_ble_mesh_blob_io *io;
struct esp_ble_mesh_dfu_cli_xfer *xfer;
} send_arg;
} btc_ble_mesh_dfu_client_args_t;
typedef enum {
BTC_BLE_MESH_EVT_DFU_CLIENT_TIMEOUT,
BTC_BLE_MESH_EVT_DFU_CLIENT_RECV_GET_RSP,
BTC_BLE_MESH_EVT_DFU_CLIENT_IMG_SEND_CMP,
BTC_BLE_MESH_EVT_DFU_CLIENT_MAX,
} btc_ble_mesh_dfu_client_cb_evt_t;
void btc_ble_mesh_dfu_client_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src);
void btc_ble_mesh_dfu_client_arg_deep_free(btc_msg_t *msg);
void bt_mesh_dfu_client_cb_evt_to_btc(uint32_t opcode, uint8_t event,
struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
const uint8_t *val, size_t len);
void btc_ble_mesh_dfu_client_call_handler(btc_msg_t *msg);
void btc_ble_mesh_dfu_client_cb_handler(btc_msg_t *msg);
uint8_t btc_ble_mesh_dfu_cli_progress(struct esp_ble_mesh_dfu_cli *cli);
#endif /* CONFIG_BLE_MESH_DFU_CLI */
#if CONFIG_BLE_MESH_DFU_SRV
void btc_ble_mesh_dfu_srv_verified(esp_ble_mesh_dfu_srv_t *srv);
void btc_ble_mesh_dfu_srv_rejected(esp_ble_mesh_dfu_srv_t *srv);
void btc_ble_mesh_dfu_srv_cancel(esp_ble_mesh_dfu_srv_t *srv);
void btc_ble_mesh_dfu_srv_applied(esp_ble_mesh_dfu_srv_t *srv);
bool btc_ble_mesh_dfu_srv_is_busy(const esp_ble_mesh_dfu_srv_t *srv);
uint8_t btc_ble_mesh_dfu_srv_progress(const esp_ble_mesh_dfu_srv_t *srv);
#endif /* CONFIG_BLE_MESH_DFU_SRV */
#if CONFIG_BLE_MESH_DFD_CLI
typedef enum {
BTC_BLE_MESH_ACT_DFD_CLIENT_GET,
BTC_BLE_MESH_ACT_DFD_CLIENT_SET,
BTC_BLE_MESH_ACT_DFD_CLIEND_SEND_COMP,
BTC_BLE_MESH_ACT_DFD_CLIENT_MAX,
} btc_ble_mesh_dfd_client_act_t;
typedef enum {
BTC_BLE_MESH_EVT_DFD_CLIENT_TIMEOUT,
BTC_BLE_MESH_EVT_DFD_CLIENT_RECV_RSP,
BTC_BLE_MESH_EVT_DFD_CLIENT_MAX,
} btc_ble_mesh_dfd_client_cb_evt_t;
typedef union {
struct {
esp_ble_mesh_client_common_param_t *params;
esp_ble_mesh_dfd_client_get_param_t *get;
} dfd_client_get;
struct {
esp_ble_mesh_client_common_param_t *params;
esp_ble_mesh_dfd_client_set_param_t *set;
} dfd_client_set;
} btc_ble_mesh_dfd_client_args_t;
void btc_ble_mesh_dfd_client_cb_handler(btc_msg_t *msg);
void btc_ble_mesh_dfd_client_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src);
void btc_ble_mesh_dfd_client_arg_deep_free(btc_msg_t *msg);
void btc_ble_mesh_dfd_client_rsp_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src);
void btc_ble_mesh_dfd_client_rsp_deep_free(btc_msg_t *msg);
void bt_mesh_dfd_client_cb_evt_to_btc(btc_ble_mesh_dfd_client_cb_evt_t event,
struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
const uint8_t *val, size_t len);
void btc_ble_mesh_dfd_client_call_handler(btc_msg_t *msg);
#endif /* CONFIG_BLE_MESH_DFD_CLI */
#if CONFIG_BLE_MESH_DFD_SRV
#if CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD
int btc_ble_mesh_dfd_srv_oob_check_complete(struct esp_ble_mesh_dfd_srv *srv,
const struct esp_ble_mesh_dfu_slot *slot, int status,
uint8_t *fwid, size_t fwid_len);
int btc_ble_mesh_dfd_srv_oob_store_complete(struct esp_ble_mesh_dfd_srv *srv,
const struct esp_ble_mesh_dfu_slot *slot, bool success,
size_t size, const uint8_t *metadata, size_t metadata_len);
#endif /* CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD */
#endif /* CONFIG_BLE_MESH_DFD_SRV */
#ifdef __cplusplus
}
#endif
#endif /* _BTC_BLE_MESH_DFU_MODEL_H_ */

View File

@@ -0,0 +1,36 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _BTC_BLE_MESH_DFU_SLOT_H_
#define _BTC_BLE_MESH_DFU_SLOT_H_
int btc_ble_mesh_dfu_slot_count(void);
struct esp_ble_mesh_dfu_slot *btc_ble_mesh_dfu_slot_reserve(void);
int btc_ble_mesh_dfu_slot_info_set(struct esp_ble_mesh_dfu_slot *dfu_slot, size_t size,
const uint8_t *metadata, size_t metadata_len);
int btc_ble_mesh_dfu_slot_fwid_set(struct esp_ble_mesh_dfu_slot *dfu_slot,
const uint8_t *fwid, size_t fwid_len);
int btc_ble_mesh_dfu_slot_commit(struct esp_ble_mesh_dfu_slot *dfu_slot);
void btc_ble_mesh_dfu_slot_release(const struct esp_ble_mesh_dfu_slot *dfu_slot);
int btc_ble_mesh_dfu_slot_del(const struct esp_ble_mesh_dfu_slot *slot);
void btc_ble_mesh_dfu_slot_del_all(void);
const struct esp_ble_mesh_dfu_slot *btc_ble_mesh_dfu_slot_at(uint16_t img_idx);
int btc_ble_mesh_dfu_slot_get(const uint8_t *fwid, size_t fwid_len, struct esp_ble_mesh_dfu_slot **slot);
int btc_ble_mesh_dfu_slot_img_idx_get(const struct esp_ble_mesh_dfu_slot *slot);
size_t btc_ble_mesh_dfu_slot_foreach(esp_ble_mesh_dfu_slot_cb_t cb, void *user_data);
#endif /* _BTC_BLE_MESH_DFU_SLOT_H_ */

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -14,6 +14,11 @@
extern "C" {
#endif
#if CONFIG_IDF_CI_BUILD
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
typedef enum {
BTC_BLE_MESH_ACT_MBT_CLIENT_RETRIEVE_CAPABILITIES,
BTC_BLE_MESH_ACT_MBT_CLIENT_TRANSFER_BLOB,
@@ -136,6 +141,10 @@ void bt_mesh_mbt_server_cb_evt_to_btc(uint8_t event,
struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx);
#if CONFIG_IDF_CI_BUILD
#pragma GCC diagnostic pop
#endif
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,699 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include "dfu_slot.h"
#include "dfu.h"
#include "net.h"
#include "transport.h"
#include "mesh_v1.1/dfu/dfd.h"
#include "mesh_v1.1/dfu/dfu_cli.h"
#include "mesh_v1.1/mbt/blob_srv.h"
#include "btc_ble_mesh_dfu_model.h"
#include "mesh_v1.1/dfu/dfd_cli.h"
#if CONFIG_BLE_MESH_DFD_CLI
static const bt_mesh_client_op_pair_t dfd_cli_pair[] = {
{BLE_MESH_DFD_OP_RECEIVERS_ADD, BLE_MESH_DFD_OP_RECEIVERS_STATUS},
{BLE_MESH_DFD_OP_RECEIVERS_DELETE_ALL, BLE_MESH_DFD_OP_RECEIVERS_STATUS},
{BLE_MESH_DFD_OP_RECEIVERS_GET, BLE_MESH_DFD_OP_RECEIVERS_LIST},
{BLE_MESH_DFD_OP_CAPABILITIES_GET, BLE_MESH_DFD_OP_CAPABILITIES_STATUS},
{BLE_MESH_DFD_OP_GET, BLE_MESH_DFD_OP_STATUS},
{BLE_MESH_DFD_OP_START, BLE_MESH_DFD_OP_STATUS},
{BLE_MESH_DFD_OP_SUSPEND, BLE_MESH_DFD_OP_STATUS},
{BLE_MESH_DFD_OP_CANCEL, BLE_MESH_DFD_OP_STATUS},
{BLE_MESH_DFD_OP_APPLY, BLE_MESH_DFD_OP_STATUS},
{BLE_MESH_DFD_OP_UPLOAD_GET, BLE_MESH_DFD_OP_UPLOAD_STATUS},
{BLE_MESH_DFD_OP_UPLOAD_START, BLE_MESH_DFD_OP_UPLOAD_STATUS},
{BLE_MESH_DFD_OP_UPLOAD_START_OOB, BLE_MESH_DFD_OP_UPLOAD_STATUS},
{BLE_MESH_DFD_OP_UPLOAD_CANCEL, BLE_MESH_DFD_OP_UPLOAD_STATUS},
{BLE_MESH_DFD_OP_FW_GET, BLE_MESH_DFD_OP_FW_STATUS},
{BLE_MESH_DFD_OP_FW_GET_BY_INDEX, BLE_MESH_DFD_OP_FW_STATUS},
{BLE_MESH_DFD_OP_FW_DELETE, BLE_MESH_DFD_OP_FW_STATUS},
{BLE_MESH_DFD_OP_FW_DELETE_ALL, BLE_MESH_DFD_OP_FW_STATUS},
};
static bt_mesh_mutex_t dfd_client_lock;
static void timeout_handler(struct k_work *work)
{
struct k_delayed_work *timer = NULL;
bt_mesh_client_node_t *node = NULL;
BT_WARN("DFDRspTmo");
bt_mesh_mutex_lock(&dfd_client_lock);
timer = CONTAINER_OF(work, struct k_delayed_work, work);
if (timer && !k_delayed_work_free(timer)) {
node = CONTAINER_OF(work, bt_mesh_client_node_t, timer.work);
if (node) {
bt_mesh_dfd_client_cb_evt_to_btc(BTC_BLE_MESH_EVT_DFD_CLIENT_TIMEOUT, node->model, &node->ctx, NULL, 0);
bt_mesh_client_free_node(node);
}
}
bt_mesh_mutex_unlock(&dfd_client_lock);
return;
}
static void dfd_client_recv_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
void *status, size_t len)
{
bt_mesh_client_node_t *node = NULL;
struct net_buf_simple buf = {0};
btc_ble_mesh_dfd_client_cb_evt_t evt = 0;
if (!model || !ctx) {
BT_ERR("%s,InvParam", __func__);
return;
}
buf.data = (uint8_t *)status;
buf.len = (uint16_t)len;
bt_mesh_mutex_lock(&dfd_client_lock);
node = bt_mesh_is_client_recv_publish_msg(model, ctx, &buf, true);
if (!node) {
BT_DBG("UnexpDfdStus:0x%04x", ctx->recv_op);
} else {
switch (ctx->recv_op) {
case BLE_MESH_DFD_OP_RECEIVERS_STATUS:
case BLE_MESH_DFD_OP_CAPABILITIES_GET:
case BLE_MESH_DFD_OP_RECEIVERS_LIST:
case BLE_MESH_DFD_OP_CAPABILITIES_STATUS:
case BLE_MESH_DFD_OP_STATUS:
case BLE_MESH_DFD_OP_UPLOAD_STATUS:
case BLE_MESH_DFD_OP_FW_STATUS:
evt = BTC_BLE_MESH_EVT_DFD_CLIENT_RECV_RSP;
break;
default:
BT_ERR("UnkwnOpc:%04x", node->opcode);
break;
}
if (!k_delayed_work_free(&node->timer)) {
bt_mesh_dfd_client_cb_evt_to_btc(evt, model, ctx, (const uint8_t *)status, len);
bt_mesh_client_free_node(node);
}
}
bt_mesh_mutex_unlock(&dfd_client_lock);
}
static void handle_receiver_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
dfd_status_t status = {0};
status.receiver_status.status = net_buf_simple_pull_u8(buf);
if (status.receiver_status.status > BLE_MESH_DFD_ERR_SUSPEND_FAILED) {
BT_ERR("InvSrvStu:%d", status.receiver_status.status);
return;
}
if (status.receiver_status.status != BLE_MESH_DFD_SUCCESS) {
BT_ERR("StusErr:%d", status);
return;
}
status.receiver_status.receiver_list_cnt = net_buf_simple_pull_le16(buf);
BT_DBG("RecvLstCnt:%d", status.receiver_status.receiver_list_cnt);
dfd_client_recv_status(model, ctx, &status, sizeof(status.receiver_status));
}
static void handle_receiver_list(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
int i = 0;
uint32_t target_info = 0;
dfd_status_t status = {0};
status.receiver_list.entries_cnt = net_buf_simple_pull_le16(buf);
status.receiver_list.first_index = net_buf_simple_pull_le16(buf);
status.receiver_list.entries = bt_mesh_calloc(status.receiver_list.entries_cnt * sizeof(target_node_entry_t));
for (i = 0; i < status.receiver_list.entries_cnt; i++) {
target_info = net_buf_simple_pull_le32(buf);
status.receiver_list.entries[i].addr = TARGET_ADDR(target_info);
status.receiver_list.entries[i].retrieved_update_phase = TARGET_UPDATE_PHASE(target_info);
status.receiver_list.entries[i].update_status = TARGET_UPDATE_STATUS(target_info);
status.receiver_list.entries[i].transfer_status = TARGET_TRANSFER_STATUS(target_info);
status.receiver_list.entries[i].transfer_progress = TARGET_TRANSFER_PROGRESS(target_info);
status.receiver_list.entries[i].update_fw_idx = net_buf_simple_pull_u8(buf);
}
dfd_client_recv_status(model, ctx, &status, sizeof(status.receiver_list));
bt_mesh_free(status.receiver_list.entries);
return;
}
static void handle_capabilities(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
dfd_status_t status = {0};
struct net_buf_simple url_scheme_names = {0};
status.dist_caps.max_receiver_list_sz = net_buf_simple_pull_le16(buf);
status.dist_caps.max_fw_list_sz = net_buf_simple_pull_le16(buf);
status.dist_caps.max_fw_sz = net_buf_simple_pull_le32(buf);
status.dist_caps.max_upload_space = net_buf_simple_pull_le32(buf);
status.dist_caps.remaining_upload_space = net_buf_simple_pull_le32(buf);
status.dist_caps.oob_retrieval_supported = net_buf_simple_pull_le32(buf);
if (buf->len) {
status.dist_caps.supported_url_scheme_names = &url_scheme_names;
net_buf_simple_init_with_data(status.dist_caps.supported_url_scheme_names, buf->data, buf->len);
net_buf_simple_pull_mem(buf, buf->len);
}
dfd_client_recv_status(model, ctx, &status, sizeof(status.dist_caps));
return;
}
static void handle_dfd_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
dfd_status_t status = {0};
uint8_t trans_mode_policy = 0;
status.dist_status.status = net_buf_simple_pull_u8(buf);
status.dist_status.dist_phase = net_buf_simple_pull_u8(buf);
if (buf->len != 0 && buf->len != 10) {
BT_ERR("Invalid data");
return;
}
status.dist_status.multicast_address = net_buf_simple_pull_le16(buf);
status.dist_status.appkey_idx = net_buf_simple_pull_le16(buf);
status.dist_status.ttl = net_buf_simple_pull_u8(buf);
status.dist_status.timeout_base = net_buf_simple_pull_le16(buf);
trans_mode_policy = net_buf_simple_pull_u8(buf);
if ((trans_mode_policy & ~(BIT6 - 1)) != 0) {
BT_ERR("RFU should be zero");
return;
}
status.dist_status.trans_mode = trans_mode_policy >> 6;
status.dist_status.update_policy = (trans_mode_policy >> 5) & 0x01;
status.dist_status.RFU = trans_mode_policy & 0x1f;
status.dist_status.fw_idx = net_buf_simple_pull_le16(buf);
dfd_client_recv_status(model, ctx, &status, sizeof(status.dist_status));
return;
}
static void handle_upload_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
dfd_status_t status = {0};
uint8_t progress_type = 0;
struct net_buf_simple buf_cache = {0};
status.upload_status.status = net_buf_simple_pull_u8(buf);
status.upload_status.upload_phase = net_buf_simple_pull_u8(buf);
if (buf->len == 0) {
status.upload_status.upload_progress = UPLOAD_PROGRESS_UNSET;
dfd_client_recv_status(model, ctx, &status, sizeof(status.upload_status));
return;
}
progress_type = net_buf_simple_pull_u8(buf);
status.upload_status.upload_progress = progress_type>>1;
if (status.upload_status.upload_progress >= UPLOAD_PROGRESS_UNSET) {
BT_ERR("Invalid upload progress");
return;
}
if (buf->len == 0) {
BT_ERR("InvFwID");
return;
}
status.upload_status.upload_type = progress_type & 0x01;
if (status.upload_status.upload_type == UPLOAD_IN_BAND) {
status.upload_status.fwid = &buf_cache;
net_buf_simple_init_with_data(status.upload_status.fwid, buf->data, buf->len);
net_buf_simple_pull_mem(buf, buf->len);
} else if (status.upload_status.upload_type == UPLOAD_OOB){
status.upload_status.oob_fwid = &buf_cache;
net_buf_simple_init_with_data(status.upload_status.oob_fwid, buf->data, buf->len);
net_buf_simple_pull_mem(buf, buf->len);
} else {
BT_ERR("Invalid upload type:%d", status.upload_status.upload_type);
return;
}
dfd_client_recv_status(model, ctx, &status, sizeof(status.upload_status));
return;
}
static void handle_fw_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
dfd_status_t status = {0};
struct net_buf_simple buf_cache = {0};
status.firmware_status.status = net_buf_simple_pull_u8(buf);
status.firmware_status.entry_cnt = net_buf_simple_pull_le16(buf);
status.firmware_status.firmware_image_index = net_buf_simple_pull_le16(buf);
if (buf->len) {
status.firmware_status.fwid = &buf_cache;
net_buf_simple_init_with_data(status.firmware_status.fwid, buf->data, buf->len);
net_buf_simple_pull_mem(buf, buf->len);
}
dfd_client_recv_status(model, ctx, &status, sizeof(status.firmware_status));
return;
}
const struct bt_mesh_model_op _bt_mesh_dfd_cli_op[] = {
{ BLE_MESH_DFD_OP_RECEIVERS_STATUS, 3, handle_receiver_status },
{ BLE_MESH_DFD_OP_RECEIVERS_LIST, 4 , handle_receiver_list },
{ BLE_MESH_DFD_OP_CAPABILITIES_STATUS, 17, handle_capabilities },
{ BLE_MESH_DFD_OP_STATUS, 2, handle_dfd_status },
{ BLE_MESH_DFD_OP_UPLOAD_STATUS, 2, handle_upload_status },
{ BLE_MESH_DFD_OP_FW_STATUS, 5, handle_fw_status },
};
int bt_mesh_dfd_cli_receivers_add(bt_mesh_client_common_param_t *param, dfd_cli_receiver_entry_t *receivers, uint16_t receivers_cnt)
{
uint16_t msg_length = 2;
struct net_buf_simple *msg = NULL;
dfd_cli_receiver_entry_t *entry = NULL;
int err = 0;
if (param == NULL) {
BT_ERR("Invalid param");
return -EINVAL;
}
BT_INFO("AddedValidCnt:%d", receivers_cnt);
msg_length += (receivers_cnt * 3);
/* needs to confirm long or short mic */
if (msg_length > BLE_MESH_MAX_PDU_LEN_WITH_SMIC) {
BT_ERR("Too much receivers added once time");
return -EINVAL;
}
msg = bt_mesh_alloc_buf(msg_length + BLE_MESH_MIC_SHORT);
if (!msg) {
BT_ERR("Failed to alloc buffer to send message");
return -EINVAL;
}
bt_mesh_model_msg_init(msg, BLE_MESH_DFD_OP_RECEIVERS_ADD);
for (int i = 0; i < receivers_cnt; i++) {
entry = &receivers[i];
if (BLE_MESH_ADDR_IS_UNICAST(entry->addr)) {
net_buf_simple_add_le16(msg, entry->addr);
net_buf_simple_add_u8(msg, entry->fw_idx);
BT_INFO("AddedUnicastAddr:0x%04x,FwIdx:%d", entry->addr, entry->fw_idx);
}
}
err = bt_mesh_client_send_msg(param, msg, true, timeout_handler);
bt_mesh_free_buf(msg);
return err;
}
int bt_mesh_dfd_cli_receivers_delete_all(bt_mesh_client_common_param_t *param)
{
BLE_MESH_MODEL_BUF_DEFINE(msg, BLE_MESH_DFD_OP_RECEIVERS_DELETE_ALL, 0);
if (!param) {
BT_ERR("Invalid param");
return -EINVAL;
}
bt_mesh_model_msg_init(&msg, BLE_MESH_DFD_OP_RECEIVERS_DELETE_ALL);
return bt_mesh_client_send_msg(param, &msg, true, timeout_handler);
}
int bt_mesh_dfd_cli_receivers_get(bt_mesh_client_common_param_t *param, uint16_t first_index, uint16_t entries_limit)
{
BLE_MESH_MODEL_BUF_DEFINE(msg, BLE_MESH_DFD_OP_RECEIVERS_GET, 4);
if (!param) {
BT_ERR("Invalid param");
return -EINVAL;
}
bt_mesh_model_msg_init(&msg, BLE_MESH_DFD_OP_RECEIVERS_GET);
net_buf_simple_add_le16(&msg, first_index);
net_buf_simple_add_le16(&msg, entries_limit);
return bt_mesh_client_send_msg(param, &msg, true, timeout_handler);
}
int bt_mesh_dfd_cli_distribution_capabilities_get(bt_mesh_client_common_param_t *param)
{
BLE_MESH_MODEL_BUF_DEFINE(msg, BLE_MESH_DFD_OP_CAPABILITIES_GET, 0);
if (!param) {
BT_ERR("Invalid param");
return -EINVAL;
}
bt_mesh_model_msg_init(&msg, BLE_MESH_DFD_OP_CAPABILITIES_GET);
return bt_mesh_client_send_msg(param, &msg, true, timeout_handler);
}
int bt_mesh_dfd_cli_distribution_get(bt_mesh_client_common_param_t *param)
{
BLE_MESH_MODEL_BUF_DEFINE(msg, BLE_MESH_DFD_OP_GET, 0);
if (!param) {
BT_ERR("Invalid param");
return -EINVAL;
}
bt_mesh_model_msg_init(&msg, BLE_MESH_DFD_OP_GET);
return bt_mesh_client_send_msg(param, &msg, true, timeout_handler);
}
int bt_mesh_dfd_cli_distribution_start(bt_mesh_client_common_param_t *param,
dfd_cli_dist_start_t *start)
{
BLE_MESH_MODEL_BUF_DEFINE(msg, BLE_MESH_DFD_OP_START, 2 + 1 + 2 + 1 + 2 + 16);
if (!param || !start) {
BT_ERR("Invalid param");
return -EINVAL;
}
bt_mesh_model_msg_init(&msg, BLE_MESH_DFD_OP_START);
net_buf_simple_add_le16(&msg, start->app_idx);
net_buf_simple_add_u8(&msg, start->ttl);
net_buf_simple_add_le16(&msg, start->timeout_base);
net_buf_simple_add_u8(&msg, ((start->trans_mode) << 6) | ((start->update_policy) << 5));
net_buf_simple_add_le16(&msg, start->fw_idx);
if (start->is_va) {
net_buf_simple_add_mem(&msg, &(start->label_uuid), 16);
} else {
net_buf_simple_add_le16(&msg, start->group_addr);
}
return bt_mesh_client_send_msg(param, &msg, true, timeout_handler);
}
int bt_mesh_dfd_cli_distribution_suspend(bt_mesh_client_common_param_t *param)
{
BLE_MESH_MODEL_BUF_DEFINE(msg, BLE_MESH_DFD_OP_SUSPEND, 0);
if (!param) {
BT_ERR("Invalid param");
return -EINVAL;
}
bt_mesh_model_msg_init(&msg, BLE_MESH_DFD_OP_SUSPEND);
return bt_mesh_client_send_msg(param, &msg, true, timeout_handler);
}
int bt_mesh_dfd_cli_distribution_cancel(bt_mesh_client_common_param_t *param)
{
BLE_MESH_MODEL_BUF_DEFINE(msg, BLE_MESH_DFD_OP_CANCEL, 0);
if (!param) {
BT_ERR("Invalid param");
return -EINVAL;
}
bt_mesh_model_msg_init(&msg, BLE_MESH_DFD_OP_CANCEL);
return bt_mesh_client_send_msg(param, &msg, true, timeout_handler);
}
int bt_mesh_dfd_cli_distribution_apply(bt_mesh_client_common_param_t *param)
{
BLE_MESH_MODEL_BUF_DEFINE(msg, BLE_MESH_DFD_OP_APPLY, 0);
if (!param) {
BT_ERR("Invalid param");
return -EINVAL;
}
bt_mesh_model_msg_init(&msg, BLE_MESH_DFD_OP_APPLY);
return bt_mesh_client_send_msg(param, &msg, true, timeout_handler);
}
int bt_mesh_dfd_cli_distribution_upload_get(bt_mesh_client_common_param_t *param)
{
BLE_MESH_MODEL_BUF_DEFINE(msg, BLE_MESH_DFD_OP_UPLOAD_GET, 0);
if (!param) {
BT_ERR("Invalid param");
return -EINVAL;
}
bt_mesh_model_msg_init(&msg, BLE_MESH_DFD_OP_UPLOAD_GET);
return bt_mesh_client_send_msg(param, &msg, true, timeout_handler);
}
int bt_mesh_dfd_cli_distribution_upload_start(bt_mesh_client_common_param_t *param,
dfd_cli_dist_upload_start_t *start)
{
struct net_buf_simple *msg = NULL;
uint16_t msg_length = 2;
int err = 0;
if (!param || !start) {
BT_ERR("Invalid param");
return -EINVAL;
}
msg_length += (1 + 2 + 8 + 4 + 1 + start->fwid->len);
if (start->fw_metadata) {
msg_length += start->fw_metadata->len;
}
msg = bt_mesh_alloc_buf(msg_length + BLE_MESH_MIC_SHORT);
if (!msg) {
BT_ERR("Failed to alloc buffer to send message");
return -EINVAL;
}
bt_mesh_model_msg_init(msg, BLE_MESH_DFD_OP_UPLOAD_START);
net_buf_simple_add_u8(msg, start->ttl);
net_buf_simple_add_le16(msg, start->timeout_base);
net_buf_simple_add_le64(msg, start->blob_id);
net_buf_simple_add_le32(msg, start->fw_size);
if (start->fw_metadata) {
net_buf_simple_add_u8(msg, start->fw_metadata->len);
net_buf_simple_add_mem(msg, start->fw_metadata->data, start->fw_metadata->len);
} else {
net_buf_simple_add_u8(msg, 0);
}
net_buf_simple_add_mem(msg, start->fwid->data, start->fwid->len);
err = bt_mesh_client_send_msg(param, msg, true, timeout_handler);
bt_mesh_free_buf(msg);
return err;
}
int bt_mesh_dfd_cli_distribution_upload_oob_start(bt_mesh_client_common_param_t *param,
dfd_cli_dist_upload_oob_start_t *start)
{
int err = 0;
struct net_buf_simple *msg = NULL;
uint16_t msg_length = 2;
if (!param || !start) {
BT_ERR("Invalid param");
return -1;
}
if (!start->url) {
BT_ERR("Null url info");
return -1;
}
if (!start->fwid) {
BT_ERR("Invalid firmware id");
return -1;
}
msg_length += (1 + start->url->len + start->fwid->len);
msg = bt_mesh_alloc_buf(msg_length + BLE_MESH_MIC_SHORT);
if (!msg) {
BT_ERR("Failed to alloc buffer to send message");
return -EINVAL;
}
bt_mesh_model_msg_init(msg, BLE_MESH_DFD_OP_UPLOAD_START_OOB);
net_buf_simple_add_u8(msg, start->url->len);
net_buf_simple_add_mem(msg, start->url->data, start->url->len);
net_buf_simple_add_mem(msg, start->fwid->data, start->fwid->len);
err = bt_mesh_client_send_msg(param, msg, true, timeout_handler);
bt_mesh_free_buf(msg);
return err;
}
int bt_mesh_dfd_cli_distribution_upload_oob_cancel(bt_mesh_client_common_param_t *param)
{
BLE_MESH_MODEL_BUF_DEFINE(msg, BLE_MESH_DFD_OP_UPLOAD_CANCEL, 0);
bt_mesh_model_msg_init(&msg, BLE_MESH_DFD_OP_UPLOAD_CANCEL);
return bt_mesh_client_send_msg(param, &msg, true, timeout_handler);
}
int bt_mesh_dfd_cli_firmware_get(bt_mesh_client_common_param_t *param, struct net_buf_simple *fwid)
{
struct net_buf_simple *msg = NULL;
uint16_t msg_length = 2;
int err;
if (!fwid) {
BT_ERR("NULL Firmware id");
return -EINVAL;
}
msg_length += fwid->len;
msg = bt_mesh_alloc_buf(msg_length + BLE_MESH_MIC_SHORT);
if (!msg) {
BT_ERR("Failed to alloc buffer to send message");
return -EINVAL;
}
bt_mesh_model_msg_init(msg, BLE_MESH_DFD_OP_FW_GET);
net_buf_simple_add_mem(msg, fwid->data, fwid->len);
err = bt_mesh_client_send_msg(param, msg, true, timeout_handler);
bt_mesh_free_buf(msg);
return err;
}
int bt_mesh_dfd_cli_firmware_get_by_index(bt_mesh_client_common_param_t *param, uint16_t fw_id_index)
{
BLE_MESH_MODEL_BUF_DEFINE(msg, BLE_MESH_DFD_OP_FW_GET_BY_INDEX, 2);
bt_mesh_model_msg_init(&msg, BLE_MESH_DFD_OP_FW_GET_BY_INDEX);
net_buf_simple_add_le16(&msg, fw_id_index);
return bt_mesh_client_send_msg(param, &msg, true, timeout_handler);
}
int bt_mesh_dfd_cli_firmware_get_delete(bt_mesh_client_common_param_t *param, struct net_buf_simple *fwid)
{
struct net_buf_simple *msg = NULL;
uint16_t msg_length = 2;
int err;
if (!fwid) {
BT_ERR("NULL Firmware id");
return -EINVAL;
}
msg_length += fwid->len;
msg = bt_mesh_alloc_buf(msg_length + BLE_MESH_MIC_SHORT);
if (!msg) {
BT_ERR("Failed to alloc buffer to send message");
return -EINVAL;
}
bt_mesh_model_msg_init(msg, BLE_MESH_DFD_OP_FW_DELETE);
net_buf_simple_add_mem(msg, fwid->data, fwid->len);
err = bt_mesh_client_send_msg(param, msg, true, timeout_handler);
bt_mesh_free_buf(msg);
return err;
}
int bt_mesh_dfd_cli_firmware_delete_all(bt_mesh_client_common_param_t *param)
{
BLE_MESH_MODEL_BUF_DEFINE(msg, BLE_MESH_DFD_OP_FW_DELETE_ALL, 0);
bt_mesh_model_msg_init(&msg, BLE_MESH_DFD_OP_FW_DELETE_ALL);
return bt_mesh_client_send_msg(param, &msg, true, timeout_handler);
}
static int dfd_cli_init(struct bt_mesh_model *model)
{
bt_mesh_dfd_client_t *client = NULL;
dfd_internal_data_t *internal = NULL;
if (!model) {
BT_ERR("Invalid Device Firmware Distribution Client model");
return -EINVAL;
}
if (!bt_mesh_model_in_primary(model)) {
BT_ERR("Device Firmware Distribution Client only allowed in primary element");
return -EINVAL;
}
client = (bt_mesh_dfd_client_t *)model->user_data;
if (!client) {
BT_ERR("No Device Firmware Distribution Client context provided");
return -EINVAL;
}
if (client->internal_data) {
BT_WARN("%s, Already", __func__);
return -EALREADY;
}
internal = bt_mesh_calloc(sizeof(dfd_internal_data_t));
if (!internal) {
BT_ERR("%s, Out of memory", __func__);
return -ENOMEM;
}
sys_slist_init(&internal->queue);
client->model = model;
client->op_pair_size = ARRAY_SIZE(dfd_cli_pair);
client->op_pair = dfd_cli_pair;
client->internal_data = internal;
BT_INFO("Dfd client initialized");
bt_mesh_mutex_create(&dfd_client_lock);
return 0;
}
#if CONFIG_BLE_MESH_DEINIT
static int dfd_cli_deinit(struct bt_mesh_model *model)
{
bt_mesh_dfd_client_t *client = NULL;
if (!model) {
BT_ERR("Invalid Device Firmware Distribution Client model");
return -EINVAL;
}
client = (bt_mesh_dfd_client_t *)model->user_data;
if (!client) {
BT_ERR("No Device Firmware Distribution Client context provided");
return -EINVAL;
}
if (client->internal_data) {
/* Remove items from the list */
bt_mesh_client_clear_list(client->internal_data);
/* Free the allocated internal data */
bt_mesh_free(client->internal_data);
client->internal_data = NULL;
}
bt_mesh_mutex_free(&dfd_client_lock);
return 0;
}
#endif
const struct bt_mesh_model_cb _bt_mesh_dfd_cli_cb = {
.init = dfd_cli_init,
#if CONFIG_BLE_MESH_DEINIT
.deinit = dfd_cli_deinit,
#endif /* CONFIG_BLE_MESH_DEINIT */
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,49 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _BLE_MESH_v11_DFD_SRV_INTERNAL_H__
#define _BLE_MESH_v11_DFD_SRV_INTERNAL_H__
#include "mesh_v1.1/dfu/dfd_srv.h"
#if CONFIG_BLE_MESH_DFD_SRV
#ifdef __cplusplus
extern "C" {
#endif
struct bt_mesh_dfd_start_params {
uint16_t app_idx, timeout_base, slot_idx, group;
enum bt_mesh_blob_xfer_mode xfer_mode;
uint8_t ttl;
bool apply;
};
enum bt_mesh_dfd_status bt_mesh_dfd_srv_receiver_add(struct bt_mesh_dfd_srv *srv, uint16_t addr,
uint8_t img_idx);
enum bt_mesh_dfd_status bt_mesh_dfd_srv_receivers_delete_all(struct bt_mesh_dfd_srv *srv);
enum bt_mesh_dfd_status bt_mesh_dfd_srv_start(struct bt_mesh_dfd_srv *srv,
struct bt_mesh_dfd_start_params *params);
enum bt_mesh_dfd_status bt_mesh_dfd_srv_suspend(struct bt_mesh_dfd_srv *srv);
enum bt_mesh_dfd_status bt_mesh_dfd_srv_cancel(struct bt_mesh_dfd_srv *srv,
struct bt_mesh_msg_ctx *ctx);
enum bt_mesh_dfd_status bt_mesh_dfd_srv_apply(struct bt_mesh_dfd_srv *srv);
enum bt_mesh_dfd_status bt_mesh_dfd_srv_fw_delete(struct bt_mesh_dfd_srv *srv, size_t *fwid_len,
const uint8_t **fwid);
enum bt_mesh_dfd_status bt_mesh_dfd_srv_fw_delete_all(struct bt_mesh_dfd_srv *srv);
#ifdef __cplusplus
}
#endif
#endif
#endif /* _BLE_MESH_v11_DFD_SRV_INTERNAL_H__ */

View File

@@ -0,0 +1,47 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "mesh/buf.h"
#if CONFIG_BLE_MESH_DFU_SRV || CONFIG_BLE_MESH_DFU_CLI
#define BLE_MESH_DFU_OP_UPDATE_INFO_GET BLE_MESH_MODEL_OP_2(0x83, 0x08)
#define BLE_MESH_DFU_OP_UPDATE_INFO_STATUS BLE_MESH_MODEL_OP_2(0x83, 0x09)
#define BLE_MESH_DFU_OP_UPDATE_METADATA_CHECK BLE_MESH_MODEL_OP_2(0x83, 0x0a)
#define BLE_MESH_DFU_OP_UPDATE_METADATA_STATUS BLE_MESH_MODEL_OP_2(0x83, 0x0b)
#define BLE_MESH_DFU_OP_UPDATE_GET BLE_MESH_MODEL_OP_2(0x83, 0x0c)
#define BLE_MESH_DFU_OP_UPDATE_START BLE_MESH_MODEL_OP_2(0x83, 0x0d)
#define BLE_MESH_DFU_OP_UPDATE_CANCEL BLE_MESH_MODEL_OP_2(0x83, 0x0e)
#define BLE_MESH_DFU_OP_UPDATE_APPLY BLE_MESH_MODEL_OP_2(0x83, 0x0f)
#define BLE_MESH_DFU_OP_UPDATE_STATUS BLE_MESH_MODEL_OP_2(0x83, 0x10)
#define DFU_UPDATE_INFO_STATUS_MSG_MINLEN (4 + CONFIG_BLE_MESH_DFU_FWID_MAXLEN + \
CONFIG_BLE_MESH_DFU_URI_MAXLEN)
#define DFU_UPDATE_START_MSG_MAXLEN (12 + CONFIG_BLE_MESH_DFU_METADATA_MAXLEN)
static inline uint16_t dfu_metadata_checksum(struct net_buf_simple *buf)
{
/* Simple Fletcher-16 checksum to ensure duplicate start messages don't
* have different metadata.
*/
struct net_buf_simple_state state;
uint8_t sum[2] = {0, 0};
net_buf_simple_save(buf, &state);
while (buf->len) {
uint8_t byte = net_buf_simple_pull_u8(buf);
sum[0] += byte;
sum[1] += sum[0];
}
net_buf_simple_restore(buf, &state);
return (sum[0] << 8U) | sum[1];
}
#endif /* CONFIG_BLE_MESH_DFU_SRV || CONFIG_BLE_MESH_DFU_CLI */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,105 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include "crypto.h"
#include "access.h"
#include "mesh/byteorder.h"
#include "mesh/buf.h"
#include "mesh_v1.1/dfu/dfu_metadata.h"
#if CONFIG_BLE_MESH_DFU_METADATA
int bt_mesh_dfu_metadata_decode(struct net_buf_simple *buf,
struct bt_mesh_dfu_metadata *metadata)
{
if (buf->len < 12) {
return -EMSGSIZE;
}
metadata->fw_ver.major = net_buf_simple_pull_u8(buf);
metadata->fw_ver.minor = net_buf_simple_pull_u8(buf);
metadata->fw_ver.revision = net_buf_simple_pull_le16(buf);
metadata->fw_ver.build_num = net_buf_simple_pull_le32(buf);
metadata->fw_size = net_buf_simple_pull_le24(buf);
metadata->fw_core_type = net_buf_simple_pull_u8(buf);
if (metadata->fw_core_type & BLE_MESH_DFU_FW_CORE_TYPE_APP) {
if (buf->len < 6) {
return -EMSGSIZE;
}
metadata->comp_hash = net_buf_simple_pull_le32(buf);
metadata->elems = net_buf_simple_pull_le16(buf);
}
metadata->user_data = buf->len > 0 ? buf->data : NULL;
metadata->user_data_len = buf->len;
return 0;
}
int bt_mesh_dfu_metadata_encode(const struct bt_mesh_dfu_metadata *metadata,
struct net_buf_simple *buf)
{
size_t md_len_min = 12 + metadata->user_data_len;
if (metadata->fw_core_type & BLE_MESH_DFU_FW_CORE_TYPE_APP) {
md_len_min += 6;
}
if (net_buf_simple_tailroom(buf) < md_len_min) {
return -EMSGSIZE;
}
net_buf_simple_add_u8(buf, metadata->fw_ver.major);
net_buf_simple_add_u8(buf, metadata->fw_ver.minor);
net_buf_simple_add_le16(buf, metadata->fw_ver.revision);
net_buf_simple_add_le32(buf, metadata->fw_ver.build_num);
net_buf_simple_add_le24(buf, metadata->fw_size);
net_buf_simple_add_u8(buf, metadata->fw_core_type);
net_buf_simple_add_le32(buf, metadata->comp_hash);
net_buf_simple_add_le16(buf, metadata->elems);
if (metadata->user_data_len > 0) {
net_buf_simple_add_mem(buf, metadata->user_data, metadata->user_data_len);
}
return 0;
}
int bt_mesh_dfu_metadata_comp_hash_get(struct net_buf_simple *buf, uint8_t *key, uint32_t *hash)
{
uint8_t mac[16];
int err;
struct bt_mesh_sg sg = {.data = buf->data, .len = buf->len};
/* The implementation of this function is the same as function `bt_mesh_aes_cmac_raw_key` in Zephyr. */
err = bt_mesh_aes_cmac(key, &sg, 1, mac);
if (err) {
return err;
}
*hash = sys_get_le32(mac);
return 0;
}
int bt_mesh_dfu_metadata_comp_hash_local_get(uint8_t *key, uint32_t *hash)
{
NET_BUF_SIMPLE_DEFINE(buf, BLE_MESH_TX_SDU_MAX);
int err;
err = bt_mesh_get_comp_data(&buf, 0, 0, true);
if (err) {
return err;
}
err = bt_mesh_dfu_metadata_comp_hash_get(&buf, key, hash);
return err;
}
#endif /* CONFIG_BLE_MESH_DFU_METADATA */

View File

@@ -0,0 +1,444 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "dfu_slot.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "mesh/common.h"
#include "mesh/utils.h"
#include "settings_nvs.h"
#include "settings.h"
#if CONFIG_BLE_MESH_DFU_SLOTS
#define SLOT_ENTRY_BUFLEN 25
#define DFU_SLOT_SETTINGS_PATH "mesh/dfu/s"
#define HEADER_SIZE offsetof(struct slot, slot.fwid)
#define PROP_HEADER "h"
#define PROP_FWID "id"
#define PROP_METADATA "m"
#define SETTINGS_NAME_END '='
#define SETTINGS_NAME_SEPARATOR '/'
static sys_slist_t list;
static struct slot {
uint32_t idx;
struct bt_mesh_dfu_slot slot;
sys_snode_t n;
} slots[CONFIG_BLE_MESH_DFU_SLOT_CNT];
static uint32_t slot_index;
inline int settings_name_next(const char *name, const char **next)
{
int rc = 0;
if (next) {
*next = NULL;
}
if (!name) {
return 0;
}
/* name might come from flash directly, in flash the name would end
* with '=' or '\0' depending how storage is done. Flash reading is
* limited to what can be read
*/
while ((*name != '\0') && (*name != SETTINGS_NAME_END) &&
(*name != SETTINGS_NAME_SEPARATOR)) {
rc++;
name++;
}
if (*name == SETTINGS_NAME_SEPARATOR) {
if (next) {
*next = name + 1;
}
return rc;
}
return rc;
}
#if CONFIG_BLE_MESH_SETTINGS
static char *slot_entry_encode(uint16_t idx, char buf[SLOT_ENTRY_BUFLEN],
const char *property)
{
snprintf(buf, SLOT_ENTRY_BUFLEN, DFU_SLOT_SETTINGS_PATH "/%x/%s", idx,
property);
return buf;
}
#endif
static bool slot_eq(const struct bt_mesh_dfu_slot *slot,
const uint8_t *fwid, size_t fwid_len)
{
return (slot->fwid_len == fwid_len) &&
!memcmp(fwid, slot->fwid, fwid_len);
}
static bool is_slot_committed(struct slot *slot_to_check)
{
struct slot *s;
SYS_SLIST_FOR_EACH_CONTAINER(&list, s, n) {
if (s == slot_to_check) {
return true;
}
}
return false;
}
static int slot_store(const struct slot *slot_to_store)
{
int err = 0;
#if CONFIG_BLE_MESH_SETTINGS
uint16_t idx = ARRAY_INDEX(slots, slot_to_store);
char buf[SLOT_ENTRY_BUFLEN];
err = bt_mesh_save_core_settings(slot_entry_encode(idx, buf, PROP_HEADER),
(uint8_t *)slot_to_store, HEADER_SIZE);
if (err) {
return err;
}
err = bt_mesh_save_core_settings(slot_entry_encode(idx, buf, PROP_FWID),
slot_to_store->slot.fwid, slot_to_store->slot.fwid_len);
if (err) {
return err;
}
err = bt_mesh_save_core_settings(slot_entry_encode(idx, buf, PROP_METADATA),
slot_to_store->slot.metadata, slot_to_store->slot.metadata_len);
#endif
return err;
}
static void slot_erase(struct slot *slot_to_erase)
{
#if CONFIG_BLE_MESH_SETTINGS
uint16_t idx = ARRAY_INDEX(slots, slot_to_erase);
char buf[SLOT_ENTRY_BUFLEN];
bt_mesh_erase_core_settings(slot_entry_encode(idx, buf, PROP_HEADER));
bt_mesh_erase_core_settings(slot_entry_encode(idx, buf, PROP_FWID));
bt_mesh_erase_core_settings(slot_entry_encode(idx, buf, PROP_METADATA));
#endif
}
static void slot_index_defrag(void)
{
slot_index = 0;
struct slot *s;
SYS_SLIST_FOR_EACH_CONTAINER(&list, s, n) {
s->idx = ++slot_index;
slot_store(s);
}
}
int bt_mesh_dfu_slot_count(void)
{
int cnt = 0;
sys_snode_t *n;
SYS_SLIST_FOR_EACH_NODE(&list, n) {
cnt++;
}
return cnt;
}
struct bt_mesh_dfu_slot *bt_mesh_dfu_slot_reserve(void)
{
struct slot *slot = NULL;
for (int i = 0; i < ARRAY_SIZE(slots); ++i) {
if (slots[i].idx == 0) {
slot = &slots[i];
break;
}
}
if (!slot) {
BT_WARN("No space");
return NULL;
}
if (slot_index == UINT32_MAX) {
slot_index_defrag();
}
slot->slot.fwid_len = 0;
slot->slot.metadata_len = 0;
slot->slot.size = 0;
slot->idx = ++slot_index;
BT_DBG("Reserved slot #%u", slot - &slots[0]);
return &slot->slot;
}
int bt_mesh_dfu_slot_info_set(struct bt_mesh_dfu_slot *dfu_slot, size_t size,
const uint8_t *metadata, size_t metadata_len)
{
struct slot *slot = CONTAINER_OF(dfu_slot, struct slot, slot);
if (metadata_len > CONFIG_BLE_MESH_DFU_METADATA_MAXLEN) {
return -EFBIG;
}
if (slot->idx == 0 || is_slot_committed(slot)) {
return -EINVAL;
}
slot->slot.size = size;
slot->slot.metadata_len = metadata_len;
memcpy(slot->slot.metadata, metadata, metadata_len);
return 0;
}
int bt_mesh_dfu_slot_fwid_set(struct bt_mesh_dfu_slot *dfu_slot,
const uint8_t *fwid, size_t fwid_len)
{
struct slot *slot = CONTAINER_OF(dfu_slot, struct slot, slot);
if (fwid_len > CONFIG_BLE_MESH_DFU_FWID_MAXLEN) {
return -EFBIG;
}
if (slot->idx == 0) {
return -EINVAL;
}
if (is_slot_committed(slot)) {
return -EEXIST;
}
for (int i = 0; i < ARRAY_SIZE(slots); i++) {
if (slots[i].idx != 0 &&
slot_eq(&slots[i].slot, fwid, fwid_len)) {
return -EALREADY;
}
}
slot->slot.fwid_len = fwid_len;
memcpy(slot->slot.fwid, fwid, fwid_len);
return 0;
}
int bt_mesh_dfu_slot_commit(struct bt_mesh_dfu_slot *dfu_slot)
{
int err;
struct slot *slot = CONTAINER_OF(dfu_slot, struct slot, slot);
if (slot->idx == 0 ||
slot->slot.fwid_len == 0 ||
slot->slot.size == 0 ||
is_slot_committed(slot)) {
return -EINVAL;
}
err = slot_store(slot);
if (err) {
BT_WARN("Store failed (err: %d)", err);
return err;
}
sys_slist_append(&list, &slot->n);
BT_DBG("Stored slot #%u: %s", ARRAY_INDEX(slots, slot),
bt_hex(slot->slot.fwid, slot->slot.fwid_len));
return 0;
}
void bt_mesh_dfu_slot_release(const struct bt_mesh_dfu_slot *dfu_slot)
{
struct slot *slot = CONTAINER_OF(dfu_slot, struct slot, slot);
if (is_slot_committed(slot)) {
return;
}
slot->idx = 0;
}
int bt_mesh_dfu_slot_del(const struct bt_mesh_dfu_slot *dfu_slot)
{
struct slot *slot = CONTAINER_OF(dfu_slot, struct slot, slot);
if (!sys_slist_find_and_remove(&list, &slot->n)) {
return -EINVAL;
}
int idx = ARRAY_INDEX(slots, slot);
BT_DBG("%u", idx);
slot_erase(slot);
slot->idx = 0;
return 0;
}
void bt_mesh_dfu_slot_del_all(void)
{
struct slot *s;
SYS_SLIST_FOR_EACH_CONTAINER(&list, s, n) {
slot_erase(s);
s->idx = 0;
}
sys_slist_init(&list);
}
const struct bt_mesh_dfu_slot *bt_mesh_dfu_slot_at(uint16_t img_idx)
{
struct slot *s;
SYS_SLIST_FOR_EACH_CONTAINER(&list, s, n) {
if (!img_idx--) {
return &s->slot;
}
}
return NULL;
}
int bt_mesh_dfu_slot_get(const uint8_t *fwid, size_t fwid_len, struct bt_mesh_dfu_slot **slot)
{
struct slot *s;
int idx = 0;
SYS_SLIST_FOR_EACH_CONTAINER(&list, s, n) {
if (slot_eq(&s->slot, fwid, fwid_len)) {
if (slot) {
*slot = &s->slot;
}
return idx;
}
idx++;
}
return -ENOENT;
}
int bt_mesh_dfu_slot_img_idx_get(const struct bt_mesh_dfu_slot *dfu_slot)
{
struct slot *s;
int idx = 0;
SYS_SLIST_FOR_EACH_CONTAINER(&list, s, n) {
if (&s->slot == dfu_slot) {
return idx;
}
idx++;
}
return -ENOENT;
}
size_t bt_mesh_dfu_slot_foreach(bt_mesh_dfu_slot_cb_t cb, void *user_data)
{
enum bt_mesh_dfu_iter iter;
size_t cnt = 0;
struct slot *s;
SYS_SLIST_FOR_EACH_CONTAINER(&list, s, n) {
cnt++;
if (!cb) {
continue;
}
iter = cb(&s->slot, user_data);
if (iter != BLE_MESH_DFU_ITER_CONTINUE) {
break;
}
}
return cnt;
}
#if 0
static int slot_data_load(const char *key, size_t len_rd,
settings_read_cb read_cb, void *cb_arg)
{
const char *prop;
size_t len;
uint16_t idx;
idx = strtol(key, NULL, 16);
if (idx >= ARRAY_SIZE(slots)) {
return 0;
}
len = settings_name_next(key, &prop);
if (!strncmp(prop, PROP_HEADER, len)) {
if (read_cb(cb_arg, &slots[idx], HEADER_SIZE) > 0) {
struct slot *s, *prev = NULL;
SYS_SLIST_FOR_EACH_CONTAINER(&list, s, n) {
if (s->idx > slots[idx].idx) {
break;
}
prev = s;
}
if (prev == NULL) {
sys_slist_prepend(&list, &slots[idx].n);
} else {
sys_slist_insert(&list, &prev->n, &slots[idx].n);
}
if (slots[idx].idx >= slot_index) {
slot_index = slots[idx].idx + 1;
}
}
return 0;
}
if (!strncmp(prop, PROP_FWID, len)) {
if (read_cb(cb_arg, &slots[idx].slot.fwid,
sizeof(slots[idx].slot.fwid)) < 0) {
slots[idx].idx = 0;
sys_slist_find_and_remove(&list, &slots[idx].n);
return 0;
}
slots[idx].slot.fwid_len = len_rd;
return 0;
}
if (!strncmp(prop, PROP_METADATA, len)) {
if (read_cb(cb_arg, &slots[idx].slot.metadata,
sizeof(slots[idx].slot.metadata)) < 0) {
slots[idx].idx = 0;
sys_slist_find_and_remove(&list, &slots[idx].n);
return 0;
}
slots[idx].slot.metadata_len = len_rd;
return 0;
}
return 0;
}
#endif
#endif /* CONFIG_BLE_MESH_DFU_SLOTS */

View File

@@ -0,0 +1,137 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "mesh_v1.1/dfu/dfu.h"
#if CONFIG_BLE_MESH_DFU_SLOTS
/** @brief Slot iteration callback.
*
* @param slot A valid DFU image slot.
* @param user_data User data passed to @ref bt_mesh_dfu_slot_foreach.
*
* @return Iteration action determining next step.
*/
typedef enum bt_mesh_dfu_iter(*bt_mesh_dfu_slot_cb_t)
(const struct bt_mesh_dfu_slot *slot, void *user_data);
/** @brief Get the number of slots committed to the firmware list.
*
* @return Number of committed slots.
*/
int bt_mesh_dfu_slot_count(void);
/** @brief Reserve a new DFU image slot for a distributable image.
*
* A DFU image slot represents a single distributable DFU image with all its
* metadata. The slot data must be set using @ref bt_mesh_dfu_slot_info_set and
* @ref bt_mesh_dfu_slot_fwid_set, and the slot committed using
* @ref bt_mesh_dfu_slot_commit for the slot to be considered part of the slot
* list.
*
* @return A pointer to the reserved slot, or NULL if allocation failed.
*/
struct bt_mesh_dfu_slot *bt_mesh_dfu_slot_reserve(void);
/** @brief Set the size and metadata for a reserved slot.
*
* @param dfu_slot Pointer to the reserved slot for which to set the
* metadata.
* @param size The size of the image.
* @param metadata Metadata or NULL.
* @param metadata_len Length of the metadata, at most @c
* CONFIG_BLE_MESH_DFU_METADATA_MAXLEN.
*
* @return 0 on success, (negative) error code otherwise.
*/
int bt_mesh_dfu_slot_info_set(struct bt_mesh_dfu_slot *dfu_slot, size_t size,
const uint8_t *metadata, size_t metadata_len);
/** @brief Set the new fwid for the incoming image for a reserved slot.
*
* @param dfu_slot Pointer to the reserved slot for which to set the fwid.
* @param fwid Fwid to set.
* @param fwid_len Length of the fwid, at most @c
* CONFIG_BLE_MESH_DFU_FWID_MAXLEN.
*
* @return 0 on success, (negative) error code otherwise.
*/
int bt_mesh_dfu_slot_fwid_set(struct bt_mesh_dfu_slot *dfu_slot,
const uint8_t *fwid, size_t fwid_len);
/** @brief Commit the reserved slot to the list of slots, and store it
* persistently.
*
* If the commit fails for any reason, the slot will still be in the reserved
* state after this call.
*
* @param dfu_slot Pointer to the reserved slot.
*
* @return 0 on success, (negative) error code otherwise.
*/
int bt_mesh_dfu_slot_commit(struct bt_mesh_dfu_slot *dfu_slot);
/** @brief Release a reserved slot so that it can be reserved again.
*
* @param dfu_slot Pointer to the reserved slot.
*/
void bt_mesh_dfu_slot_release(const struct bt_mesh_dfu_slot *dfu_slot);
/** @brief Delete a committed DFU image slot.
*
* @param slot Slot to delete. Must be a valid pointer acquired from this
* module.
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_dfu_slot_del(const struct bt_mesh_dfu_slot *slot);
/** @brief Delete all DFU image slots.
*
* @return 0 on success, or (negative) error code on failure.
*/
void bt_mesh_dfu_slot_del_all(void);
/** @brief Get the DFU image slot at the given firmware image list index.
*
* @param idx DFU image slot index.
*
* @return The DFU image slot at the given index, or NULL if no slot exists with the
* given index.
*/
const struct bt_mesh_dfu_slot *bt_mesh_dfu_slot_at(uint16_t img_idx);
/** @brief Get the committed DFU image slot for the image with the given
* firmware ID.
*
* @param fwid Firmware ID.
* @param fwid_len Firmware ID length.
* @param slot Slot pointer to fill.
*
* @return Slot index on success, or negative error code on failure.
*/
int bt_mesh_dfu_slot_get(const uint8_t *fwid, size_t fwid_len, struct bt_mesh_dfu_slot **slot);
/** @brief Get the index in the firmware image list for the given slot.
*
* @param slot Slot to find.
*
* @return Slot index on success, or negative error code on failure.
*/
int bt_mesh_dfu_slot_img_idx_get(const struct bt_mesh_dfu_slot *slot);
/** @brief Iterate through all DFU image slots.
*
* Calls the callback for every DFU image slot or until the callback returns
* something other than @ref BLE_MESH_DFU_ITER_CONTINUE.
*
* @param cb Callback to call for each slot, or NULL to just count the
* number of slots.
* @param user_data User data to pass to the callback.
*
* @return The number of slots iterated over.
*/
size_t bt_mesh_dfu_slot_foreach(bt_mesh_dfu_slot_cb_t cb, void *user_data);
#endif /* CONFIG_BLE_MESH_DFU_SLOTS */

View File

@@ -0,0 +1,631 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "mesh_v1.1/dfu/dfu.h"
#include "mesh_v1.1/dfu/dfu_srv.h"
#include "dfu.h"
#include "blob.h"
#include "access.h"
#if CONFIG_BLE_MESH_SETTINGS
#include "settings.h"
#endif
#if CONFIG_BLE_MESH_DFU_SRV
#define UPDATE_IDX_NONE 0xff
_Static_assert((DFU_UPDATE_START_MSG_MAXLEN + BLE_MESH_MODEL_OP_LEN(BLE_MESH_DFU_OP_UPDATE_START) +
BLE_MESH_MIC_SHORT) <= BLE_MESH_RX_SDU_MAX,
"The Firmware Update Start message does not fit into the maximum incoming SDU size.");
_Static_assert((DFU_UPDATE_INFO_STATUS_MSG_MINLEN +
BLE_MESH_MODEL_OP_LEN(BLE_MESH_DFU_OP_UPDATE_INFO_STATUS) + BLE_MESH_MIC_SHORT)
<= BLE_MESH_TX_SDU_MAX,
"The Firmware Update Info Status message does not fit into the maximum outgoing SDU "
"size.");
static void store_state(struct bt_mesh_dfu_srv *srv)
{
#if CONFIG_BLE_MESH_SETTINGS
bt_mesh_model_data_store(srv->mod, false, NULL, &srv->update,
sizeof(srv->update));
#endif
}
static void erase_state(struct bt_mesh_dfu_srv *srv)
{
#if CONFIG_BLE_MESH_SETTINGS
bt_mesh_model_data_store(srv->mod, false, NULL, NULL, 0);
#endif
}
static void xfer_failed(struct bt_mesh_dfu_srv *srv)
{
if (!bt_mesh_dfu_srv_is_busy(srv) ||
srv->update.idx >= srv->img_count) {
return;
}
erase_state(srv);
if (srv->cb->end) {
srv->cb->end(srv, &srv->imgs[srv->update.idx], false);
}
}
static enum bt_mesh_dfu_status metadata_check(struct bt_mesh_dfu_srv *srv,
uint8_t idx,
struct net_buf_simple *buf,
enum bt_mesh_dfu_effect *effect)
{
*effect = BLE_MESH_DFU_EFFECT_NONE;
if (idx >= srv->img_count) {
return BLE_MESH_DFU_ERR_FW_IDX;
}
if (!srv->cb->check) {
return BLE_MESH_DFU_SUCCESS;
}
if (srv->cb->check(srv, &srv->imgs[idx], buf, effect)) {
*effect = BLE_MESH_DFU_EFFECT_NONE;
return BLE_MESH_DFU_ERR_METADATA;
}
return BLE_MESH_DFU_SUCCESS;
}
static void apply_rsp_sent(int err, void *cb_params)
{
struct bt_mesh_dfu_srv *srv = cb_params;
if (err) {
/* return phase back to give client one more chance. */
srv->update.phase = BLE_MESH_DFU_PHASE_VERIFY_OK;
BT_WARN("Apply response failed, wait for retry (err %d)", err);
return;
}
BT_DBG("");
if (!srv->cb->apply || srv->update.idx == UPDATE_IDX_NONE) {
srv->update.phase = BLE_MESH_DFU_PHASE_IDLE;
store_state(srv);
BT_DBG("Prerequisites for apply callback are wrong");
return;
}
store_state(srv);
err = srv->cb->apply(srv, &srv->imgs[srv->update.idx]);
if (err) {
srv->update.phase = BLE_MESH_DFU_PHASE_IDLE;
store_state(srv);
BT_DBG("Application apply callback failed (err %d)", err);
}
}
static void apply_rsp_sending(uint16_t duration, int err, void *cb_params)
{
if (err) {
apply_rsp_sent(err, cb_params);
}
}
static void verify(struct bt_mesh_dfu_srv *srv)
{
srv->update.phase = BLE_MESH_DFU_PHASE_VERIFY;
if (srv->update.idx >= srv->img_count) {
bt_mesh_dfu_srv_rejected(srv);
return;
}
if (!srv->cb->end) {
bt_mesh_dfu_srv_verified(srv);
return;
}
srv->cb->end(srv, &srv->imgs[srv->update.idx], true);
if (srv->update.phase == BLE_MESH_DFU_PHASE_VERIFY) {
store_state(srv);
}
}
static int handle_info_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct bt_mesh_dfu_srv *srv = mod->user_data;
uint8_t idx, limit;
if (srv->update.phase == BLE_MESH_DFU_PHASE_APPLYING) {
BT_INFO("Still applying, not responding");
return -EBUSY;
}
idx = net_buf_simple_pull_u8(buf);
limit = net_buf_simple_pull_u8(buf);
BT_DBG("from %u (limit: %u)", idx, limit);
NET_BUF_SIMPLE_DEFINE(rsp, BLE_MESH_TX_SDU_MAX);
bt_mesh_model_msg_init(&rsp, BLE_MESH_DFU_OP_UPDATE_INFO_STATUS);
net_buf_simple_add_u8(&rsp, srv->img_count);
net_buf_simple_add_u8(&rsp, idx);
for (; idx < srv->img_count && limit > 0; ++idx) {
uint32_t entry_len;
if (!srv->imgs[idx].fwid) {
continue;
}
entry_len = 2 + srv->imgs[idx].fwid_len;
if (srv->imgs[idx].uri) {
entry_len += strlen(srv->imgs[idx].uri);
}
if (net_buf_simple_tailroom(&rsp) + BLE_MESH_MIC_SHORT < entry_len) {
break;
}
net_buf_simple_add_u8(&rsp, srv->imgs[idx].fwid_len);
net_buf_simple_add_mem(&rsp, srv->imgs[idx].fwid,
srv->imgs[idx].fwid_len);
if (srv->imgs[idx].uri) {
size_t len = strlen(srv->imgs[idx].uri);
net_buf_simple_add_u8(&rsp, len);
net_buf_simple_add_mem(&rsp, srv->imgs[idx].uri, len);
} else {
net_buf_simple_add_u8(&rsp, 0);
}
limit--;
}
if (srv->update.phase != BLE_MESH_DFU_PHASE_IDLE) {
ctx->send_ttl = srv->update.ttl;
}
bt_mesh_model_send(mod, ctx, &rsp, NULL, NULL);
return 0;
}
static int handle_metadata_check(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct bt_mesh_dfu_srv *srv = mod->user_data;
enum bt_mesh_dfu_status status;
enum bt_mesh_dfu_effect effect;
uint8_t idx;
BLE_MESH_MODEL_BUF_DEFINE(rsp, BLE_MESH_DFU_OP_UPDATE_METADATA_STATUS, 2);
bt_mesh_model_msg_init(&rsp, BLE_MESH_DFU_OP_UPDATE_METADATA_STATUS);
idx = net_buf_simple_pull_u8(buf);
status = metadata_check(srv, idx, buf, &effect);
BT_DBG("%u", idx);
net_buf_simple_add_u8(&rsp, (status & BIT_MASK(3)) | (effect << 3));
net_buf_simple_add_u8(&rsp, idx);
if (srv->update.phase != BLE_MESH_DFU_PHASE_IDLE) {
ctx->send_ttl = srv->update.ttl;
}
bt_mesh_model_send(mod, ctx, &rsp, NULL, NULL);
return 0;
}
static void update_status_rsp(struct bt_mesh_dfu_srv *srv,
struct bt_mesh_msg_ctx *ctx,
enum bt_mesh_dfu_status status,
const struct bt_mesh_send_cb *send_cb)
{
BLE_MESH_MODEL_BUF_DEFINE(buf, BLE_MESH_DFU_OP_UPDATE_STATUS, 14);
bt_mesh_model_msg_init(&buf, BLE_MESH_DFU_OP_UPDATE_STATUS);
net_buf_simple_add_u8(&buf, ((status & BIT_MASK(3)) |
(srv->update.phase << 5)));
if (srv->update.phase != BLE_MESH_DFU_PHASE_IDLE) {
net_buf_simple_add_u8(&buf, srv->update.ttl);
net_buf_simple_add_u8(&buf, srv->update.effect);
net_buf_simple_add_le16(&buf, srv->update.timeout_base);
net_buf_simple_add_le64(&buf, srv->blob.state.xfer.id);
net_buf_simple_add_u8(&buf, srv->update.idx);
ctx->send_ttl = srv->update.ttl;
}
bt_mesh_model_send(srv->mod, ctx, &buf, send_cb, srv);
}
static int handle_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct bt_mesh_dfu_srv *srv = mod->user_data;
BT_DBG("");
update_status_rsp(srv, ctx, BLE_MESH_DFU_SUCCESS, NULL);
return 0;
}
static inline bool is_active_update(struct bt_mesh_dfu_srv *srv, uint8_t idx,
uint16_t timeout_base,
const uint64_t *blob_id, uint8_t ttl,
uint16_t meta_checksum)
{
return (srv->update.idx != idx || srv->blob.state.xfer.id != *blob_id ||
srv->update.ttl != ttl ||
srv->update.timeout_base != timeout_base ||
srv->update.meta != meta_checksum);
}
static int handle_start(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct bt_mesh_dfu_srv *srv = mod->user_data;
const struct bt_mesh_blob_io *io;
uint16_t timeout_base, meta_checksum;
enum bt_mesh_dfu_status status;
uint8_t ttl, idx;
uint64_t blob_id;
int err;
struct net_buf_simple_state buf_state;
ttl = net_buf_simple_pull_u8(buf);
timeout_base = net_buf_simple_pull_le16(buf);
blob_id = net_buf_simple_pull_le64(buf);
idx = net_buf_simple_pull_u8(buf);
meta_checksum = dfu_metadata_checksum(buf);
BT_DBG("%u ttl: %u extra time: %u", idx, ttl, timeout_base);
if ((!buf->len || meta_checksum == srv->update.meta) &&
srv->update.phase == BLE_MESH_DFU_PHASE_TRANSFER_ERR &&
srv->update.ttl == ttl &&
srv->update.timeout_base == timeout_base &&
srv->update.idx == idx &&
srv->blob.state.xfer.id == blob_id) {
srv->update.phase = BLE_MESH_DFU_PHASE_TRANSFER_ACTIVE;
status = BLE_MESH_DFU_SUCCESS;
store_state(srv);
/* blob srv will resume the transfer. */
BT_DBG("Resuming transfer");
goto rsp;
}
if (bt_mesh_dfu_srv_is_busy(srv)) {
if (is_active_update(srv, idx, timeout_base, &blob_id, ttl,
meta_checksum)) {
status = BLE_MESH_DFU_ERR_WRONG_PHASE;
} else {
status = BLE_MESH_DFU_SUCCESS;
srv->update.ttl = ttl;
srv->blob.state.xfer.id = blob_id;
}
BT_WARN("Busy. Phase: %u", srv->update.phase);
goto rsp;
}
net_buf_simple_save(buf, &buf_state);
status = metadata_check(srv, idx, buf,
(enum bt_mesh_dfu_effect *)&srv->update.effect);
net_buf_simple_restore(buf, &buf_state);
if (status != BLE_MESH_DFU_SUCCESS) {
goto rsp;
}
srv->update.ttl = ttl;
srv->update.timeout_base = timeout_base;
srv->update.meta = meta_checksum;
io = NULL;
err = srv->cb->start(srv, &srv->imgs[idx], buf, &io);
if (err == -EALREADY || (!err && bt_mesh_has_addr(ctx->addr))) {
/* This image has already been received or this is a
* self-update. Skip the transfer phase and proceed to
* verifying update.
*/
status = BLE_MESH_DFU_SUCCESS;
srv->update.idx = idx;
srv->blob.state.xfer.id = blob_id;
srv->update.phase = BLE_MESH_DFU_PHASE_VERIFY;
update_status_rsp(srv, ctx, status, NULL);
verify(srv);
return 0;
}
if (err == -ENOMEM) {
status = BLE_MESH_DFU_ERR_RESOURCES;
goto rsp;
}
if (err == -EBUSY) {
status = BLE_MESH_DFU_ERR_TEMPORARILY_UNAVAILABLE;
goto rsp;
}
if (err || !io || !io->wr) {
status = BLE_MESH_DFU_ERR_INTERNAL;
goto rsp;
}
err = bt_mesh_blob_srv_recv(&srv->blob, blob_id, io,
ttl, timeout_base);
if (err) {
status = BLE_MESH_DFU_ERR_BLOB_XFER_BUSY;
goto rsp;
}
srv->update.idx = idx;
srv->update.phase = BLE_MESH_DFU_PHASE_TRANSFER_ACTIVE;
status = BLE_MESH_DFU_SUCCESS;
store_state(srv);
rsp:
update_status_rsp(srv, ctx, status, NULL);
return 0;
}
static int handle_cancel(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct bt_mesh_dfu_srv *srv = mod->user_data;
if (srv->update.idx == UPDATE_IDX_NONE) {
goto rsp;
}
BT_DBG("");
bt_mesh_blob_srv_cancel(&srv->blob);
srv->update.phase = BLE_MESH_DFU_PHASE_IDLE;
xfer_failed(srv);
rsp:
update_status_rsp(srv, ctx, BLE_MESH_DFU_SUCCESS, NULL);
return 0;
}
static int handle_apply(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct bt_mesh_dfu_srv *srv = mod->user_data;
static const struct bt_mesh_send_cb send_cb = {
.start = apply_rsp_sending,
.end = apply_rsp_sent,
};
BT_DBG("");
if (srv->update.phase == BLE_MESH_DFU_PHASE_APPLYING) {
update_status_rsp(srv, ctx, BLE_MESH_DFU_SUCCESS, NULL);
return 0;
}
if (srv->update.phase != BLE_MESH_DFU_PHASE_VERIFY_OK) {
BT_WARN("Apply: Invalid phase %u", srv->update.phase);
update_status_rsp(srv, ctx, BLE_MESH_DFU_ERR_WRONG_PHASE, NULL);
return 0;
}
/* Postponing the apply callback until the response has been sent, in
* case it triggers a reboot:
*/
srv->update.phase = BLE_MESH_DFU_PHASE_APPLYING;
update_status_rsp(srv, ctx, BLE_MESH_DFU_SUCCESS, &send_cb);
return 0;
}
const struct bt_mesh_model_op _bt_mesh_dfu_srv_op[] = {
{ BLE_MESH_DFU_OP_UPDATE_INFO_GET, 2, (void *)handle_info_get },
{ BLE_MESH_DFU_OP_UPDATE_METADATA_CHECK, 1, (void *)handle_metadata_check },
{ BLE_MESH_DFU_OP_UPDATE_GET, 0, (void *)handle_get },
{ BLE_MESH_DFU_OP_UPDATE_START, 12, (void *)handle_start },
{ BLE_MESH_DFU_OP_UPDATE_CANCEL, 0, (void *)handle_cancel },
{ BLE_MESH_DFU_OP_UPDATE_APPLY, 0, (void *)handle_apply },
BLE_MESH_MODEL_OP_END,
};
static int dfu_srv_init(struct bt_mesh_model *mod)
{
struct bt_mesh_dfu_srv *srv = mod->user_data;
srv->mod = mod;
srv->update.idx = UPDATE_IDX_NONE;
srv->blob.cb = &_bt_mesh_dfu_srv_blob_cb;
if (!srv->cb || !srv->cb->start || !srv->imgs || srv->img_count == 0 ||
srv->img_count == UPDATE_IDX_NONE) {
BT_ERR("Invalid DFU Server initialization");
return -EINVAL;
}
return 0;
}
__attribute__((unused))
static int dfu_srv_settings_set(const struct bt_mesh_model *mod, const char *name,
size_t len_rd, settings_read_cb read_cb,
void *cb_arg)
{
struct bt_mesh_dfu_srv *srv = mod->user_data;
ssize_t len;
if (len_rd < sizeof(srv->update)) {
return -EINVAL;
}
len = read_cb(cb_arg, &srv->update, sizeof(srv->update));
if (len < 0) {
return len;
}
BT_DBG("Recovered transfer (phase: %u, idx: %u)", srv->update.phase,
srv->update.idx);
if (srv->update.phase == BLE_MESH_DFU_PHASE_TRANSFER_ACTIVE) {
BT_DBG("Settings recovered mid-transfer, setting transfer error");
srv->update.phase = BLE_MESH_DFU_PHASE_TRANSFER_ERR;
} else if (srv->update.phase == BLE_MESH_DFU_PHASE_VERIFY_OK) {
BT_DBG("Settings recovered before application, setting verification fail");
srv->update.phase = BLE_MESH_DFU_PHASE_VERIFY_FAIL;
}
return 0;
}
static void dfu_srv_reset(struct bt_mesh_model *mod)
{
struct bt_mesh_dfu_srv *srv = mod->user_data;
srv->update.phase = BLE_MESH_DFU_PHASE_IDLE;
erase_state(srv);
}
static int dfu_srv_deinit(struct bt_mesh_model *mod)
{
dfu_srv_reset(mod);
return 0;
}
const struct bt_mesh_model_cb _bt_mesh_dfu_srv_cb = {
.init = dfu_srv_init,
#if CONFIG_BLE_MESH_DEINIT
.deinit = dfu_srv_deinit,
#endif
};
static void blob_suspended(struct bt_mesh_blob_srv *b)
{
struct bt_mesh_dfu_srv *srv = CONTAINER_OF(b, struct bt_mesh_dfu_srv, blob);
srv->update.phase = BLE_MESH_DFU_PHASE_TRANSFER_ERR;
store_state(srv);
}
static void blob_end(struct bt_mesh_blob_srv *b, uint64_t id, bool success)
{
struct bt_mesh_dfu_srv *srv =
CONTAINER_OF(b, struct bt_mesh_dfu_srv, blob);
BT_DBG("success: %u", success);
if (!success) {
srv->update.phase = BLE_MESH_DFU_PHASE_TRANSFER_ERR;
xfer_failed(srv);
return;
}
verify(srv);
}
static int blob_recover(struct bt_mesh_blob_srv *b,
struct bt_mesh_blob_xfer *xfer,
const struct bt_mesh_blob_io **io)
{
struct bt_mesh_dfu_srv *srv =
CONTAINER_OF(b, struct bt_mesh_dfu_srv, blob);
if (!srv->cb->recover ||
srv->update.phase != BLE_MESH_DFU_PHASE_TRANSFER_ERR ||
srv->update.idx >= srv->img_count) {
return -ENOTSUP;
}
return srv->cb->recover(srv, &srv->imgs[srv->update.idx], io);
}
const struct bt_mesh_blob_srv_cb _bt_mesh_dfu_srv_blob_cb = {
.suspended = blob_suspended,
.end = blob_end,
.recover = blob_recover,
};
void bt_mesh_dfu_srv_verified(struct bt_mesh_dfu_srv *srv)
{
if (srv->update.phase != BLE_MESH_DFU_PHASE_VERIFY) {
BT_WARN("Wrong state");
return;
}
BT_DBG("");
srv->update.phase = BLE_MESH_DFU_PHASE_VERIFY_OK;
store_state(srv);
}
void bt_mesh_dfu_srv_rejected(struct bt_mesh_dfu_srv *srv)
{
if (srv->update.phase != BLE_MESH_DFU_PHASE_VERIFY) {
BT_WARN("Wrong state");
return;
}
BT_DBG("");
srv->update.phase = BLE_MESH_DFU_PHASE_VERIFY_FAIL;
store_state(srv);
}
void bt_mesh_dfu_srv_cancel(struct bt_mesh_dfu_srv *srv)
{
if (srv->update.phase == BLE_MESH_DFU_PHASE_IDLE) {
BT_WARN("Wrong state");
return;
}
(void)bt_mesh_blob_srv_cancel(&srv->blob);
}
void bt_mesh_dfu_srv_applied(struct bt_mesh_dfu_srv *srv)
{
if (srv->update.phase != BLE_MESH_DFU_PHASE_APPLYING) {
BT_WARN("Wrong state");
return;
}
BT_DBG("");
srv->update.phase = BLE_MESH_DFU_PHASE_IDLE;
store_state(srv);
}
bool bt_mesh_dfu_srv_is_busy(const struct bt_mesh_dfu_srv *srv)
{
return srv->update.phase != BLE_MESH_DFU_PHASE_IDLE &&
srv->update.phase != BLE_MESH_DFU_PHASE_TRANSFER_ERR &&
srv->update.phase != BLE_MESH_DFU_PHASE_VERIFY_FAIL;
}
uint8_t bt_mesh_dfu_srv_progress(const struct bt_mesh_dfu_srv *srv)
{
if (!bt_mesh_dfu_srv_is_busy(srv)) {
return 0U;
}
if (srv->update.phase == BLE_MESH_DFU_PHASE_TRANSFER_ACTIVE) {
return bt_mesh_blob_srv_progress(&srv->blob);
}
return 100U;
}
#endif /* CONFIG_BLE_MESH_DFU_SRV */

View File

@@ -0,0 +1,146 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _BLE_MESH_v11_DFD_H__
#define _BLE_MESH_v11_DFD_H__
#ifdef __cplusplus
extern "C" {
#endif
#define BLE_MESH_DFD_OP_RECEIVERS_ADD BLE_MESH_MODEL_OP_2(0x83, 0x11)
#define BLE_MESH_DFD_OP_RECEIVERS_DELETE_ALL BLE_MESH_MODEL_OP_2(0x83, 0x12)
#define BLE_MESH_DFD_OP_RECEIVERS_STATUS BLE_MESH_MODEL_OP_2(0x83, 0x13)
#define BLE_MESH_DFD_OP_RECEIVERS_GET BLE_MESH_MODEL_OP_2(0x83, 0x14)
#define BLE_MESH_DFD_OP_RECEIVERS_LIST BLE_MESH_MODEL_OP_2(0x83, 0x15)
#define BLE_MESH_DFD_OP_CAPABILITIES_GET BLE_MESH_MODEL_OP_2(0x83, 0x16)
#define BLE_MESH_DFD_OP_CAPABILITIES_STATUS BLE_MESH_MODEL_OP_2(0x83, 0x17)
#define BLE_MESH_DFD_OP_GET BLE_MESH_MODEL_OP_2(0x83, 0x18)
#define BLE_MESH_DFD_OP_START BLE_MESH_MODEL_OP_2(0x83, 0x19)
#define BLE_MESH_DFD_OP_SUSPEND BLE_MESH_MODEL_OP_2(0x83, 0x1a)
#define BLE_MESH_DFD_OP_CANCEL BLE_MESH_MODEL_OP_2(0x83, 0x1b)
#define BLE_MESH_DFD_OP_APPLY BLE_MESH_MODEL_OP_2(0x83, 0x1c)
#define BLE_MESH_DFD_OP_STATUS BLE_MESH_MODEL_OP_2(0x83, 0x1d)
#define BLE_MESH_DFD_OP_UPLOAD_GET BLE_MESH_MODEL_OP_2(0x83, 0x1e)
#define BLE_MESH_DFD_OP_UPLOAD_START BLE_MESH_MODEL_OP_2(0x83, 0x1f)
#define BLE_MESH_DFD_OP_UPLOAD_START_OOB BLE_MESH_MODEL_OP_2(0x83, 0x20)
#define BLE_MESH_DFD_OP_UPLOAD_CANCEL BLE_MESH_MODEL_OP_2(0x83, 0x21)
#define BLE_MESH_DFD_OP_UPLOAD_STATUS BLE_MESH_MODEL_OP_2(0x83, 0x22)
#define BLE_MESH_DFD_OP_FW_GET BLE_MESH_MODEL_OP_2(0x83, 0x23)
#define BLE_MESH_DFD_OP_FW_GET_BY_INDEX BLE_MESH_MODEL_OP_2(0x83, 0x24)
#define BLE_MESH_DFD_OP_FW_DELETE BLE_MESH_MODEL_OP_2(0x83, 0x25)
#define BLE_MESH_DFD_OP_FW_DELETE_ALL BLE_MESH_MODEL_OP_2(0x83, 0x26)
#define BLE_MESH_DFD_OP_FW_STATUS BLE_MESH_MODEL_OP_2(0x83, 0x27)
/**
* @defgroup bt_mesh_dfd Firmware Distribution models
* @ingroup bt_mesh
* @{
*/
/** Firmware distribution status. */
enum bt_mesh_dfd_status {
/** The message was processed successfully. */
BLE_MESH_DFD_SUCCESS,
/** Insufficient resources on the node. */
BLE_MESH_DFD_ERR_INSUFFICIENT_RESOURCES,
/** The operation cannot be performed while the Server is in the current
* phase.
*/
BLE_MESH_DFD_ERR_WRONG_PHASE,
/** An internal error occurred on the node. */
BLE_MESH_DFD_ERR_INTERNAL,
/** The requested firmware image is not stored on the Distributor. */
BLE_MESH_DFD_ERR_FW_NOT_FOUND,
/** The AppKey identified by the AppKey Index is not known to the node.
*/
BLE_MESH_DFD_ERR_INVALID_APPKEY_INDEX,
/** There are no Target nodes in the Distribution Receivers List
* state.
*/
BLE_MESH_DFD_ERR_RECEIVERS_LIST_EMPTY,
/** Another firmware image distribution is in progress. */
BLE_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION,
/** Another upload is in progress. */
BLE_MESH_DFD_ERR_BUSY_WITH_UPLOAD,
/** The URI scheme name indicated by the Update URI is not supported. */
BLE_MESH_DFD_ERR_URI_NOT_SUPPORTED,
/** The format of the Update URI is invalid. */
BLE_MESH_DFD_ERR_URI_MALFORMED,
/** The URI is currently unreachable. */
BLE_MESH_DFD_ERR_URI_UNREACHABLE,
/** The Check Firmware OOB procedure did not find any new firmware. */
BLE_MESH_DFD_ERR_NEW_FW_NOT_AVAILABLE,
/** The suspension of the Distribute Firmware procedure failed. */
BLE_MESH_DFD_ERR_SUSPEND_FAILED,
};
/** Firmware distribution phases. */
enum bt_mesh_dfd_phase {
/** No firmware distribution is in progress. */
BLE_MESH_DFD_PHASE_IDLE,
/** Firmware distribution is in progress. */
BLE_MESH_DFD_PHASE_TRANSFER_ACTIVE,
/** The Transfer BLOB procedure has completed successfully. */
BLE_MESH_DFD_PHASE_TRANSFER_SUCCESS,
/** The Apply Firmware on Target Nodes procedure is being executed. */
BLE_MESH_DFD_PHASE_APPLYING_UPDATE,
/** The Distribute Firmware procedure has completed successfully. */
BLE_MESH_DFD_PHASE_COMPLETED,
/** The Distribute Firmware procedure has failed. */
BLE_MESH_DFD_PHASE_FAILED,
/** The Cancel Firmware Update procedure is being executed. */
BLE_MESH_DFD_PHASE_CANCELING_UPDATE,
/** The Transfer BLOB procedure is suspended. */
BLE_MESH_DFD_PHASE_TRANSFER_SUSPENDED,
};
/** Firmware upload phases. */
enum bt_mesh_dfd_upload_phase {
/** No firmware upload is in progress. */
BLE_MESH_DFD_UPLOAD_PHASE_IDLE,
/** The Store Firmware procedure is being executed. */
BLE_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE,
/** The Store Firmware procedure or Store Firmware OOB procedure failed.
*/
BLE_MESH_DFD_UPLOAD_PHASE_TRANSFER_ERROR,
/** The Store Firmware procedure or the Store Firmware OOB procedure
* completed successfully.
*/
BLE_MESH_DFD_UPLOAD_PHASE_TRANSFER_SUCCESS,
};
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* _BLE_MESH_v11_DFD_H__ */

View File

@@ -0,0 +1,472 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @defgroup bt_mesh_dfd_cli Device Firmware Distribution Client model
* @ingroup bt_mesh_dfd
* @{
* @brief API for the Device Firmware Distribution Client model
*/
#ifndef _BLE_MESH_v11_DFD_CLI_H__
#define _BLE_MESH_v11_DFD_CLI_H__
#include "mesh/access.h"
#include "mesh/client_common.h"
#include "mesh_v1.1/dfu/dfd.h"
#include "mesh_v1.1/dfu/dfu_cli.h"
#include "mesh_v1.1/mbt/blob_cli.h"
#include "mesh_v1.1/mbt/blob_srv.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Device Firmware Distribution Client model instance. */
typedef bt_mesh_client_user_data_t bt_mesh_dfd_client_t;
/** @brief DFD Client internal data structure. */
typedef bt_mesh_client_internal_data_t dfd_internal_data_t;
/*!< Maximum value of upload progress indicating progress is unset. */
#define UPLOAD_PROGRESS_UNSET 101
/*!< In-band upload type. */
#define UPLOAD_IN_BAND 0x00
/*!< Out-of-band upload type. */
#define UPLOAD_OOB 0x01
/*!< Upload type is not set. */
#define UPLOAD_TYPE_UNSET 0xFF
/*!< Extract target address from target info bitfield. */
#define TARGET_ADDR(target_info) (target_info >> 17)
/*!< Extract target update phase from target info bitfield. */
#define TARGET_UPDATE_PHASE(target_info) ((target_info >> 13) & 0x0f)
/*!< Extract target update status from target info bitfield. */
#define TARGET_UPDATE_STATUS(target_info) ((target_info >> 10) & 0x07)
/*!< Extract target transfer status from target info bitfield. */
#define TARGET_TRANSFER_STATUS(target_info) ((target_info >> 6) & 0x0f)
/*!< Extract target transfer progress from target info bitfield. */
#define TARGET_TRANSFER_PROGRESS(target_info) (target_info & 0x3f)
/**
* @brief DFD Client receiver entry structure.
*
* This structure represents a single receiver node that will receive firmware
* distribution. Each receiver is identified by its unicast address and the
* firmware image index that should be distributed to it.
*/
typedef struct {
uint16_t addr; /*!< Unicast address of the receiver node. */
uint8_t fw_idx; /*!< Index of the firmware image to distribute. */
} dfd_cli_receiver_entry_t;
/**
* @brief Target node entry information structure.
*
* This structure contains detailed information about a target node's
* firmware distribution status, including address, update phase, transfer
* progress, and other related information.
*/
typedef struct {
uint32_t addr:15; /*!< Unicast address of the target node. */
uint32_t retrieved_update_phase:4; /*!< Current update phase of the target. */
uint32_t update_status:3; /*!< Update status of the target node. */
uint32_t transfer_status:4; /*!< Transfer status of the target. */
uint32_t transfer_progress:6; /*!< Transfer progress percentage. */
uint8_t update_fw_idx; /*!< Index of firmware being updated. */
} target_node_entry_t;
/**
* @brief DFD receiver status response structure.
*
* This structure contains the status response for receiver add/delete
* operations, including the operation result and current receiver list size.
*/
typedef struct {
uint8_t status; /*!< Status code of the operation (see @ref bt_mesh_dfd_status). */
uint16_t receiver_list_cnt; /*!< Current number of receivers in the distribution list. */
} dfd_cli_receiver_status_t;
/**
* @brief DFD receiver list response structure.
*
* This structure contains the response to a receivers get request,
* providing a list of target nodes with their current status information.
*/
typedef struct {
uint16_t entries_cnt; /*!< Number of receiver entries in the list. */
uint16_t first_index; /*!< Index of the first entry in the list. */
target_node_entry_t *entries; /*!< Pointer to array of target node entries. */
} dfd_cli_receiver_list_t;
/**
* @brief DFD distribution capabilities structure.
*
* This structure contains the capabilities of the DFD Server, including
* storage limits, receiver limits, and supported features.
*/
typedef struct {
uint16_t max_receiver_list_sz; /*!< Maximum number of receivers supported. */
uint16_t max_fw_list_sz; /*!< Maximum number of firmware images supported. */
uint32_t max_fw_sz; /*!< Maximum firmware image size supported. */
uint32_t max_upload_space; /*!< Total upload storage space available. */
uint32_t remaining_upload_space; /*!< Remaining upload storage space. */
uint8_t oob_retrieval_supported; /*!< OOB retrieval support flag. */
struct net_buf_simple *supported_url_scheme_names; /*!< Supported URL scheme names. */
} dfd_cli_dist_caps_t;
/**
* @brief DFD distribution status structure.
*
* This structure contains the current status of an ongoing or completed
* firmware distribution operation, including phase, progress, and configuration.
*/
typedef struct {
uint8_t status; /*!< Distribution status code (see @ref bt_mesh_dfd_status). */
uint8_t dist_phase; /*!< Current distribution phase (see @ref bt_mesh_dfd_phase). */
uint16_t multicast_address; /*!< Multicast address used for distribution. */
uint16_t appkey_idx; /*!< Application key index used for distribution. */
uint8_t ttl; /*!< TTL value used for distribution messages. */
uint16_t timeout_base; /*!< Base timeout value for distribution. */
uint8_t trans_mode:2; /*!< Transfer mode (push or pull). */
uint8_t update_policy:1; /*!< Update policy (single or all). */
uint8_t RFU:5; /*!< Reserved for future use. */
uint16_t fw_idx; /*!< Index of firmware being distributed. */
} dfd_cli_dist_status_t;
/**
* @brief DFD upload status structure.
*
* This structure contains the current status of a firmware upload operation,
* including phase, progress, and firmware identification.
*/
typedef struct {
uint8_t status; /*!< Upload operation status code (see @ref bt_mesh_dfd_status). */
uint8_t upload_phase; /*!< Current upload phase (see @ref bt_mesh_dfd_upload_phase). */
uint8_t upload_progress:7; /*!< Upload progress percentage (0-100). */
uint8_t upload_type:1; /*!< Upload type (in-band or OOB). */
union {
struct net_buf_simple *fwid; /*!< Firmware ID for in-band uploads. */
struct net_buf_simple *oob_fwid; /*!< Firmware ID for OOB uploads. */
};
} dfd_cli_upload_status_t;
/**
* @brief DFD firmware status structure.
*
* This structure contains the status response for firmware management
* operations, including information about firmware images.
*/
typedef struct {
uint8_t status; /*!< Firmware operation status code (see @ref bt_mesh_dfd_status). */
uint16_t entry_cnt; /*!< Number of firmware entries. */
uint16_t firmware_image_index; /*!< Index of the firmware image. */
struct net_buf_simple *fwid; /*!< Firmware ID buffer. */
} dfd_cli_firmware_status_t;
/**
* @brief DFD distribution start parameters structure.
*
* This structure contains parameters for starting a firmware distribution
* operation, including target configuration and distribution settings.
*/
typedef struct {
uint8_t ttl; /*!< TTL value for distribution messages. */
uint8_t trans_mode:2; /*!< Transfer mode (push or pull). */
uint8_t update_policy:1; /*!< Update policy (single or all). */
uint8_t RFU:5; /*!< Reserved for future use. */
uint16_t app_idx; /*!< Application key index for distribution. */
uint16_t timeout_base; /*!< Base timeout value for distribution. */
uint16_t fw_idx; /*!< Index of firmware to distribute. */
bool is_va; /*!< True if using virtual address, false for group address. */
union {
uint16_t group_addr; /*!< Group address for distribution (if is_va is false). */
uint8_t label_uuid[16]; /*!< Virtual label UUID for distribution (if is_va is true). */
};
} dfd_cli_dist_start_t;
/**
* @brief DFD distribution upload start parameters structure.
*
* This structure contains parameters for starting an in-band firmware
* upload operation to the DFD Server.
*/
typedef struct {
uint8_t ttl; /*!< TTL value for upload messages. */
uint16_t timeout_base; /*!< Base timeout value for upload. */
uint32_t fw_size; /*!< Size of the firmware image in bytes. */
uint64_t blob_id; /*!< BLOB ID for the firmware transfer. */
struct net_buf_simple *fwid; /*!< Firmware ID buffer. */
struct net_buf_simple *fw_metadata; /*!< Firmware metadata buffer. */
} dfd_cli_dist_upload_start_t;
/**
* @brief DFD distribution OOB upload start parameters structure.
*
* This structure contains parameters for starting an out-of-band firmware
* upload operation to the DFD Server.
*/
typedef struct {
struct net_buf_simple *fwid; /*!< Firmware ID buffer. */
struct net_buf_simple *url; /*!< URL for retrieving the firmware. */
} dfd_cli_dist_upload_oob_start_t;
/**
* @brief DFD status response union.
*
* This union contains different status response structures for various DFD
* Client operations, allowing type-safe access to operation-specific responses.
*/
typedef union {
dfd_cli_receiver_status_t receiver_status; /*!< Receiver add/delete status. */
dfd_cli_receiver_list_t receiver_list; /*!< Receiver list response. */
dfd_cli_dist_caps_t dist_caps; /*!< Distribution capabilities. */
dfd_cli_dist_status_t dist_status; /*!< Distribution status. */
dfd_cli_upload_status_t upload_status; /*!< Upload status. */
dfd_cli_firmware_status_t firmware_status; /*!< Firmware management status. */
} dfd_status_t;
/*!< DFD Client model operation handlers. */
extern const struct bt_mesh_model_op _bt_mesh_dfd_cli_op[];
/*!< DFD Client model callbacks. */
extern const struct bt_mesh_model_cb _bt_mesh_dfd_cli_cb;
/**
* @brief Add receivers to the distribution list.
*
* Add multiple target nodes to the DFD Server's distribution receiver list.
* These receivers will be included in subsequent firmware distribution operations.
*
* @param[in] param Common client parameters for the operation.
* @param[in] receivers Pointer to array of receiver entries to add.
* @param[in] receivers_cnt Number of receiver entries in the array.
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_dfd_cli_receivers_add(bt_mesh_client_common_param_t *param,
dfd_cli_receiver_entry_t *receivers,
uint16_t receivers_cnt);
/**
* @brief Delete all receivers from the distribution list.
*
* Remove all target nodes from the DFD Server's distribution receiver list.
* This operation will clear the entire receiver list.
*
* @param[in] param Common client parameters for the operation.
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_dfd_cli_receivers_delete_all(bt_mesh_client_common_param_t *param);
/**
* @brief Get the distribution receiver list.
*
* Retrieve a portion of the DFD Server's distribution receiver list.
* Supports pagination to retrieve large receiver lists in chunks.
*
* @param[in] param Common client parameters for the operation.
* @param[in] first_index Index of the first receiver entry to retrieve.
* @param[in] entries_limit Maximum number of entries to retrieve.
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_dfd_cli_receivers_get(bt_mesh_client_common_param_t *param,
uint16_t first_index,
uint16_t entries_limit);
/**
* @brief Get distribution capabilities from the DFD Server.
*
* Query the DFD Server's capabilities, including storage limits,
* supported features, and maximum receiver count.
*
* @param[in] param Common client parameters for the operation.
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_dfd_cli_distribution_capabilities_get(bt_mesh_client_common_param_t *param);
/**
* @brief Get current distribution status from the DFD Server.
*
* Query the current status of firmware distribution operations,
* including phase, progress, and configuration information.
*
* @param[in] param Common client parameters for the operation.
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_dfd_cli_distribution_get(bt_mesh_client_common_param_t *param);
/**
* @brief Start firmware distribution to receivers.
*
* Initiate firmware distribution to all target nodes in the distribution
* receiver list using the specified configuration parameters.
*
* @param[in] param Common client parameters for the operation.
* @param[in] start Distribution start parameters and configuration.
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_dfd_cli_distribution_start(bt_mesh_client_common_param_t *param,
dfd_cli_dist_start_t *start);
/**
* @brief Suspend ongoing firmware distribution.
*
* Suspend a currently active firmware distribution operation.
* The distribution can be resumed later if needed.
*
* @param[in] param Common client parameters for the operation.
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_dfd_cli_distribution_suspend(bt_mesh_client_common_param_t *param);
/**
* @brief Cancel firmware distribution.
*
* Cancel an ongoing or suspended firmware distribution operation.
* This will terminate the distribution process.
*
* @param[in] param Common client parameters for the operation.
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_dfd_cli_distribution_cancel(bt_mesh_client_common_param_t *param);
/**
* @brief Apply distributed firmware on target nodes.
*
* Apply the distributed firmware image on target nodes that have
* successfully received the firmware transfer.
*
* @param[in] param Common client parameters for the operation.
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_dfd_cli_distribution_apply(bt_mesh_client_common_param_t *param);
/**
* @brief Get firmware upload status from the DFD Server.
*
* Query the current status of firmware upload operations, including
* phase, progress, and transfer information.
*
* @param[in] param Common client parameters for the operation.
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_dfd_cli_distribution_upload_get(bt_mesh_client_common_param_t *param);
/**
* @brief Start in-band firmware upload to the DFD Server.
*
* Initiate an in-band firmware upload using BLOB transfer protocol.
* The firmware image will be transferred directly through the mesh network.
*
* @param[in] param Common client parameters for the operation.
* @param[in] start Upload start parameters including firmware details.
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_dfd_cli_distribution_upload_start(bt_mesh_client_common_param_t *param,
dfd_cli_dist_upload_start_t *start);
/**
* @brief Start out-of-band firmware upload to the DFD Server.
*
* Initiate an out-of-band firmware upload where the DFD Server
* retrieves the firmware from the specified URL.
*
* @param[in] param Common client parameters for the operation.
* @param[in] start OOB upload start parameters including URL and firmware ID.
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_dfd_cli_distribution_upload_oob_start(bt_mesh_client_common_param_t *param,
dfd_cli_dist_upload_oob_start_t *start);
/**
* @brief Cancel out-of-band firmware upload.
*
* Cancel an ongoing out-of-band firmware upload operation.
*
* @param[in] param Common client parameters for the operation.
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_dfd_cli_distribution_upload_oob_cancel(bt_mesh_client_common_param_t *param);
/**
* @brief Get firmware information by firmware ID.
*
* Query detailed information about a specific firmware image
* stored on the DFD Server using its firmware ID.
*
* @param[in] param Common client parameters for the operation.
* @param[in] fwid Firmware ID to query information for.
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_dfd_cli_firmware_get(bt_mesh_client_common_param_t *param,
struct net_buf_simple *fwid);
/**
* @brief Get firmware information by index.
*
* Query detailed information about a firmware image stored on the
* DFD Server using its index in the firmware list.
*
* @param[in] param Common client parameters for the operation.
* @param[in] fw_id_index Index of the firmware image to query.
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_dfd_cli_firmware_get_by_index(bt_mesh_client_common_param_t *param,
uint16_t fw_id_index);
/**
* @brief Delete specific firmware image by firmware ID.
*
* Delete a specific firmware image from the DFD Server's storage
* using its firmware ID.
*
* @param[in] param Common client parameters for the operation.
* @param[in] fwid Firmware ID of the image to delete.
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_dfd_cli_firmware_get_delete(bt_mesh_client_common_param_t *param,
struct net_buf_simple *fwid);
/**
* @brief Delete all firmware images from the DFD Server.
*
* Delete all firmware images stored on the DFD Server.
* This operation will clear the entire firmware storage.
*
* @param[in] param Common client parameters for the operation.
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_dfd_cli_firmware_delete_all(bt_mesh_client_common_param_t *param);
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* _BLE_MESH_v11_DFD_CLI_H__ */

View File

@@ -0,0 +1,311 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @defgroup bt_mesh_dfd_srv Firmware Distribution Server model
* @ingroup bt_mesh_dfd
* @{
* @brief API for the Firmware Distribution Server model
*/
#ifndef _BLE_MESH_v11_DFD_SRV_H__
#define _BLE_MESH_v11_DFD_SRV_H__
#include "mesh/access.h"
#include "mesh_v1.1/dfu/dfd.h"
#include "mesh_v1.1/dfu/dfu_cli.h"
#include "mesh_v1.1/mbt/blob_cli.h"
#include "mesh_v1.1/mbt/blob_srv.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef CONFIG_BLE_MESH_DFD_SRV_TARGETS_MAX
#define CONFIG_BLE_MESH_DFD_SRV_TARGETS_MAX 0
#endif
#ifndef CONFIG_BLE_MESH_DFD_SRV_SLOT_MAX_SIZE
#define CONFIG_BLE_MESH_DFD_SRV_SLOT_MAX_SIZE 0
#endif
#ifndef CONFIG_BLE_MESH_DFD_SRV_SLOT_SPACE
#define CONFIG_BLE_MESH_DFD_SRV_SLOT_SPACE 0
#endif
struct bt_mesh_dfd_srv;
#ifdef CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD
/**
* @brief Initialization parameters for the @ref bt_mesh_dfd_srv with OOB
* upload support.
*
* @param[in] _cb Pointer to a @ref bt_mesh_dfd_srv_cb instance.
* @param[in] _oob_schemes Array of OOB schemes supported by the server,
* each scheme being a code point from the
* Bluetooth SIG Assigned Numbers document.
* @param[in] _oob_schemes_count Number of schemes in @c _oob_schemes.
*/
#define BT_MESH_DFD_SRV_OOB_INIT(_cb, _oob_schemes, _oob_schemes_count) \
{ \
.cb = _cb, \
.dfu = BLE_MESH_DFU_CLI_INIT(&_bt_mesh_dfd_srv_dfu_cb), \
.upload = { \
.blob = { .cb = &_bt_mesh_dfd_srv_blob_cb }, \
}, \
.oob_schemes = { \
.schemes = _oob_schemes, \
.count = _oob_schemes_count, \
}, \
}
#endif /* CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD */
/**
* @brief Initialization parameters for the @ref bt_mesh_dfd_srv.
*
* @param[in] _cb Pointer to a @ref bt_mesh_dfd_srv_cb instance.
*/
#define BT_MESH_DFD_SRV_INIT(_cb) \
{ \
.cb = _cb, \
.dfu = BLE_MESH_DFU_CLI_INIT(&_bt_mesh_dfd_srv_dfu_cb), \
.upload = { \
.blob = { .cb = &_bt_mesh_dfd_srv_blob_cb }, \
}, \
}
/**
* @brief Firmware Distribution Server model Composition Data entry.
*
* @param _srv Pointer to a @ref bt_mesh_dfd_srv instance.
*/
#define BT_MESH_MODEL_DFD_SRV(_srv) \
BT_MESH_MODEL_DFU_CLI(&(_srv)->dfu), \
BT_MESH_MODEL_BLOB_SRV(&(_srv)->upload.blob), \
BLE_MESH_MODEL_CB(BLE_MESH_MODEL_ID_DFD_SRV, _bt_mesh_dfd_srv_op, NULL, \
_srv, &_bt_mesh_dfd_srv_cb)
/** Firmware Distribution Server callbacks: */
struct bt_mesh_dfd_srv_cb {
/** @brief Slot receive callback.
*
* Called at the start of an upload procedure. The callback must fill
* @c io with a pointer to a writable BLOB stream for the Firmware Distribution
* Server to write the firmware image to.
*
* @param srv Firmware Distribution Server model instance.
* @param slot DFU image slot being received.
* @param io BLOB stream response pointer.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int (*recv)(struct bt_mesh_dfd_srv *srv,
const struct bt_mesh_dfu_slot *slot,
const struct bt_mesh_blob_io **io);
#ifdef CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD
/** @brief Firmware upload OOB start callback.
*
* Called at the start of an OOB firmware upload. The application must
* start a firmware check using an OOB mechanism, and then call
* @ref bt_mesh_dfd_srv_oob_check_complete. Depending on the return
* value of this function, the application must then start storing the
* firmware image using an OOB mechanism, and call
* @ref bt_mesh_dfd_srv_oob_store_complete. This callback is mandatory
* to support OOB uploads.
*
* @param srv Firmware Distribution Server model instance.
* @param slot Slot to be used for the upload.
* @param uri Pointer to buffer containing the URI used to
* check for new firmware.
* @param uri_len Length of the URI buffer.
* @param fwid Pointer to buffer containing the current
* firmware ID to be used when checking for
* availability of new firmware.
* @param fwid_len Length of the current firmware ID. Must be set
* to the length of the new firmware ID if it is
* available, or to 0 if new firmware is not
* available.
*
* @return BLE_MESH_DFD_SUCCESS on success, or error code otherwise.
*/
int (*start_oob_upload)(struct bt_mesh_dfd_srv *srv,
const struct bt_mesh_dfu_slot *slot,
const char *uri, uint8_t uri_len,
const uint8_t *fwid, uint16_t fwid_len);
/** @brief Cancel store OOB callback
*
* Called when an OOB store is cancelled. The application must stop
* any ongoing OOB image transfer. This callback is mandatory to
* support OOB uploads.
*
* @param srv Firmware Distribution Server model instance.
* @param slot DFU image slot to cancel
*/
void (*cancel_oob_upload)(struct bt_mesh_dfd_srv *srv,
const struct bt_mesh_dfu_slot *slot);
/** @brief Get the progress of an ongoing OOB store
*
* Called by the Firmware Distribution Server model when it needs to
* get the current progress of an ongoing OOB store from the
* application. This callback is mandatory to support OOB uploads.
*
* @param srv Firmware Distribution Server model instance.
* @param slot DFU image slot to get progress for.
*
* @return The current progress of the ongoing OOB store, in percent.
*/
uint8_t (*oob_progress_get)(struct bt_mesh_dfd_srv *srv,
const struct bt_mesh_dfu_slot *slot);
#endif /* CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD */
/** @brief Slot delete callback.
*
* Called when the Firmware Distribution Server is about to delete a DFU image slot.
* All allocated data associated with the firmware slot should be
* deleted.
*
* @param srv Firmware Update Server instance.
* @param slot DFU image slot being deleted.
*/
void (*del)(struct bt_mesh_dfd_srv *srv,
const struct bt_mesh_dfu_slot *slot);
/** @brief Slot send callback.
*
* Called at the start of a distribution procedure. The callback must
* fill @c io with a pointer to a readable BLOB stream for the Firmware
* Distribution Server to read the firmware image from.
*
* @param srv Firmware Distribution Server model instance.
* @param slot DFU image slot being sent.
* @param io BLOB stream response pointer.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int (*send)(struct bt_mesh_dfd_srv *srv,
const struct bt_mesh_dfu_slot *slot,
const struct bt_mesh_blob_io **io);
/** @brief Phase change callback (Optional).
*
* Called whenever the phase of the Firmware Distribution Server changes.
*
* @param srv Firmware Distribution Server model instance.
* @param phase New Firmware Distribution phase.
*/
void (*phase)(struct bt_mesh_dfd_srv *srv, enum bt_mesh_dfd_phase phase);
};
/** Firmware Distribution Server instance. */
struct bt_mesh_dfd_srv {
const struct bt_mesh_dfd_srv_cb *cb;
const struct bt_mesh_model *mod;
struct bt_mesh_dfu_cli dfu;
struct bt_mesh_dfu_target targets[CONFIG_BLE_MESH_DFD_SRV_TARGETS_MAX];
struct bt_mesh_blob_target_pull pull_ctxs[CONFIG_BLE_MESH_DFD_SRV_TARGETS_MAX];
const struct bt_mesh_blob_io *io;
uint16_t target_cnt;
uint16_t slot_idx;
bool apply;
enum bt_mesh_dfd_phase phase;
struct bt_mesh_blob_cli_inputs inputs;
struct {
enum bt_mesh_dfd_upload_phase phase;
struct bt_mesh_dfu_slot *slot;
const struct flash_area *area;
struct bt_mesh_blob_srv blob;
#ifdef CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD
bool is_oob;
bool is_pending_oob_check;
struct {
uint8_t uri_len;
char uri[CONFIG_BLE_MESH_DFU_URI_MAXLEN];
uint16_t current_fwid_len;
uint8_t current_fwid[CONFIG_BLE_MESH_DFU_FWID_MAXLEN];
struct bt_mesh_msg_ctx ctx;
} oob;
#endif /* CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD */
} upload;
#ifdef CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD
struct {
const uint8_t *schemes;
const uint8_t count;
} oob_schemes;
#endif /* CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD */
};
#ifdef CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD
/** @brief Call when an OOB check has completed or failed
*
* This should be called by the application after an OOB check started by the @c start_oob_upload
* callback has completed or failed. The @p status param should be set to one of the following
* values:
*
* * @c BLE_MESH_DFD_SUCCESS if the check was successful and a new firmware ID was found.
* * @c BLE_MESH_DFD_ERR_URI_MALFORMED if the URI is not formatted correctly.
* * @c BLE_MESH_DFD_ERR_URI_NOT_SUPPORTED if the URI scheme is not supported by the node.
* * @c BLE_MESH_DFD_ERR_URI_UNREACHABLE if the URI can't be reached.
* * @c BLE_MESH_DFD_ERR_NEW_FW_NOT_AVAILABLE if the check completes successfully but no new
* firmware is available.
*
* If this function returns 0, the application should then download the firmware to the
* slot. If an error code is returned, the application should abort the OOB upload.
*
* @param srv Firmware Distribution Server model instance.
* @param slot The slot used in the OOB upload.
* @param status The result of the firmware check.
* @param fwid If the check was successful and new firmware found, this should point to a
* buffer containing the new firmware ID to store.
* @param fwid_len The length of the firmware ID pointed to by @p fwid.
*
* @return 0 on success, (negative) error code otherwise.
*/
int 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);
/** @brief Call when an OOB store has completed or failed
*
* This should be called by the application after an OOB store started after a successful call to
* @c bt_mesh_dfd_srv_oob_check_complete has completed successfully or failed.
*
* @param srv Firmware Distribution Server model instance.
* @param slot The slot used when storing the firmware image.
* @param success @c true if the OOB store completed successfully, @c false otherwise.
* @param size The size of the stored firmware image, in bytes.
* @param metadata Pointer to the metadata received OOB, or @c NULL if no metadata was
* received.
* @param metadata_len Size of the metadata pointed to by @p metadata.
*
* @return 0 on success, (negative) error code otherwise.
*/
int 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);
#endif /* CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD */
/** @cond INTERNAL_HIDDEN */
extern const struct bt_mesh_model_op _bt_mesh_dfd_srv_op[];
extern const struct bt_mesh_model_cb _bt_mesh_dfd_srv_cb;
extern const struct bt_mesh_dfu_cli_cb _bt_mesh_dfd_srv_dfu_cb;
extern const struct bt_mesh_blob_srv_cb _bt_mesh_dfd_srv_blob_cb;
/** @endcond */
#ifdef __cplusplus
}
#endif
#endif /* _BLE_MESH_v11_DFD_SRV_H__ */
/** @} */

View File

@@ -0,0 +1,173 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _BLE_MESH_v11_DFU_H__
#define _BLE_MESH_v11_DFU_H__
#include <sys/types.h>
#include "mesh/types.h"
#include "mesh/utils.h"
#include "mesh_v1.1/mbt/blob.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup bt_mesh_dfu Bluetooth Mesh Device Firmware Update
* @ingroup bt_mesh
* @{
*/
#ifndef CONFIG_BLE_MESH_DFU_FWID_MAXLEN
#define CONFIG_BLE_MESH_DFU_FWID_MAXLEN 0
#endif
#ifndef CONFIG_BLE_MESH_DFU_METADATA_MAXLEN
#define CONFIG_BLE_MESH_DFU_METADATA_MAXLEN 0
#endif
#ifndef CONFIG_BLE_MESH_DFU_URI_MAXLEN
#define CONFIG_BLE_MESH_DFU_URI_MAXLEN 0
#endif
#ifndef CONFIG_BLE_MESH_DFU_SLOT_CNT
#define CONFIG_BLE_MESH_DFU_SLOT_CNT 0
#endif
/** DFU transfer phase. */
enum bt_mesh_dfu_phase {
/** Ready to start a Receive Firmware procedure. */
BLE_MESH_DFU_PHASE_IDLE,
/** The Transfer BLOB procedure failed. */
BLE_MESH_DFU_PHASE_TRANSFER_ERR,
/** The Receive Firmware procedure is being executed. */
BLE_MESH_DFU_PHASE_TRANSFER_ACTIVE,
/** The Verify Firmware procedure is being executed. */
BLE_MESH_DFU_PHASE_VERIFY,
/** The Verify Firmware procedure completed successfully. */
BLE_MESH_DFU_PHASE_VERIFY_OK,
/** The Verify Firmware procedure failed. */
BLE_MESH_DFU_PHASE_VERIFY_FAIL,
/** The Apply New Firmware procedure is being executed. */
BLE_MESH_DFU_PHASE_APPLYING,
/** Firmware transfer has been canceled. */
BLE_MESH_DFU_PHASE_TRANSFER_CANCELED,
/** Firmware applying succeeded. */
BLE_MESH_DFU_PHASE_APPLY_SUCCESS,
/** Firmware applying failed. */
BLE_MESH_DFU_PHASE_APPLY_FAIL,
/** Phase of a node was not yet retrieved. */
BLE_MESH_DFU_PHASE_UNKNOWN,
};
/** DFU status. */
enum bt_mesh_dfu_status {
/** The message was processed successfully. */
BLE_MESH_DFU_SUCCESS,
/** Insufficient resources on the node */
BLE_MESH_DFU_ERR_RESOURCES,
/** The operation cannot be performed while the Server is in the current
* phase.
*/
BLE_MESH_DFU_ERR_WRONG_PHASE,
/** An internal error occurred on the node. */
BLE_MESH_DFU_ERR_INTERNAL,
/** The message contains a firmware index value that is not expected. */
BLE_MESH_DFU_ERR_FW_IDX,
/** The metadata check failed. */
BLE_MESH_DFU_ERR_METADATA,
/** The Server cannot start a firmware update. */
BLE_MESH_DFU_ERR_TEMPORARILY_UNAVAILABLE,
/** Another BLOB transfer is in progress. */
BLE_MESH_DFU_ERR_BLOB_XFER_BUSY,
};
/** Expected effect of a DFU transfer. */
enum bt_mesh_dfu_effect {
/** No changes to node Composition Data. */
BLE_MESH_DFU_EFFECT_NONE,
/** Node Composition Data changed and the node does not support remote
* provisioning.
*/
BLE_MESH_DFU_EFFECT_COMP_CHANGE_NO_RPR,
/** Node Composition Data changed, and remote provisioning is supported.
* The node supports remote provisioning and Composition Data Page
* 0x80. Page 0x80 contains different Composition Data than Page 0x0.
*/
BLE_MESH_DFU_EFFECT_COMP_CHANGE,
/** Node will be unprovisioned after the update. */
BLE_MESH_DFU_EFFECT_UNPROV,
};
/** Action for DFU iteration callbacks. */
enum bt_mesh_dfu_iter {
/** Stop iterating. */
BLE_MESH_DFU_ITER_STOP,
/** Continue iterating. */
BLE_MESH_DFU_ITER_CONTINUE,
};
/** DFU image instance.
*
* Each DFU image represents a single updatable firmware image.
*/
struct bt_mesh_dfu_img {
/** Firmware ID. */
const void *fwid;
/** Length of the firmware ID. */
size_t fwid_len;
/** Update URI, or NULL. */
const char *uri;
};
/** DFU image slot for DFU distribution. */
struct bt_mesh_dfu_slot {
/** Size of the firmware in bytes. */
size_t size;
/** Length of the firmware ID. */
size_t fwid_len;
/** Length of the metadata. */
size_t metadata_len;
/** Firmware ID. */
uint8_t fwid[CONFIG_BLE_MESH_DFU_FWID_MAXLEN];
/** Metadata. */
uint8_t metadata[CONFIG_BLE_MESH_DFU_METADATA_MAXLEN];
};
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* _BLE_MESH_v11_DFU_H__ */

View File

@@ -0,0 +1,430 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @defgroup bt_mesh_dfu_cli Firmware Uppdate Client model
* @ingroup bt_mesh_dfu
* @{
* @brief API for the Bluetooth Mesh Firmware Update Client model
*/
#ifndef _BLE_MESH_v11_DFU_CLI_H__
#define _BLE_MESH_v11_DFU_CLI_H__
#include "freertos/semphr.h"
#include "mesh/access.h"
#include "mesh_v1.1/mbt/blob_cli.h"
#include "mesh_v1.1/dfu/dfu.h"
#ifdef __cplusplus
extern "C" {
#endif
struct bt_mesh_dfu_cli;
/**
*
* @brief Initialization parameters for the @ref bt_mesh_dfu_cli.
*
* @sa bt_mesh_dfu_cli_cb.
*
* @param _handlers Handler callback structure.
*/
#define BLE_MESH_DFU_CLI_INIT(_handlers) \
{ \
.cb = _handlers, \
.blob = { .cb = &_bt_mesh_dfu_cli_blob_handlers }, \
}
/**
*
* @brief Firmware Update Client model Composition Data entry.
*
* @param _cli Pointer to a @ref bt_mesh_dfu_cli instance.
*/
#define BT_MESH_MODEL_DFU_CLI(_cli) \
BT_MESH_MODEL_BLOB_CLI(&(_cli)->blob), \
BT_MESH_MODEL_CB(BLE_MESH_MODEL_ID_DFU_CLI, _bt_mesh_dfu_cli_op, NULL, \
_cli, &_bt_mesh_dfu_cli_cb)
/** DFU Target node. */
struct bt_mesh_dfu_target {
/** BLOB Target node */
struct bt_mesh_blob_target blob;
/** Image index on the Target node */
uint8_t img_idx;
/** Expected DFU effect, see @ref bt_mesh_dfu_effect. */
uint8_t effect;
/** Current DFU status, see @ref bt_mesh_dfu_status. */
uint8_t status;
/** Current DFU phase, see @ref bt_mesh_dfu_phase. */
uint8_t phase;
};
/** Metadata status response. */
struct bt_mesh_dfu_metadata_status {
/** Image index. */
uint8_t idx;
/** Status code. */
enum bt_mesh_dfu_status status;
/** Effect of transfer. */
enum bt_mesh_dfu_effect effect;
};
/** DFU Target node status parameters.
* The structure should be same as
* @ref esp_ble_mesh_device_firmware_update_status_t
*/
struct bt_mesh_dfu_target_status {
/** Status of the previous operation. */
enum bt_mesh_dfu_status status;
/** Phase of the current DFU transfer. */
enum bt_mesh_dfu_phase phase;
/** The effect the update will have on the Target device's state. */
enum bt_mesh_dfu_effect effect;
/** BLOB ID used in the transfer. */
uint64_t blob_id;
/** Image index to transfer. */
uint8_t img_idx;
/** TTL used in the transfer. */
uint8_t ttl;
/** Additional response time for the Target nodes, in 10-second increments.
*
* The extra time can be used to give the Target nodes more time to respond
* to messages from the Client. The actual timeout will be calculated
* according to the following formula:
*
* @verbatim
* timeout = 20 seconds + (10 seconds * timeout_base) + (100 ms * TTL)
* @endverbatim
*
* If a Target node fails to respond to a message from the Client within the
* configured transfer timeout, the Target node is dropped.
*/
uint16_t timeout_base;
};
/** @brief DFU image callback.
*
* The image callback is called for every DFU image on the Target node when
* calling @ref bt_mesh_dfu_cli_imgs_get.
*
* @param cli Firmware Update Client model instance.
* @param ctx Message context of the received message.
* @param idx Image index.
* @param total Total number of images on the Target node.
* @param img Image information for the given image index.
* @param cb_data Callback data.
*
* @retval BLE_MESH_DFU_ITER_STOP Stop iterating through the image list and
* return from @ref bt_mesh_dfu_cli_imgs_get.
* @retval BLE_MESH_DFU_ITER_CONTINUE Continue iterating through the image list
* if any images remain.
*/
typedef enum bt_mesh_dfu_iter(*bt_mesh_dfu_img_cb_t)(struct bt_mesh_dfu_cli *cli,
struct bt_mesh_msg_ctx *ctx,
uint8_t idx, uint8_t total,
const struct bt_mesh_dfu_img *img,
void *cb_data);
/** Firmware Update Client event callbacks. */
struct bt_mesh_dfu_cli_cb {
/** @brief BLOB transfer is suspended.
*
* Called when the BLOB transfer is suspended due to response timeout from all Target nodes.
*
* @param cli Firmware Update Client model instance.
*/
void (*suspended)(struct bt_mesh_dfu_cli *cli);
/** @brief DFU ended.
*
* Called when the DFU transfer ends, either because all Target nodes were
* lost or because the transfer was completed successfully.
*
* @param cli Firmware Update Client model instance.
* @param reason Reason for ending.
*/
void (*ended)(struct bt_mesh_dfu_cli *cli,
enum bt_mesh_dfu_status reason);
/** @brief DFU transfer applied on all active Target nodes.
*
* Called at the end of the apply procedure started by @ref
* bt_mesh_dfu_cli_apply.
*
* @param cli Firmware Update Client model instance.
*/
void (*applied)(struct bt_mesh_dfu_cli *cli);
/** @brief DFU transfer confirmed on all active Target nodes.
*
* Called at the end of the apply procedure started by @ref
* bt_mesh_dfu_cli_confirm.
*
* @param cli Firmware Update Client model instance.
*/
void (*confirmed)(struct bt_mesh_dfu_cli *cli);
/** @brief DFU Target node was lost.
*
* A DFU Target node was dropped from the receivers list. The Target node's
* @c status is set to reflect the reason for the failure.
*
* @param cli Firmware Update Client model instance.
* @param target DFU Target node that was lost.
*/
void (*lost_target)(struct bt_mesh_dfu_cli *cli,
struct bt_mesh_dfu_target *target);
};
enum {
STATE_IDLE,
STATE_TRANSFER,
STATE_REFRESH,
STATE_VERIFIED,
STATE_APPLY,
STATE_APPLIED,
STATE_CONFIRM,
STATE_CANCEL,
STATE_SUSPENDED,
};
typedef struct {
sys_snode_t node;
uint8_t ttl;
uint8_t type;
uint8_t img_cnt;
uint32_t opcode;
void *params;
bt_mesh_dfu_img_cb_t img_cb;
struct bt_mesh_dfu_cli *dfu_cli;
struct bt_mesh_msg_ctx ctx;
int32_t timeout;
struct k_delayed_work timer; /* Time used to get response. Only for internal use. */
} bt_mesh_dfu_cli_req_t;
/** Firmware Update Client model instance.
*
* Should be initialized with @ref BLE_MESH_DFU_CLI_INIT.
*/
struct bt_mesh_dfu_cli {
/** Callback structure. */
const struct bt_mesh_dfu_cli_cb *cb;
/** Underlying BLOB Transfer Client. */
struct bt_mesh_blob_cli blob;
/* runtime state */
uint32_t op;
struct bt_mesh_model *mod;
struct {
const struct bt_mesh_dfu_slot *slot;
const struct bt_mesh_blob_io *io;
struct bt_mesh_blob_xfer blob;
uint8_t state;
uint8_t flags;
} xfer;
bt_mesh_dfu_cli_req_t *req;
};
/** BLOB parameters for Firmware Update Client transfer: */
struct bt_mesh_dfu_cli_xfer_blob_params {
/* Logarithmic representation of the block size. */
uint8_t block_size_log;
/** Base chunk size. May be smaller for the last chunk. */
uint16_t chunk_size;
};
/** Firmware Update Client transfer parameters: */
struct bt_mesh_dfu_cli_xfer {
/** BLOB ID to use for this transfer, or 0 to set it randomly. */
uint64_t blob_id;
/** DFU image slot to transfer. */
const struct bt_mesh_dfu_slot *slot;
/** Transfer mode (Push (Push BLOB Transfer Mode) or Pull (Pull BLOB Transfer Mode)) */
enum bt_mesh_blob_xfer_mode mode;
/** BLOB parameters to be used for the transfer, or NULL to retrieve Target nodes'
* capabilities before sending a firmware.
*/
const struct bt_mesh_dfu_cli_xfer_blob_params *blob_params;
};
/** @brief Start distributing a DFU.
*
* Starts distribution of the firmware in the given slot to the list of DFU
* Target nodes in @c ctx. The transfer runs in the background, and its end is
* signalled through the @ref bt_mesh_dfu_cli_cb::ended callback.
*
* @note The BLOB Transfer Client transfer inputs @c targets list must point to a list of @ref
* bt_mesh_dfu_target nodes.
*
* @param cli Firmware Update Client model instance.
* @param inputs BLOB Transfer Client transfer inputs.
* @param io BLOB stream to read BLOB from.
* @param xfer Firmware Update Client transfer parameters.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_dfu_cli_send(struct bt_mesh_dfu_cli *cli,
const struct bt_mesh_blob_cli_inputs *inputs,
const struct bt_mesh_blob_io *io,
const struct bt_mesh_dfu_cli_xfer *xfer);
/** @brief Suspend a DFU transfer.
*
* @param cli Firmware Update Client instance.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_dfu_cli_suspend(struct bt_mesh_dfu_cli *cli);
/** @brief Resume the suspended transfer.
*
* @param cli Firmware Update Client instance.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_dfu_cli_resume(struct bt_mesh_dfu_cli *cli);
/** @brief Cancel a DFU transfer.
*
* Will cancel the ongoing DFU transfer, or the transfer on a specific Target
* node if @c ctx is valid.
*
* @param cli Firmware Update Client model instance.
* @param ctx Message context, or NULL to cancel the ongoing DFU transfer.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_dfu_cli_cancel(struct bt_mesh_dfu_cli *cli,
struct bt_mesh_msg_ctx *ctx);
/** @brief Apply the completed DFU transfer.
*
* A transfer can only be applied after it has ended successfully. The Firmware
* Update Client's @c applied callback is called at the end of the apply procedure.
*
* @param cli Firmware Update Client model instance.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_dfu_cli_apply(struct bt_mesh_dfu_cli *cli);
/** @brief Confirm that the active transfer has been applied on the Target nodes.
*
* A transfer can only be confirmed after it has been applied. The Firmware Update
* Client's @c confirmed callback is called at the end of the confirm
* procedure.
*
* Target nodes that have reported the effect as @ref BLE_MESH_DFU_EFFECT_UNPROV
* are expected to not respond to the query, and will fail if they do.
*
* @param cli Firmware Update Client model instance.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_dfu_cli_confirm(struct bt_mesh_dfu_cli *cli);
/** @brief Get progress as a percentage of completion.
*
* @param cli Firmware Update Client model instance.
*
* @return The progress of the current transfer in percent, or 0 if no
* transfer is active.
*/
uint8_t bt_mesh_dfu_cli_progress(struct bt_mesh_dfu_cli *cli);
/** @brief Check whether a DFU transfer is in progress.
*
* @param cli Firmware Update Client model instance.
*
* @return true if the BLOB Transfer Client is currently participating in a transfer,
* false otherwise.
*/
bool bt_mesh_dfu_cli_is_busy(struct bt_mesh_dfu_cli *cli);
/** @brief Perform a DFU image list request.
*
* Requests the full list of DFU images on a Target node, and iterates through
* them, calling the @c cb for every image.
*
* The DFU image list request can be used to determine which image index the
* Target node holds its different firmwares in.
*
* Waits for a response until the procedure timeout expires.
*
* @param cli Firmware Update Client model instance.
* @param ctx Message context.
* @param cb Callback to call for each image index.
* @param cb_data Callback data to pass to @c cb.
* @param first_idx Index of the first requested imgs entry.
* @param max_count Max number of images to return.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_dfu_cli_imgs_get(struct bt_mesh_dfu_cli *cli,
struct bt_mesh_msg_ctx *ctx,
bt_mesh_dfu_img_cb_t cb, void *cb_data,
uint8_t first_idx, uint8_t max_count);
/** @brief Perform a metadata check for the given DFU image slot.
*
* The metadata check procedure allows the Firmware Update Client to check if a Target
* node will accept a transfer of this DFU image slot, and what the effect would be.
*
* Waits for a response until the procedure timeout expires.
*
* @param cli Firmware Update Client model instance.
* @param ctx Message context.
* @param img_idx Target node's image index to check.
* @param metadata DFU image metadata to check for.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_dfu_cli_metadata_check(struct bt_mesh_dfu_cli *cli,
struct bt_mesh_msg_ctx *ctx, uint8_t img_idx,
struct net_buf_simple *metadata);
/** @brief Get the status of a Target node.
*
* @param cli Firmware Update Client model instance.
* @param ctx Message context.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_dfu_cli_status_get(struct bt_mesh_dfu_cli *cli,
struct bt_mesh_msg_ctx *ctx);
/** @brief Get the current procedure timeout value.
*
* @return The configured procedure timeout.
*/
int32_t bt_mesh_dfu_cli_timeout_get(void);
/** @brief Set the procedure timeout value.
*
* @param timeout The new procedure timeout.
*/
void bt_mesh_dfu_cli_timeout_set(int32_t timeout);
/** @cond INTERNAL_HIDDEN */
extern const struct bt_mesh_blob_cli_cb _bt_mesh_dfu_cli_blob_handlers;
extern const struct bt_mesh_model_cb _bt_mesh_dfu_cli_cb;
extern const struct bt_mesh_model_op _bt_mesh_dfu_cli_op[];
/** @endcond */
#ifdef __cplusplus
}
#endif
#endif /* _BLE_MESH_v11_DFU_CLI_H__ */

View File

@@ -0,0 +1,113 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @defgroup bt_mesh_dfu_metadata Bluetooth Mesh Device Firmware Update (DFU) metadata
* @ingroup bt_mesh_dfu
* @{
* @brief Common types and functions for the Bluetooth Mesh DFU metadata.
*/
#ifndef _BLE_MESH_v11_DFU_METADATA_H__
#define _BLE_MESH_v11_DFU_METADATA_H__
#include <stdint.h>
#include <sys/types.h>
#include "mesh/types.h"
#include "mesh/utils.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Firmware version. */
struct bt_mesh_dfu_metadata_fw_ver {
/** Firmware major version. */
uint8_t major;
/** Firmware minor version. */
uint8_t minor;
/** Firmware revision. */
uint16_t revision;
/** Firmware build number. */
uint32_t build_num;
};
/** Firmware core type. */
enum bt_mesh_dfu_metadata_fw_core_type {
/** Application core. */
BLE_MESH_DFU_FW_CORE_TYPE_APP = BIT(0),
/** Application-specific BLOB. */
BLE_MESH_DFU_FW_CORE_TYPE_APP_SPECIFIC_BLOB = BIT(2),
};
/** Firmware metadata. */
struct bt_mesh_dfu_metadata {
/** New firmware version. */
struct bt_mesh_dfu_metadata_fw_ver fw_ver;
/** New firmware size. */
uint32_t fw_size;
/** New firmware core type. */
enum bt_mesh_dfu_metadata_fw_core_type fw_core_type;
/** Hash of incoming Composition Data. */
uint32_t comp_hash;
/** New number of node elements. */
uint16_t elems;
/** Application-specific data for new firmware. This field is optional. */
uint8_t *user_data;
/** Length of the application-specific field. */
uint32_t user_data_len;
};
/** @brief Decode a firmware metadata from a network buffer.
*
* @param buf Buffer containing a raw metadata to be decoded.
* @param metadata Pointer to a metadata structure to be filled.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_dfu_metadata_decode(struct net_buf_simple *buf,
struct bt_mesh_dfu_metadata *metadata);
/** @brief Encode a firmware metadata into a network buffer.
*
* @param metadata Firmware metadata to be encoded.
* @param buf Buffer to store the encoded metadata.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_dfu_metadata_encode(const struct bt_mesh_dfu_metadata *metadata,
struct net_buf_simple *buf);
/** @brief Compute hash of the Composition Data state.
*
* The format of the Composition Data is defined in MshPRTv1.1: 4.2.2.1.
*
* @param buf Pointer to buffer holding Composition Data.
* @param key 128-bit key to be used in the hash computation.
* @param hash Pointer to a memory location to which the hash will be stored.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_dfu_metadata_comp_hash_get(struct net_buf_simple *buf, uint8_t *key, uint32_t *hash);
/** @brief Compute hash of the Composition Data Page 0 of this device.
*
* @param key 128-bit key to be used in the hash computation.
* @param hash Pointer to a memory location to which the hash will be stored.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_dfu_metadata_comp_hash_local_get(uint8_t *key, uint32_t *hash);
#ifdef __cplusplus
}
#endif
#endif /* _BLE_MESH_v11_DFU_METADATA_H__ */

View File

@@ -0,0 +1,264 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @defgroup bt_mesh_dfu_srv Firmware Update Server model
* @ingroup bt_mesh_dfu
* @{
* @brief API for the Bluetooth Mesh Firmware Update Server model
*/
#ifndef _BLE_MESH_v11_DFU_SRV_H__
#define _BLE_MESH_v11_DFU_SRV_H__
#include "mesh/access.h"
#include "mesh_v1.1/mbt/blob_srv.h"
#ifdef __cplusplus
extern "C" {
#endif
struct bt_mesh_dfu_srv;
/**
*
* @brief Initialization parameters for @ref bt_mesh_dfu_srv.
*
* @param _handlers DFU handler function structure.
* @param _imgs List of @ref bt_mesh_dfu_img managed by this Server.
* @param _img_count Number of DFU images managed by this Server.
*/
#define BLE_MESH_DFU_SRV_INIT(_handlers, _imgs, _img_count) \
{ \
.blob = { .cb = &_bt_mesh_dfu_srv_blob_cb }, .cb = _handlers, \
.imgs = _imgs, .img_count = _img_count, \
}
/**
*
* @brief Firmware Update Server model entry.
*
* @param _srv Pointer to a @ref bt_mesh_dfu_srv instance.
*/
#define BT_MESH_MODEL_DFU_SRV(_srv) \
BT_MESH_MODEL_BLOB_SRV(&(_srv)->blob), \
BLE_MESH_MODEL_CB(BLE_MESH_MODEL_ID_DFU_SRV, _bt_mesh_dfu_srv_op, NULL, \
_srv, &_bt_mesh_dfu_srv_cb)
/** @brief Firmware Update Server event callbacks. */
struct bt_mesh_dfu_srv_cb {
/** @brief Transfer check callback.
*
* The transfer check can be used to validate the incoming transfer
* before it starts. The contents of the metadata is implementation
* specific, and should contain all the information the application
* needs to determine whether this image should be accepted, and what
* the effect of the transfer would be.
*
* If applying the image will have an effect on the provisioning state
* of the mesh stack, this can be communicated through the @c effect
* return parameter.
*
* The metadata check can be performed both as part of starting a new
* transfer and as a separate procedure.
*
* This handler is optional.
*
* @param srv Firmware Update Server instance.
* @param img DFU image the metadata check is performed on.
* @param metadata Image metadata.
* @param effect Return parameter for the image effect on the
* provisioning state of the mesh stack.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int (*check)(struct bt_mesh_dfu_srv *srv,
const struct bt_mesh_dfu_img *img,
struct net_buf_simple *metadata,
enum bt_mesh_dfu_effect *effect);
/** @brief Transfer start callback.
*
* Called when the Firmware Update Server is ready to start a new DFU transfer.
* The application must provide an initialized BLOB stream to be used
* during the DFU transfer.
*
* The following error codes are treated specially, and should be used
* to communicate these issues:
* - @c -ENOMEM: The device cannot fit this image.
* - @c -EBUSY: The application is temporarily unable to accept the
* transfer.
* - @c -EALREADY: The device has already received and verified this
* image, and there's no need to transfer it again. The Firmware Update model
* will skip the transfer phase, and mark the image as verified.
*
* This handler is mandatory.
*
* @param srv Firmware Update Server instance.
* @param img DFU image being updated.
* @param metadata Image metadata.
* @param io BLOB stream return parameter. Must be set to a
* valid BLOB stream by the callback.
*
* @return 0 on success, or (negative) error code otherwise. Return
* codes @c -ENOMEM, @c -EBUSY @c -EALREADY will be passed to
* the updater, other error codes are reported as internal
* errors.
*/
int (*start)(struct bt_mesh_dfu_srv *srv,
const struct bt_mesh_dfu_img *img,
struct net_buf_simple *metadata,
const struct bt_mesh_blob_io **io);
/** @brief Transfer end callback.
*
* This handler is optional.
*
* If the transfer is successful, the application should verify the
* firmware image, and call either @ref bt_mesh_dfu_srv_verified or
* @ref bt_mesh_dfu_srv_rejected depending on the outcome.
*
* If the transfer fails, the Firmware Update Server will be available for new
* transfers immediately after this function returns.
*
* @param srv Firmware Update Server instance.
* @param img DFU image that failed the update.
* @param success Whether the DFU transfer was successful.
*/
void (*end)(struct bt_mesh_dfu_srv *srv,
const struct bt_mesh_dfu_img *img, bool success);
/** @brief Transfer recovery callback.
*
* If the device reboots in the middle of a transfer, the Firmware Update Server
* calls this function when the Bluetooth Mesh subsystem is started.
*
* This callback is optional, but transfers will not be recovered after
* a reboot without it.
*
* @param srv Firmware Update Server instance.
* @param img DFU image being updated.
* @param io BLOB stream return parameter. Must be set to a valid BLOB
* stream by the callback.
*
* @return 0 on success, or (negative) error code to abandon the
* transfer.
*/
int (*recover)(struct bt_mesh_dfu_srv *srv,
const struct bt_mesh_dfu_img *img,
const struct bt_mesh_blob_io **io);
/** @brief Transfer apply callback.
*
* Called after a transfer has been validated, and the updater sends an
* apply message to the Target nodes.
*
* This handler is optional.
*
* @param srv Firmware Update Server instance.
* @param img DFU image that should be applied.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int (*apply)(struct bt_mesh_dfu_srv *srv,
const struct bt_mesh_dfu_img *img);
};
/** @brief Firmware Update Server instance.
*
* Should be initialized with @ref BLE_MESH_DFU_SRV_INIT.
*/
struct bt_mesh_dfu_srv {
/** Underlying BLOB Transfer Server. */
struct bt_mesh_blob_srv blob;
/** Callback structure. */
const struct bt_mesh_dfu_srv_cb *cb;
/** List of updatable images. */
const struct bt_mesh_dfu_img *imgs;
/** Number of updatable images. */
size_t img_count;
/* Runtime state */
const struct bt_mesh_model *mod;
struct {
/* Effect of transfer, @see bt_mesh_dfu_effect. */
uint8_t effect;
/* Current phase, @see bt_mesh_dfu_phase. */
uint8_t phase;
uint8_t ttl;
uint8_t idx;
uint16_t timeout_base;
uint16_t meta;
} update;
};
/** @brief Accept the received DFU transfer.
*
* Should be called at the end of a successful DFU transfer.
*
* If the DFU transfer completes successfully, the application should verify
* the image validity (including any image authentication or integrity checks),
* and call this function if the image is ready to be applied.
*
* @param srv Firmware Update Server instance.
*/
void bt_mesh_dfu_srv_verified(struct bt_mesh_dfu_srv *srv);
/** @brief Reject the received DFU transfer.
*
* Should be called at the end of a successful DFU transfer.
*
* If the DFU transfer completes successfully, the application should verify
* the image validity (including any image authentication or integrity checks),
* and call this function if one of the checks fail.
*
* @param srv Firmware Update Server instance.
*/
void bt_mesh_dfu_srv_rejected(struct bt_mesh_dfu_srv *srv);
/** @brief Cancel the ongoing DFU transfer.
*
* @param srv Firmware Update Server instance.
*/
void bt_mesh_dfu_srv_cancel(struct bt_mesh_dfu_srv *srv);
/** @brief Confirm that the received DFU transfer was applied.
*
* Should be called as a result of the @ref bt_mesh_dfu_srv_cb.apply callback.
*
* @param srv Firmware Update Server instance.
*/
void bt_mesh_dfu_srv_applied(struct bt_mesh_dfu_srv *srv);
/** @brief Check if the Firmware Update Server is busy processing a transfer.
*
* @param srv Firmware Update Server instance.
*
* @return true if a DFU procedure is in progress, false otherwise.
*/
bool bt_mesh_dfu_srv_is_busy(const struct bt_mesh_dfu_srv *srv);
/** @brief Get the progress of the current DFU procedure, in percent.
*
* @param srv Firmware Update Server instance.
*
* @return The current transfer progress in percent.
*/
uint8_t bt_mesh_dfu_srv_progress(const struct bt_mesh_dfu_srv *srv);
/** @cond INTERNAL_HIDDEN */
extern const struct bt_mesh_model_op _bt_mesh_dfu_srv_op[];
extern const struct bt_mesh_model_cb _bt_mesh_dfu_srv_cb;
extern const struct bt_mesh_blob_srv_cb _bt_mesh_dfu_srv_blob_cb;
/** @endcond */
#ifdef __cplusplus
}
#endif
#endif /* _BLE_MESH_v11_DFU_SRV_H__ */

View File

@@ -0,0 +1,272 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _BLE_MESH_v11_BLOB_H__
#define _BLE_MESH_v11_BLOB_H__
#include <sys/types.h>
#include "mesh/types.h"
#include "mesh/utils.h"
#include "mesh.h"
#include "mesh/utils.h"
#include "mesh/access.h"
#include "mesh/atomic.h"
#include "mesh/timer.h"
#include "mesh/compiler.h"
#include "mesh/trace.h"
#include "transport.h"
#include "mesh_v1.1/mbt/blob.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup bt_mesh_blob Bluetooth Mesh BLOB model API
* @ingroup bt_mesh
* @{
*/
#ifndef CONFIG_BLE_MESH_BLOB_CHUNK_COUNT_MAX
#define CONFIG_BLE_MESH_BLOB_CHUNK_COUNT_MAX 0
#endif
/** BLOB transfer mode. */
enum bt_mesh_blob_xfer_mode {
/** No valid transfer mode. */
BT_MESH_BLOB_XFER_MODE_NONE,
/** Push mode (Push BLOB Transfer Mode). */
BT_MESH_BLOB_XFER_MODE_PUSH,
/** Pull mode (Pull BLOB Transfer Mode). */
BT_MESH_BLOB_XFER_MODE_PULL,
/** Both modes are valid. */
BT_MESH_BLOB_XFER_MODE_ALL,
};
/** Transfer phase. */
enum bt_mesh_blob_xfer_phase {
/** The BLOB Transfer Server is awaiting configuration. */
BT_MESH_BLOB_XFER_PHASE_INACTIVE,
/** The BLOB Transfer Server is ready to receive a BLOB transfer. */
BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_START,
/** The BLOB Transfer Server is waiting for the next block of data. */
BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_BLOCK,
/** The BLOB Transfer Server is waiting for the next chunk of data. */
BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_CHUNK,
/** The BLOB was transferred successfully. */
BT_MESH_BLOB_XFER_PHASE_COMPLETE,
/** The BLOB transfer is paused. */
BT_MESH_BLOB_XFER_PHASE_SUSPENDED,
};
/** BLOB model status codes. */
enum bt_mesh_blob_status {
/** The message was processed successfully. */
BT_MESH_BLOB_SUCCESS,
/** The Block Number field value is not within the range of blocks being
* transferred.
*/
BT_MESH_BLOB_ERR_INVALID_BLOCK_NUM,
/** The block size is smaller than the size indicated by the Min Block
* Size Log state or is larger than the size indicated by the Max Block
* Size Log state.
*/
BT_MESH_BLOB_ERR_INVALID_BLOCK_SIZE,
/** The chunk size exceeds the size indicated by the Max Chunk Size
* state, or the number of chunks exceeds the number specified by the
* Max Total Chunks state.
*/
BT_MESH_BLOB_ERR_INVALID_CHUNK_SIZE,
/** The operation cannot be performed while the server is in the current
* phase.
*/
BT_MESH_BLOB_ERR_WRONG_PHASE,
/** A parameter value in the message cannot be accepted. */
BT_MESH_BLOB_ERR_INVALID_PARAM,
/** The message contains a BLOB ID value that is not expected. */
BT_MESH_BLOB_ERR_WRONG_BLOB_ID,
/** There is not enough space available in memory to receive the BLOB.
*/
BT_MESH_BLOB_ERR_BLOB_TOO_LARGE,
/** The transfer mode is not supported by the BLOB Transfer Server
* model.
*/
BT_MESH_BLOB_ERR_UNSUPPORTED_MODE,
/** An internal error occurred on the node. */
BT_MESH_BLOB_ERR_INTERNAL,
/** The requested information cannot be provided while the server is in
* the current phase.
*/
BT_MESH_BLOB_ERR_INFO_UNAVAILABLE,
};
/** BLOB transfer data block. */
struct bt_mesh_blob_block {
/** Block size in bytes */
size_t size;
/** Offset in bytes from the start of the BLOB. */
off_t offset;
/** Block number */
uint16_t number;
/** Number of chunks in block. */
uint16_t chunk_count;
/** Bitmap of missing chunks. */
uint8_t missing[DIV_ROUND_UP(CONFIG_BLE_MESH_BLOB_CHUNK_COUNT_MAX,
8)];
};
/** BLOB data chunk. */
struct bt_mesh_blob_chunk {
/** Offset of the chunk data from the start of the block. */
off_t offset;
/** Chunk data size. */
size_t size;
/** Chunk data. */
uint8_t *data;
};
/** BLOB transfer. */
struct bt_mesh_blob_xfer {
/** BLOB ID. */
uint64_t id;
/** Total BLOB size in bytes. */
size_t size;
/** BLOB transfer mode. */
enum bt_mesh_blob_xfer_mode mode;
/* Logarithmic representation of the block size. */
uint8_t block_size_log;
/** Base chunk size. May be smaller for the last chunk. */
uint16_t chunk_size;
};
/** BLOB stream interaction mode. */
enum bt_mesh_blob_io_mode {
/** Read data from the stream. */
BT_MESH_BLOB_READ,
/** Write data to the stream. */
BT_MESH_BLOB_WRITE,
};
/** BLOB stream. */
struct bt_mesh_blob_io {
/** @brief Open callback.
*
* Called when the reader is opened for reading.
*
* @param io BLOB stream.
* @param xfer BLOB transfer.
* @param mode Direction of the stream (read/write).
*
* @return 0 on success, or (negative) error code otherwise.
*/
int (*open)(const struct bt_mesh_blob_io *io,
const struct bt_mesh_blob_xfer *xfer,
enum bt_mesh_blob_io_mode mode);
/** @brief Close callback.
*
* Called when the reader is closed.
*
* @param io BLOB stream.
* @param xfer BLOB transfer.
*/
void (*close)(const struct bt_mesh_blob_io *io,
const struct bt_mesh_blob_xfer *xfer);
/** @brief Block start callback.
*
* Called when a new block is opened for sending. Each block is only
* sent once, and are always sent in increasing order. The data chunks
* inside a single block may be requested out of order and multiple
* times.
*
* @param io BLOB stream.
* @param xfer BLOB transfer.
* @param block Block that was started.
*/
int (*block_start)(const struct bt_mesh_blob_io *io,
const struct bt_mesh_blob_xfer *xfer,
const struct bt_mesh_blob_block *block);
/** @brief Block end callback.
*
* Called when the current block has been transmitted in full.
* No data from this block will be requested again, and the application
* data associated with this block may be discarded.
*
* @param io BLOB stream.
* @param xfer BLOB transfer.
* @param block Block that finished sending.
*/
void (*block_end)(const struct bt_mesh_blob_io *io,
const struct bt_mesh_blob_xfer *xfer,
const struct bt_mesh_blob_block *block);
/** @brief Chunk data write callback.
*
* Used by the BLOB Transfer Server on incoming data.
*
* Each block is divided into chunks of data. This callback is called
* when a new chunk of data is received. Chunks may be received in
* any order within their block.
*
* If the callback returns successfully, this chunk will be marked as
* received, and will not be received again unless the block is
* restarted due to a transfer suspension. If the callback returns a
* non-zero value, the chunk remains unreceived, and the BLOB Transfer
* Client will attempt to resend it later.
*
* Note that the Client will only perform a limited number of attempts
* at delivering a chunk before dropping a Target node from the transfer.
* The number of retries performed by the Client is implementation
* specific.
*
* @param io BLOB stream.
* @param xfer BLOB transfer.
* @param block Block the chunk is part of.
* @param chunk Received chunk.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int (*wr)(const struct bt_mesh_blob_io *io,
const struct bt_mesh_blob_xfer *xfer,
const struct bt_mesh_blob_block *block,
const struct bt_mesh_blob_chunk *chunk);
/** @brief Chunk data read callback.
*
* Used by the BLOB Transfer Client to fetch outgoing data.
*
* The Client calls the chunk data request callback to populate a chunk
* message going out to the Target nodes. The data request callback
* may be called out of order and multiple times for each offset, and
* cannot be used as an indication of progress.
*
* Returning a non-zero status code on the chunk data request callback
* results in termination of the transfer.
*
* @param io BLOB stream.
* @param xfer BLOB transfer.
* @param block Block the chunk is part of.
* @param chunk Chunk to get the data of. The buffer pointer to by the
* @c data member should be filled by the callback.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int (*rd)(const struct bt_mesh_blob_io *io,
const struct bt_mesh_blob_xfer *xfer,
const struct bt_mesh_blob_block *block,
const struct bt_mesh_blob_chunk *chunk);
};
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* _BLE_MESH_v11_BLOB_H__ */

View File

@@ -0,0 +1,467 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _BLE_MESH_v11_BLOB_CLI_H_
#define _BLE_MESH_v11_BLOB_CLI_H_
#include <sys/types.h>
#include "mesh/access.h"
#include "mesh/utils.h"
#include "mesh.h"
#include "mesh/utils.h"
#include "mesh/access.h"
#include "mesh/atomic.h"
#include "mesh/timer.h"
#include "mesh/compiler.h"
#include "mesh/trace.h"
#include "transport.h"
#include "mesh_v1.1/mbt/blob.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup bt_mesh_blob_cli Bluetooth Mesh BLOB Transfer Client model API
* @ingroup bt_mesh
* @{
*/
struct bt_mesh_blob_cli;
/**
*
* @brief BLOB Transfer Client model Composition Data entry.
*
* @param _cli Pointer to a @ref bt_mesh_blob_cli instance.
*/
#define BT_MESH_MODEL_BLOB_CLI(_cli) \
BLE_MESH_MODEL_CB(BLE_MESH_MODEL_ID_BLOB_CLI, _bt_mesh_blob_cli_op, \
NULL, _cli, &_bt_mesh_blob_cli_cb)
/** Target node's Pull mode (Pull BLOB Transfer Mode) context used
* while sending chunks to the Target node.
*/
struct bt_mesh_blob_target_pull {
/** Timestamp when the Block Report Timeout Timer expires for this Target node. */
int64_t block_report_timestamp;
/** Missing chunks reported by this Target node. */
uint8_t missing[DIV_ROUND_UP(CONFIG_BLE_MESH_BLOB_CHUNK_COUNT_MAX, 8)];
};
/** BLOB Transfer Client Target node. */
struct bt_mesh_blob_target {
/** Linked list node */
sys_snode_t n;
/** Target node address. */
uint16_t addr;
/** Target node's Pull mode context.
* Needs to be initialized when sending a BLOB in Pull mode.
*/
struct bt_mesh_blob_target_pull *pull;
/** BLOB transfer status, see @ref bt_mesh_blob_status. */
uint8_t status;
uint8_t procedure_complete: 1, /* Procedure has been completed. */
acked: 1, /* Message has been acknowledged. Not used when sending. */
timedout: 1, /* Target node didn't respond after specified timeout. */
skip: 1; /* Skip Target node from broadcast. */
};
/** BLOB transfer information.
*
* If @c phase is @ref BT_MESH_BLOB_XFER_PHASE_INACTIVE,
* the fields below @c phase are not initialized.
* If @c phase is @ref BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_START,
* the fields below @c id are not initialized.
*/
struct bt_mesh_blob_xfer_info {
/** BLOB transfer status. */
enum bt_mesh_blob_status status;
/** BLOB transfer mode. */
enum bt_mesh_blob_xfer_mode mode;
/** BLOB transfer phase. */
enum bt_mesh_blob_xfer_phase phase;
/** BLOB ID. */
uint64_t id;
/** BLOB size in octets. */
uint32_t size;
/** Logarithmic representation of the block size. */
uint8_t block_size_log;
/** MTU size in octets. */
uint16_t mtu_size;
/** Bit field indicating blocks that were not received. */
const uint8_t *missing_blocks;
};
/** BLOB Transfer Client transfer inputs. */
struct bt_mesh_blob_cli_inputs {
/** Linked list of Target nodes. Each node should point to @ref
* bt_mesh_blob_target::n.
*/
sys_slist_t targets;
/** AppKey index to send with. */
uint16_t app_idx;
/** Group address destination for the BLOB transfer, or @ref
* BLE_MESH_ADDR_UNASSIGNED to send every message to each Target
* node individually.
*/
uint16_t group;
/** Time to live value of BLOB transfer messages. */
uint8_t ttl;
/** Additional response time for the Target nodes, in 10-second increments.
*
* The extra time can be used to give the Target nodes more time to respond
* to messages from the Client. The actual timeout will be calculated
* according to the following formula:
*
* @verbatim
* timeout = 20 seconds + (10 seconds * timeout_base) + (100 ms * TTL)
* @endverbatim
*
* If a Target node fails to respond to a message from the Client within the
* configured transfer timeout, the Target node is dropped.
*/
uint16_t timeout_base;
};
/** Transfer capabilities of a Target node. */
struct bt_mesh_blob_cli_caps {
/** Max BLOB size. */
size_t max_size;
/** Logarithmic representation of the minimum block size. */
uint8_t min_block_size_log;
/** Logarithmic representation of the maximum block size. */
uint8_t max_block_size_log;
/** Max number of chunks per block. */
uint16_t max_chunks;
/** Max chunk size. */
uint16_t max_chunk_size;
/** Max MTU size. */
uint16_t mtu_size;
/** Supported transfer modes. */
enum bt_mesh_blob_xfer_mode modes;
};
/** BLOB Transfer Client state. */
enum bt_mesh_blob_cli_state {
/** No transfer is active. */
BT_MESH_BLOB_CLI_STATE_NONE,
/** Retrieving transfer capabilities. */
BT_MESH_BLOB_CLI_STATE_CAPS_GET,
/** Sending transfer start. */
BT_MESH_BLOB_CLI_STATE_START,
/** Sending block start. */
BT_MESH_BLOB_CLI_STATE_BLOCK_START,
/** Sending block chunks. */
BT_MESH_BLOB_CLI_STATE_BLOCK_SEND,
/** Checking block status. */
BT_MESH_BLOB_CLI_STATE_BLOCK_CHECK,
/** Checking transfer status. */
BT_MESH_BLOB_CLI_STATE_XFER_CHECK,
/** Cancelling transfer. */
BT_MESH_BLOB_CLI_STATE_CANCEL,
/** Transfer is suspended. */
BT_MESH_BLOB_CLI_STATE_SUSPENDED,
/** Checking transfer progress. */
BT_MESH_BLOB_CLI_STATE_XFER_PROGRESS_GET,
};
/** Event handler callbacks for the BLOB Transfer Client model.
*
* All handlers are optional.
*/
struct bt_mesh_blob_cli_cb {
/** @brief Capabilities retrieval completion callback.
*
* Called when the capabilities retrieval procedure completes, indicating that
* a common set of acceptable transfer parameters have been established
* for the given list of Target nodes. All compatible Target nodes have
* status code @ref BT_MESH_BLOB_SUCCESS.
*
* @param cli BLOB Transfer Client instance.
* @param caps Safe transfer capabilities if the transfer capabilities
* of at least one Target node has satisfied the Client, or NULL otherwise.
*/
void (*caps)(struct bt_mesh_blob_cli *cli,
const struct bt_mesh_blob_cli_caps *caps);
/** @brief Target node loss callback.
*
* Called whenever a Target node has been lost due to some error in the
* transfer. Losing a Target node is not considered a fatal error for
* the Client until all Target nodes have been lost.
*
* @param cli BLOB Transfer Client instance.
* @param target Target node that was lost.
* @param reason Reason for the Target node loss.
*/
void (*lost_target)(struct bt_mesh_blob_cli *cli,
struct bt_mesh_blob_target *target,
enum bt_mesh_blob_status reason);
/** @brief Transfer is suspended.
*
* Called when the transfer is suspended due to response timeout from all Target nodes.
*
* @param cli BLOB Transfer Client instance.
*/
void (*suspended)(struct bt_mesh_blob_cli *cli);
/** @brief Transfer end callback.
*
* Called when the transfer ends.
*
* @param cli BLOB Transfer Client instance.
* @param xfer Completed transfer.
* @param success Status of the transfer.
* Is @c true if at least one Target
* node received the whole transfer.
*/
void (*end)(struct bt_mesh_blob_cli *cli,
const struct bt_mesh_blob_xfer *xfer, bool success);
/** @brief Transfer progress callback
*
* The content of @c info is invalidated upon exit from the callback.
* Therefore it needs to be copied if it is planned to be used later.
*
* @param cli BLOB Transfer Client instance.
* @param target Target node that responded to the request.
* @param info BLOB transfer information.
*/
void (*xfer_progress)(struct bt_mesh_blob_cli *cli,
struct bt_mesh_blob_target *target,
const struct bt_mesh_blob_xfer_info *info);
/** @brief End of Get Transfer Progress procedure.
*
* Called when all Target nodes have responded or the procedure timed-out.
*
* @param cli BLOB Transfer Client instance.
*/
void (*xfer_progress_complete)(struct bt_mesh_blob_cli *cli);
};
/** @cond INTERNAL_HIDDEN */
struct blob_cli_broadcast_ctx {
/** Called for every Target node in unicast mode, or once in case of multicast mode. */
void (*send)(struct bt_mesh_blob_cli *cli, uint16_t dst);
/** Called after every @ref blob_cli_broadcast_ctx::send callback. */
void (*send_complete)(struct bt_mesh_blob_cli *cli, uint16_t dst);
/** If @ref blob_cli_broadcast_ctx::acked is true, called after all Target nodes
* have confirmed reception by @ref blob_cli_broadcast_rsp. Otherwise, called
* after transmission has been completed.
*/
void (*next)(struct bt_mesh_blob_cli *cli);
/** If true, every transmission needs to be confirmed by @ref blob_cli_broadcast_rsp before
* @ref blob_cli_broadcast_ctx::next is called.
*/
bool acked;
/** If true, the message is always sent in a unicast way. */
bool force_unicast;
/** If true, non-responsive Target nodes won't be dropped after transfer has timed out. */
bool optional;
/** Set to true by the BLOB Transfer Client between blob_cli_broadcast
* and broadcast_complete calls.
*/
bool is_inited;
/* Defines a time in ms by which the broadcast API postpones sending the message to a next
* target or completing the broadcast.
*/
uint32_t post_send_delay_ms;
};
/** INTERNAL_HIDDEN @endcond */
/** BLOB Transfer Client model instance. */
struct bt_mesh_blob_cli {
/** Event handler callbacks */
const struct bt_mesh_blob_cli_cb *cb;
/* Runtime state */
const struct bt_mesh_model *mod;
struct {
struct bt_mesh_blob_target *target;
struct blob_cli_broadcast_ctx ctx;
struct k_work_delayable retry;
/* Represents Client Timeout timer in a timestamp. Used in Pull mode only. */
int64_t cli_timestamp;
struct k_work_delayable complete;
uint16_t pending;
uint8_t retries;
uint8_t sending : 1,
cancelled : 1;
} tx;
const struct bt_mesh_blob_io *io;
const struct bt_mesh_blob_cli_inputs *inputs;
const struct bt_mesh_blob_xfer *xfer;
uint32_t chunk_interval_ms;
uint16_t block_count;
uint16_t chunk_idx;
uint16_t mtu_size;
enum bt_mesh_blob_cli_state state;
struct bt_mesh_blob_block block;
struct bt_mesh_blob_cli_caps caps;
};
/** @brief Retrieve transfer capabilities for a list of Target nodes.
*
* Queries the availability and capabilities of all Target nodes, producing a
* cumulative set of transfer capabilities for the Target nodes, and returning
* it through the @ref bt_mesh_blob_cli_cb::caps callback.
*
* Retrieving the capabilities may take several seconds, depending on the
* number of Target nodes and mesh network performance. The end of the procedure
* is indicated through the @ref bt_mesh_blob_cli_cb::caps callback.
*
* This procedure is not required, but strongly recommended as a
* preparation for a transfer to maximize performance and the chances of
* success.
*
* @param cli BLOB Transfer Client instance.
* @param inputs Statically allocated BLOB Transfer Client transfer inputs.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_blob_cli_caps_get(struct bt_mesh_blob_cli *cli,
const struct bt_mesh_blob_cli_inputs *inputs);
/** @brief Perform a BLOB transfer.
*
* Starts sending the transfer to the Target nodes. Only Target nodes with a
* @c status of @ref BT_MESH_BLOB_SUCCESS will be considered.
*
* The transfer will keep going either until all Target nodes have been dropped, or
* the full BLOB has been sent.
*
* The BLOB transfer may take several minutes, depending on the number of
* Target nodes, size of the BLOB and mesh network performance. The end of the
* transfer is indicated through the @ref bt_mesh_blob_cli_cb::end callback.
*
* A Client only supports one transfer at the time.
*
* @param cli BLOB Transfer Client instance.
* @param inputs Statically allocated BLOB Transfer Client transfer inputs.
* @param xfer Statically allocated transfer parameters.
* @param io BLOB stream to read the transfer from.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_blob_cli_send(struct bt_mesh_blob_cli *cli,
const struct bt_mesh_blob_cli_inputs *inputs,
const struct bt_mesh_blob_xfer *xfer,
const struct bt_mesh_blob_io *io);
/** @brief Suspend the active transfer.
*
* @param cli BLOB Transfer Client instance.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_blob_cli_suspend(struct bt_mesh_blob_cli *cli);
/** @brief Resume the suspended transfer.
*
* @param cli BLOB Transfer Client instance.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_blob_cli_resume(struct bt_mesh_blob_cli *cli);
/** @brief Cancel an ongoing transfer.
*
* @param cli BLOB Transfer Client instance.
*/
void bt_mesh_blob_cli_cancel(struct bt_mesh_blob_cli *cli);
void bt_mesh_blob_cli_send_cancel(struct bt_mesh_blob_cli *cli,
const struct bt_mesh_blob_xfer *xfer);
/** @brief Get the progress of BLOB transfer.
*
* This function can only be used if the BLOB Transfer Client is currently
* not performing a BLOB transfer.
* To get progress of the active BLOB transfer, use the
* @ref bt_mesh_blob_cli_xfer_progress_active_get function.
*
* @param cli BLOB Transfer Client instance.
* @param inputs Statically allocated BLOB Transfer Client transfer inputs.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_blob_cli_xfer_progress_get(struct bt_mesh_blob_cli *cli,
const struct bt_mesh_blob_cli_inputs *inputs);
/** @brief Get the current progress of the active transfer in percent.
*
* @param cli BLOB Transfer Client instance.
*
* @return The current transfer progress, or 0 if no transfer is active.
*/
uint8_t bt_mesh_blob_cli_xfer_progress_active_get(struct bt_mesh_blob_cli *cli);
/** @brief Get the current state of the BLOB Transfer Client.
*
* @param cli BLOB Transfer Client instance.
*
* @return true if the BLOB Transfer Client is currently participating in a transfer or
* retrieving the capabilities and false otherwise.
*/
bool bt_mesh_blob_cli_is_busy(struct bt_mesh_blob_cli *cli);
/** @brief Set chunk sending interval in ms
*
* This function is optional, and can be used to define how fast chunks are sent in the BLOB Client
* Model.
* Without an added delay, for example a Bluetooth Mesh DFU can cause network blockage by
* constantly sending the next chunks, especially if the chunks are sent to group addresses or
* multiple unicast addresses.
*
* @note: Big intervals may cause timeouts. Increasing the @c timeout_base accordingly can
* circumvent this.
*
* @param cli BLOB Transfer Client instance.
* @param interval_ms the delay before each chunk is sent out in ms.
*/
void bt_mesh_blob_cli_set_chunk_interval_ms(struct bt_mesh_blob_cli *cli, uint32_t interval_ms);
/** @cond INTERNAL_HIDDEN */
extern const struct bt_mesh_model_op _bt_mesh_blob_cli_op[];
extern const struct bt_mesh_model_cb _bt_mesh_blob_cli_cb;
/** @endcond */
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* _BLE_MESH_v11_BLOB_CLI_H_ */

View File

@@ -0,0 +1,229 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _BLE_MESH_v11_BLOB_SRV_H_
#define _BLE_MESH_v11_BLOB_SRV_H_
#include "mesh/access.h"
#include "mesh/utils.h"
#include "mesh_v1.1/mbt/blob.h"
#include "mesh.h"
#include "mesh/utils.h"
#include "mesh/access.h"
#include "mesh/atomic.h"
#include "mesh/timer.h"
#include "mesh/compiler.h"
#include "mesh/trace.h"
#include "transport.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup bt_mesh_blob_srv Bluetooth Mesh BLOB Transfer Server model API
* @ingroup bt_mesh
* @{
*/
struct bt_mesh_blob_srv;
/**
*
* @brief Max number of blocks in a single transfer.
*/
#if defined(CONFIG_BLE_MESH_BLOB_SRV)
#define BT_MESH_BLOB_BLOCKS_MAX \
(DIV_ROUND_UP(CONFIG_BLE_MESH_BLOB_SIZE_MAX, CONFIG_BLE_MESH_BLOB_BLOCK_SIZE_MIN))
#else
#define BT_MESH_BLOB_BLOCKS_MAX 1
#endif
/**
*
* @brief BLOB Transfer Server model composition data entry.
*
* @param _srv Pointer to a @ref bt_mesh_blob_srv instance.
*/
#define BT_MESH_MODEL_BLOB_SRV(_srv) \
BLE_MESH_MODEL_CB(BLE_MESH_MODEL_ID_BLOB_SRV, _bt_mesh_blob_srv_op, \
NULL, _srv, &_bt_mesh_blob_srv_cb)
/** @brief BLOB Transfer Server model event handlers.
*
* All callbacks are optional.
*/
struct bt_mesh_blob_srv_cb {
/** @brief Transfer start callback.
*
* Called when the transfer has started with the prepared BLOB ID.
*
* @param srv BLOB Transfer Server instance.
* @param ctx Message context for the incoming start message. The
* entire transfer will be sent from the same source
* address.
* @param xfer Transfer parameters.
*
* @return 0 on success, or (negative) error code to reject the
* transfer.
*/
int (*start)(struct bt_mesh_blob_srv *srv, struct bt_mesh_msg_ctx *ctx,
struct bt_mesh_blob_xfer *xfer);
/** @brief Transfer end callback.
*
* Called when the transfer ends, either because it was cancelled, or
* because it finished successfully. A new transfer may be prepared.
*
* @note The transfer may end before it's started if the start
* parameters are invalid.
*
* @param srv BLOB Transfer Server instance.
* @param id BLOB ID of the cancelled transfer.
* @param success Whether the transfer was successful.
*/
void (*end)(struct bt_mesh_blob_srv *srv, uint64_t id, bool success);
/** @brief Transfer suspended callback.
*
* Called if the Server timed out while waiting for a transfer packet.
* A suspended transfer may resume later from the start of the current
* block. Any received chunks in the current block should be discarded,
* they will be received again if the transfer resumes.
*
* The transfer will call @c resumed again when resuming.
*
* @note The BLOB Transfer Server does not run a timer in the suspended state,
* and it's up to the application to determine whether the
* transfer should be permanently cancelled. Without interaction,
* the transfer will be suspended indefinitely, and the BLOB Transfer
* Server will not accept any new transfers.
*
* @param srv BLOB Transfer Server instance.
*/
void (*suspended)(struct bt_mesh_blob_srv *srv);
/** @brief Transfer resume callback.
*
* Called if the transfer is resumed after being suspended.
*
* @param srv BLOB Transfer Server instance.
*/
void (*resume)(struct bt_mesh_blob_srv *srv);
/** @brief Transfer recovery callback.
*
* Called when the Bluetooth Mesh subsystem is started if the device is rebooted
* in the middle of a transfer.
*
* Transfers will not be resumed after a reboot if this callback is not
* defined.
*
* @param srv BLOB Transfer Server instance.
* @param xfer Transfer to resume.
* @param io BLOB stream return parameter. Must be set to a valid
* BLOB stream by the callback.
*
* @return 0 on success, or (negative) error code to abandon the
* transfer.
*/
int (*recover)(struct bt_mesh_blob_srv *srv,
struct bt_mesh_blob_xfer *xfer,
const struct bt_mesh_blob_io **io);
};
/** @brief BLOB Transfer Server model instance. */
struct bt_mesh_blob_srv {
/** Event handler callbacks. */
const struct bt_mesh_blob_srv_cb *cb;
/* Runtime state: */
const struct bt_mesh_blob_io *io;
struct k_work_delayable rx_timeout;
struct bt_mesh_blob_block block;
const struct bt_mesh_model *mod;
enum bt_mesh_blob_xfer_phase phase;
struct bt_mesh_blob_srv_state {
struct bt_mesh_blob_xfer xfer;
uint16_t cli;
uint16_t app_idx;
uint16_t timeout_base;
uint16_t mtu_size;
uint8_t ttl;
/* Bitfield of pending blocks. */
BLE_MESH_ATOMIC_DEFINE(blocks, BT_MESH_BLOB_BLOCKS_MAX);
} state;
/* Pull mode (Pull BLOB Transfer Mode) behavior. */
struct {
uint16_t chunk_idx;
struct k_work_delayable report;
} pull;
};
/** @brief Prepare BLOB Transfer Server for an incoming transfer.
*
* Before a BLOB Transfer Server can receive a transfer, the transfer must be prepared
* through some application level mechanism. The BLOB Transfer Server will only accept
* incoming transfers with a matching BLOB ID.
*
* @param srv BLOB Transfer Server instance.
* @param id BLOB ID to accept.
* @param io BLOB stream to write the incoming BLOB to.
* @param ttl Time to live value to use in responses to the BLOB Transfer Client.
* @param timeout_base Extra time for the Client to respond in addition to the
* base 10 seconds, in 10-second increments.
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_blob_srv_recv(struct bt_mesh_blob_srv *srv, uint64_t id,
const struct bt_mesh_blob_io *io, uint8_t ttl,
uint16_t timeout_base);
/** @brief Cancel the current BLOB transfer.
*
* Tells the BLOB Transfer Client to drop this device from the list of Targets for the
* current transfer. Note that the client may continue sending the transfer to
* other Targets.
*
* @param srv BLOB Transfer Server instance.
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_blob_srv_cancel(struct bt_mesh_blob_srv *srv);
/** @brief Get the current state of the BLOB Transfer Server.
*
* @param srv BLOB Transfer Server instance.
*
* @return true if the BLOB Transfer Server is currently participating in a transfer,
* false otherwise.
*/
bool bt_mesh_blob_srv_is_busy(const struct bt_mesh_blob_srv *srv);
/** @brief Get the current progress of the active transfer in percent.
*
* @param srv BLOB Transfer Server instance.
*
* @return The current transfer progress, or 0 if no transfer is active.
*/
uint8_t bt_mesh_blob_srv_progress(const struct bt_mesh_blob_srv *srv);
/** @cond INTERNAL_HIDDEN */
extern const struct bt_mesh_model_op _bt_mesh_blob_srv_op[];
extern const struct bt_mesh_model_cb _bt_mesh_blob_srv_cb;
/** @endcond */
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* _BLE_MESH_v11_BLOB_SRV_H_ */

View File

@@ -0,0 +1,164 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#if CONFIG_BLE_MESH_BLOB_CLI || CONFIG_BLE_MESH_BLOB_SRV
#include "mesh/utils.h"
#include "mesh_v1.1/mbt/blob.h"
#include "mesh_v1.1/mbt/blob_cli.h"
#include "mesh_v1.1/mbt/blob_srv.h"
#define BT_MESH_BLOB_OP_XFER_GET BLE_MESH_MODEL_OP_2(0x83, 0x00)
#define BT_MESH_BLOB_OP_XFER_START BLE_MESH_MODEL_OP_2(0x83, 0x01)
#define BT_MESH_BLOB_OP_XFER_CANCEL BLE_MESH_MODEL_OP_2(0x83, 0x02)
#define BT_MESH_BLOB_OP_XFER_STATUS BLE_MESH_MODEL_OP_2(0x83, 0x03)
#define BT_MESH_BLOB_OP_BLOCK_GET BLE_MESH_MODEL_OP_2(0x83, 0x05)
#define BT_MESH_BLOB_OP_BLOCK_START BLE_MESH_MODEL_OP_2(0x83, 0x04)
#define BT_MESH_BLOB_OP_CHUNK BLE_MESH_MODEL_OP_1(0x66)
#define BT_MESH_BLOB_OP_BLOCK_STATUS BLE_MESH_MODEL_OP_1(0x67)
#define BT_MESH_BLOB_OP_BLOCK_REPORT BLE_MESH_MODEL_OP_1(0x68)
#define BT_MESH_BLOB_OP_INFO_GET BLE_MESH_MODEL_OP_2(0x83, 0x06)
#define BT_MESH_BLOB_OP_INFO_STATUS BLE_MESH_MODEL_OP_2(0x83, 0x07)
#define BLOB_BLOCK_NOT_SET 0xffff
#define BLOB_CHUNK_SDU_OVERHEAD \
(BLE_MESH_MODEL_OP_LEN(BT_MESH_BLOB_OP_CHUNK) + 2 + BLE_MESH_MIC_SHORT)
#define BLOB_CHUNK_SIZE_MAX(sdu_max) ((sdu_max) - BLOB_CHUNK_SDU_OVERHEAD)
#define BLOB_CHUNK_SDU_LEN(chunk_size) (BLOB_CHUNK_SDU_OVERHEAD + (chunk_size))
#if CONFIG_BLE_MESH_ALIGN_CHUNK_SIZE_TO_MAX_SEGMENT || \
CONFIG_BLE_MESH_RX_BLOB_CHUNK_SIZE > BLOB_CHUNK_SIZE_MAX(BLE_MESH_RX_SDU_MAX)
#define BLOB_RX_CHUNK_SIZE BLOB_CHUNK_SIZE_MAX(BLE_MESH_RX_SDU_MAX)
#else
#define BLOB_RX_CHUNK_SIZE CONFIG_BLE_MESH_RX_BLOB_CHUNK_SIZE
#endif
#if CONFIG_BLE_MESH_ALIGN_CHUNK_SIZE_TO_MAX_SEGMENT || \
CONFIG_BLE_MESH_TX_BLOB_CHUNK_SIZE > BLOB_CHUNK_SIZE_MAX(BLE_MESH_TX_SDU_MAX)
#define BLOB_TX_CHUNK_SIZE BLOB_CHUNK_SIZE_MAX(BLE_MESH_TX_SDU_MAX)
#else
#define BLOB_TX_CHUNK_SIZE CONFIG_BLE_MESH_TX_BLOB_CHUNK_SIZE
#endif
/* Utility macros for calculating log2 of a number at compile time.
* Used to determine the log2 representation of the block size, which
* is configured as a raw number, but encoded as log2.
*
* The macros expand to a series of ternary expressions, effectively
* searching through power of twos until a match is found.
* According to MshMBTv1.0, the block size cannot be larger than 2^20,
* so we'll stop the search at 20.
*/
#define _BLOB_LOG_2_CEIL(l, x) ((x) <= (1U << l)) ? l :
#define _BLOB_LOG_2_FLOOR(l, x) ((x) < (1U << (l + 1))) ? l :
#define BLOB_BLOCK_SIZE_LOG_CEIL(x) (LISTIFY(20, _BLOB_LOG_2_CEIL, (), x) 20)
#define BLOB_BLOCK_SIZE_LOG_FLOOR(x) (LISTIFY(20, _BLOB_LOG_2_FLOOR, (), x) 20)
/* Log2 representation of the minimum block size */
#define BLOB_BLOCK_SIZE_LOG_MIN BLOB_BLOCK_SIZE_LOG_CEIL(CONFIG_BLE_MESH_BLOB_BLOCK_SIZE_MIN)
/* Log2 representation of the maximum block size */
#define BLOB_BLOCK_SIZE_LOG_MAX BLOB_BLOCK_SIZE_LOG_FLOOR(CONFIG_BLE_MESH_BLOB_BLOCK_SIZE_MAX)
#if defined(CONFIG_BLE_MESH_BLOB_SRV)
#define BLOB_BLOCK_REPORT_STATUS_MSG_MAXLEN ( \
MAX(sizeof(((struct bt_mesh_blob_block *)0)->missing), \
CONFIG_BLE_MESH_BLOB_SRV_PULL_REQ_COUNT * 3))
#define BLOB_BLOCK_STATUS_MSG_MAXLEN (5 + \
MAX(sizeof(((struct bt_mesh_blob_block *)0)->missing), \
CONFIG_BLE_MESH_BLOB_SRV_PULL_REQ_COUNT * 3))
#else
#define BLOB_BLOCK_REPORT_STATUS_MSG_MAXLEN sizeof(((struct bt_mesh_blob_srv *)0)->block.missing)
#define BLOB_BLOCK_STATUS_MSG_MAXLEN (5 + sizeof(((struct bt_mesh_blob_srv *)0)->block.missing))
#endif
#define BLOB_XFER_STATUS_MSG_MAXLEN (17 + sizeof(((struct bt_mesh_blob_srv *)0)->state.blocks))
enum bt_mesh_blob_chunks_missing {
BT_MESH_BLOB_CHUNKS_MISSING_ALL,
BT_MESH_BLOB_CHUNKS_MISSING_NONE,
BT_MESH_BLOB_CHUNKS_MISSING_SOME,
BT_MESH_BLOB_CHUNKS_MISSING_ENCODED,
};
static inline size_t blob_block_size(size_t xfer_size, uint8_t block_size_log,
uint32_t idx)
{
if (((idx + 1U) << block_size_log) <= xfer_size) {
return (1U << block_size_log);
}
return xfer_size & BIT_MASK(block_size_log);
}
static inline void blob_chunk_missing_set(uint8_t *missing_chunks,
int idx, bool missing)
{
WRITE_BIT(missing_chunks[idx / 8], idx % 8, missing);
}
static inline bool
blob_chunk_missing_get(const uint8_t *missing_chunks, int idx)
{
return !!(missing_chunks[idx / 8] & BIT(idx % 8));
}
static inline void blob_chunk_missing_set_all(struct bt_mesh_blob_block *block)
{
size_t bytes = block->chunk_count / 8;
memset(block->missing, 0xff, bytes);
if (block->chunk_count % 8) {
block->missing[bytes] = BIT_MASK(block->chunk_count % 8);
}
}
static inline void blob_chunk_missing_set_none(struct bt_mesh_blob_block *block)
{
memset(block->missing, 0, sizeof(block->missing));
}
#if CONFIG_BLE_MESH_BLOB_CLI
/** @brief Perform a message broadcast to all BLOB Transfer Client Target nodes.
*
* Will send to a group or each Target node individually, repeating until
* all Target nodes have responded or the retry time has run out.
*
* @param cli BLOB Transfer Client instance
* @param ctx Broadcast context
*/
void blob_cli_broadcast(struct bt_mesh_blob_cli *cli,
const struct blob_cli_broadcast_ctx *ctx);
/** @brief Register that a Target node responded to a broadcast.
*
* @param cli BLOB Transfer Client instance
* @param target Target node that responded.
*/
void blob_cli_broadcast_rsp(struct bt_mesh_blob_cli *cli,
struct bt_mesh_blob_target *target);
/** @brief Notify the BLOB Transfer Client that the requested transmission is complete.
*
* Should be called once for each call to the @ref blob_cli_broadcast_ctx.send
* callback.
*
* @param cli BLOB Transfer Client instance.
*/
void blob_cli_broadcast_tx_complete(struct bt_mesh_blob_cli *cli);
/** @brief Aborts any ongoing BLOB Transfer Client operations.
*
* @param cli BLOB Transfer Client instance.
*/
void blob_cli_broadcast_abort(struct bt_mesh_blob_cli *cli);
#endif /* CONFIG_BLE_MESH_BLOB_CLI */
#endif /* CONFIG_BLE_MESH_BLOB_CLI || CONFIG_BLE_MESH_BLOB_SRV */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -46,6 +46,8 @@ INPUT = \
$(PROJECT_PATH)/components/bt/esp_ble_mesh/v1.1/api/core/include/esp_ble_mesh_rpr_model_api.h \
$(PROJECT_PATH)/components/bt/esp_ble_mesh/v1.1/api/core/include/esp_ble_mesh_sar_model_api.h \
$(PROJECT_PATH)/components/bt/esp_ble_mesh/v1.1/api/core/include/esp_ble_mesh_srpl_model_api.h \
$(PROJECT_PATH)/components/bt/esp_ble_mesh/v1.1/api/models/include/esp_ble_mesh_dfu_model_api.h \
$(PROJECT_PATH)/components/bt/esp_ble_mesh/v1.1/api/models/include/esp_ble_mesh_dfu_slot_api.h \
$(PROJECT_PATH)/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h \
$(PROJECT_PATH)/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_config_model_api.h \
$(PROJECT_PATH)/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_generic_model_api.h \

View File

@@ -29,6 +29,7 @@ Mesh Core
* Private Beacon
* Subnet Bridge
* Minor Enhancements
* Device Firmware Update (Preview)
* Multiple Client Models Run Simultaneously
* Support multiple client models send packets to different nodes simultaneously
@@ -132,6 +133,14 @@ Mesh Models
* Light LC Server
* Light LC Setup Server
* Device Firmware Update Client models
* Firmware Update Client model (Preview)
* Firmware Distribution Client model (Preview)
* Device Firmware Update Server models
* Firmware Update Server model (Preview)
* Firmware Distribution Server model (Preview)
Mesh Examples
"""""""""""""

View File

@@ -228,3 +228,12 @@ Composition and Metadata
^^^^^^^^^^^^^^^^^^^^^^^^
.. include-build-file:: inc/esp_ble_mesh_cm_data_api.inc
Device Firmware Update
.. include-build-file:: inc/esp_ble_mesh_dfu_model_api.inc
Device Firmware Slots
.. include-build-file:: inc/esp_ble_mesh_dfu_slot_api.inc

View File

@@ -132,6 +132,14 @@ Mesh 模型
* 灯光 LC 服务器
* 灯光 LC 设置服务器
* 设备固件更新客户端模型
* 固件更新客户端模型(预览)
* 固件分发客户端模型(预览)
* 设备固件更新服务器模型
* 固件更新服务器模型(预览)
* 固件分发服务器模型(预览)
Mesh 示例
"""""""""""