From 6e349344330e9c755115dbd0744af400a56c9d83 Mon Sep 17 00:00:00 2001 From: luoxu Date: Sun, 30 Nov 2025 17:15:01 +0800 Subject: [PATCH] feat(ble_mesh): dfd client/server supported --- components/bt/CMakeLists.txt | 2 + components/bt/common/btc/core/btc_task.c | 3 + .../bt/common/btc/include/btc/btc_task.h | 2 + components/bt/esp_ble_mesh/Kconfig.in | 47 + .../bt/esp_ble_mesh/api/esp_ble_mesh_defs.h | 3 +- .../bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c | 26 + .../btc/include/btc_ble_mesh_model_common.h | 68 +- .../api/models/esp_ble_mesh_dfu_model_api.c | 101 ++ .../include/esp_ble_mesh_dfu_model_api.h | 1055 ++++++++++++++++- .../v1.1/btc/btc_ble_mesh_dfu_model.c | 808 ++++++++++++- .../v1.1/btc/include/btc_ble_mesh_dfu_model.h | 49 + components/bt/esp_ble_mesh/v1.1/dfu/dfd.h | 35 - components/bt/esp_ble_mesh/v1.1/dfu/dfd_cli.c | 699 +++++++++++ components/bt/esp_ble_mesh/v1.1/dfu/dfd_srv.c | 333 +++--- components/bt/esp_ble_mesh/v1.1/dfu/dfu_cli.c | 6 +- .../v1.1/include/mesh_v1.1/dfu/dfd.h | 76 +- .../v1.1/include/mesh_v1.1/dfu/dfd_cli.h | 472 ++++++++ .../v1.1/include/mesh_v1.1/dfu/dfd_srv.h | 51 +- .../esp-ble-mesh/ble-mesh-feature-list.rst | 4 +- .../esp-ble-mesh/ble-mesh-feature-list.rst | 4 +- 20 files changed, 3518 insertions(+), 326 deletions(-) delete mode 100644 components/bt/esp_ble_mesh/v1.1/dfu/dfd.h create mode 100644 components/bt/esp_ble_mesh/v1.1/dfu/dfd_cli.c create mode 100644 components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/dfu/dfd_cli.h diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index e85501734c..57007eb0d2 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -654,6 +654,8 @@ if(CONFIG_BT_ENABLED) "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) diff --git a/components/bt/common/btc/core/btc_task.c b/components/bt/common/btc/core/btc_task.c index 3bc91c9659..9299015591 100644 --- a/components/bt/common/btc/core/btc_task.c +++ b/components/bt/common/btc/core/btc_task.c @@ -266,6 +266,9 @@ static const btc_func_t profile_tab[BTC_PID_NUM] = { #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 */ diff --git a/components/bt/common/btc/include/btc/btc_task.h b/components/bt/common/btc/include/btc/btc_task.h index 98c66652d3..4c254f1cbd 100644 --- a/components/bt/common/btc/include/btc/btc_task.h +++ b/components/bt/common/btc/include/btc/btc_task.h @@ -110,6 +110,8 @@ typedef enum { 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) diff --git a/components/bt/esp_ble_mesh/Kconfig.in b/components/bt/esp_ble_mesh/Kconfig.in index 1f86ae878b..b1157256e0 100644 --- a/components/bt/esp_ble_mesh/Kconfig.in +++ b/components/bt/esp_ble_mesh/Kconfig.in @@ -1870,6 +1870,53 @@ if BLE_MESH 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 diff --git a/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h b/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h index 8b7ff38ed7..01ade02668 100644 --- a/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h +++ b/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h @@ -1988,7 +1988,8 @@ typedef union { #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. diff --git a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c index babbdf5408..49ae1d5dda 100644 --- a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c +++ b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c @@ -1427,6 +1427,14 @@ extern const struct bt_mesh_model_cb _bt_mesh_dfu_srv_cb; 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) { @@ -2274,6 +2282,24 @@ static void btc_ble_mesh_model_op_set(esp_ble_mesh_model_t *model) } 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; } diff --git a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_model_common.h b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_model_common.h index 73b00db41f..66507a1bb2 100644 --- a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_model_common.h +++ b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_model_common.h @@ -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); } } diff --git a/components/bt/esp_ble_mesh/v1.1/api/models/esp_ble_mesh_dfu_model_api.c b/components/bt/esp_ble_mesh/v1.1/api/models/esp_ble_mesh_dfu_model_api.c index feb082cd66..84110f8ade 100644 --- a/components/bt/esp_ble_mesh/v1.1/api/models/esp_ble_mesh_dfu_model_api.c +++ b/components/bt/esp_ble_mesh/v1.1/api/models/esp_ble_mesh_dfu_model_api.c @@ -146,3 +146,104 @@ uint8_t esp_ble_mesh_dfu_srv_progress(const esp_ble_mesh_dfu_srv_t *srv) 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 */ diff --git a/components/bt/esp_ble_mesh/v1.1/api/models/include/esp_ble_mesh_dfu_model_api.h b/components/bt/esp_ble_mesh/v1.1/api/models/include/esp_ble_mesh_dfu_model_api.h index bf91d9e06f..6ef42d3dd8 100644 --- a/components/bt/esp_ble_mesh/v1.1/api/models/include/esp_ble_mesh_dfu_model_api.h +++ b/components/bt/esp_ble_mesh/v1.1/api/models/include/esp_ble_mesh_dfu_model_api.h @@ -34,18 +34,55 @@ extern "C" { #define ESP_BLE_MESH_DFU_OP_UPDATE_APPLY ESP_BLE_MESH_MODEL_OP_2(0x83, 0x0f) #define ESP_BLE_MESH_DFU_OP_UPDATE_STATUS ESP_BLE_MESH_MODEL_OP_2(0x83, 0x10) +/* Distribution Receivers Management Operations (Section 4.3.1) */ +#define ESP_BLE_MESH_DFD_OP_RECEIVERS_ADD ESP_BLE_MESH_MODEL_OP_2(0x83, 0x11) /*!< Add receivers to the distribution list. */ +#define ESP_BLE_MESH_DFD_OP_RECEIVERS_DELETE_ALL ESP_BLE_MESH_MODEL_OP_2(0x83, 0x12) /*!< Delete all receivers from the distribution list. */ +#define ESP_BLE_MESH_DFD_OP_RECEIVERS_STATUS ESP_BLE_MESH_MODEL_OP_2(0x83, 0x13) /*!< Status of receivers add/delete operations. */ +#define ESP_BLE_MESH_DFD_OP_RECEIVERS_GET ESP_BLE_MESH_MODEL_OP_2(0x83, 0x14) /*!< Get the distribution receivers list. */ +#define ESP_BLE_MESH_DFD_OP_RECEIVERS_LIST ESP_BLE_MESH_MODEL_OP_2(0x83, 0x15) /*!< List of distribution receivers. */ + +/* Distribution Capabilities Operations (Section 4.3.2) */ +#define ESP_BLE_MESH_DFD_OP_CAPABILITIES_GET ESP_BLE_MESH_MODEL_OP_2(0x83, 0x16) /*!< Get distribution capabilities of the node. */ +#define ESP_BLE_MESH_DFD_OP_CAPABILITIES_STATUS ESP_BLE_MESH_MODEL_OP_2(0x83, 0x17) /*!< Distribution capabilities status. */ + +/* Firmware Distribution Control Operations (Section 4.3.3) */ +#define ESP_BLE_MESH_DFD_OP_GET ESP_BLE_MESH_MODEL_OP_2(0x83, 0x18) /*!< Get current firmware distribution status. */ +#define ESP_BLE_MESH_DFD_OP_START ESP_BLE_MESH_MODEL_OP_2(0x83, 0x19) /*!< Start firmware distribution to receivers. */ +#define ESP_BLE_MESH_DFD_OP_SUSPEND ESP_BLE_MESH_MODEL_OP_2(0x83, 0x1a) /*!< Suspend ongoing firmware distribution. */ +#define ESP_BLE_MESH_DFD_OP_CANCEL ESP_BLE_MESH_MODEL_OP_2(0x83, 0x1b) /*!< Cancel firmware distribution. */ +#define ESP_BLE_MESH_DFD_OP_APPLY ESP_BLE_MESH_MODEL_OP_2(0x83, 0x1c) /*!< Apply distributed firmware on target nodes. */ +#define ESP_BLE_MESH_DFD_OP_STATUS ESP_BLE_MESH_MODEL_OP_2(0x83, 0x1d) /*!< Firmware distribution status. */ + +/* Firmware Upload Management Operations (Section 4.3.4) */ +#define ESP_BLE_MESH_DFD_OP_UPLOAD_GET ESP_BLE_MESH_MODEL_OP_2(0x83, 0x1e) /*!< Get firmware upload status and progress. */ +#define ESP_BLE_MESH_DFD_OP_UPLOAD_START ESP_BLE_MESH_MODEL_OP_2(0x83, 0x1f) /*!< Start firmware upload (in-band transfer). */ +#define ESP_BLE_MESH_DFD_OP_UPLOAD_START_OOB ESP_BLE_MESH_MODEL_OP_2(0x83, 0x20) /*!< Start firmware upload (out-of-band transfer). */ +#define ESP_BLE_MESH_DFD_OP_UPLOAD_CANCEL ESP_BLE_MESH_MODEL_OP_2(0x83, 0x21) /*!< Cancel firmware upload. */ +#define ESP_BLE_MESH_DFD_OP_UPLOAD_STATUS ESP_BLE_MESH_MODEL_OP_2(0x83, 0x22) /*!< Firmware upload status and progress. */ + +/* Firmware Image Management Operations (Section 4.3.5) */ +#define ESP_BLE_MESH_DFD_OP_FW_GET ESP_BLE_MESH_MODEL_OP_2(0x83, 0x23) /*!< Get firmware image information by FW ID. */ +#define ESP_BLE_MESH_DFD_OP_FW_GET_BY_INDEX ESP_BLE_MESH_MODEL_OP_2(0x83, 0x24) /*!< Get firmware image information by index. */ +#define ESP_BLE_MESH_DFD_OP_FW_DELETE ESP_BLE_MESH_MODEL_OP_2(0x83, 0x25) /*!< Delete specific firmware image. */ +#define ESP_BLE_MESH_DFD_OP_FW_DELETE_ALL ESP_BLE_MESH_MODEL_OP_2(0x83, 0x26) /*!< Delete all firmware images. */ +#define ESP_BLE_MESH_DFD_OP_FW_STATUS ESP_BLE_MESH_MODEL_OP_2(0x83, 0x27) /*!< Firmware image management status. */ + +/* Device Firmware Distribution Constants and Status Codes */ +#define ESP_BLE_MESH_DFD_UPLOAD_PROGRESS_UNSET 101 /*!< Upload progress is not set/available. */ +#define ESP_BLE_MESH_DFD_UPLOAD_TYPE_INBAND 0 /*!< In-band firmware upload type. */ +#define ESP_BLE_MESH_DFD_UPLOAD_TYPE_OOB BIT0 /*!< Out-of-band firmware upload type. */ + #if CONFIG_BLE_MESH_DFU_CLI -/** @def ESP_BLE_MESH_MODEL_DFU_CLI +/** + * @brief Define a new DFU Client model. * - * @brief Define a new DFU Client model. + * @note This API needs to be called for each element on which + * the application needs to have a DFU Client model. * - * @note This API needs to be called for each element on which - * the application needs to have a DFU Client model. + * @param cli_pub Pointer to the unique `esp_ble_mesh_model_pub_t`. + * @param cli_data Pointer to the unique `esp_ble_mesh_client_t`. * - * @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 DFU Client model instance. + * @return New DFU Client model instance. */ #define ESP_BLE_MESH_MODEL_DFU_CLI(cli_pub, cli_data) \ ESP_BLE_MESH_MODEL_BLOB_CLI(NULL, &(cli_data)->blob), \ @@ -53,16 +90,14 @@ extern "C" { NULL, cli_pub, cli_data) -/** @def ESP_BLE_MESH_DFU_CLI_INIT +/** + * @brief Initialize a DFU Client model instance. * - * @brief Initialize a DFU Client model instance. + * @note This macro initializes the DFU Client model and sets callback handlers. * - * @note This macro is used to initialize the DFU Client model. - * It sets the callback handlers for the DFU Client. + * @param _handlers Pointer to the callback handler structure `esp_ble_mesh_dfu_cli_cb_t`. * - * @param _handlers Pointer to the callback handler structure (esp_ble_mesh_dfu_cli_cb_t). - * - * @return An initialized DFU Client model instance. + * @return An initialized DFU Client model instance. */ #define ESP_BLE_MESH_DFU_CLI_INIT(_handlers) \ { \ @@ -71,17 +106,16 @@ extern "C" { #endif /* CONFIG_BLE_MESH_DFU_CLI */ #if CONFIG_BLE_MESH_DFU_SRV -/** @def ESP_BLE_MESH_MODEL_DFU_SRV +/** + * @brief Define a new DFU Server model. * - * @brief Define a new DFU Server model. + * @note This API needs to be called for each element on which + * the application needs to have a DFU Server model. * - * @note This API needs to be called for each element on which - * the application needs to have a DFU Server model. + * @param srv_pub Pointer to the unique `esp_ble_mesh_model_pub_t`. + * @param srv_data Pointer to the unique `esp_ble_mesh_dfu_trans_srv_t`. * - * @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_dfu_trans_srv_t. - * - * @return New DFU Server model instance. + * @return New DFU Server model instance. */ #define ESP_BLE_MESH_MODEL_DFU_SRV(srv_pub, srv_data) \ ESP_BLE_MESH_MODEL_BLOB_SRV(NULL, &(srv_data)->blob), \ @@ -89,18 +123,17 @@ extern "C" { NULL, srv_pub, srv_data) -/** @def ESP_BLE_MESH_DFU_SRV_INIT +/** + * @brief Initialize a DFU Server model instance. * - * @brief Initialize a DFU Server model instance. + * @note This macro initializes the DFU Server model and sets callback handlers + * and image information. * - * @note This macro is used to initialize the DFU Server model. - * It sets the callback handlers and image information for the DFU Server. + * @param _handlers Pointer to the callback handler structure `esp_ble_mesh_dfu_srv_cb_t`. + * @param _imgs Pointer to the array of DFU images `esp_ble_mesh_dfu_img_t`. + * @param _img_count Number of DFU images in the array. * - * @param _handlers Pointer to the callback handler structure (esp_ble_mesh_dfu_srv_cb_t). - * @param _imgs Pointer to the array of DFU images (esp_ble_mesh_dfu_img_t). - * @param _img_count Number of DFU images in the array. - * - * @return An initialized DFU Server model instance. + * @return An initialized DFU Server model instance. */ #define ESP_BLE_MESH_DFU_SRV_INIT(_handlers, _imgs, _img_count) \ { \ @@ -109,6 +142,75 @@ extern "C" { } #endif /* CONFIG_BLE_MESH_DFU_SRV */ +#if CONFIG_BLE_MESH_DFD_CLI +/** + * @def ESP_BLE_MESH_MODEL_DFD_CLI + * + * @brief Define a new Device Firmware Distribution Client model. + * + * Define a DFD Client model for managing firmware distribution operations, + * including receiver lists, upload control, progress monitoring, and + * firmware transfers. + * + * @param cli_pub Pointer to the unique `esp_ble_mesh_model_pub_t` for publish messages. + * @param cli_data Pointer to the unique `esp_ble_mesh_client_t` containing client data. + * + * @return New DFD Client model instance. + */ +#define ESP_BLE_MESH_MODEL_DFD_CLI(cli_pub, cli_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_DFD_CLI, \ + NULL, cli_pub, cli_data) +#endif /* CONFIG_BLE_MESH_DFD_CLI */ + +#if CONFIG_BLE_MESH_DFD_SRV +/** + * @def ESP_BLE_MESH_MODEL_DFD_SRV + * + * @brief Define a new Device Firmware Distribution Server model. + * + * Define a DFD Server model that stores firmware, distributes to targets, + * handles uploads, manages receiver lists, and controls distribution phases. + * Contains internal DFU Client for updates and BLOB Server for transfers. + * + * @param srv_pub Pointer to the unique `esp_ble_mesh_model_pub_t` for publish messages. + * @param srv_data Pointer to the unique `esp_ble_dfd_trans_srv_t` containing server data. + * + * @return New DFD Server model instance. + */ +#define ESP_BLE_MESH_MODEL_DFD_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_MODEL_DFU_CLI(NULL, &(srv_data)->dfu), \ + ESP_BLE_MESH_MODEL_BLOB_SRV(NULL, &((srv_data)->upload.blob)),\ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_DFD_SRV, \ + NULL, srv_pub, srv_data) + +/* Internal callback structures for DFD Server implementation */ +extern const struct bt_mesh_dfu_cli_cb _bt_mesh_dfd_srv_dfu_cb; /*!< Internal DFU Client callbacks for DFD Server. */ +extern const struct bt_mesh_blob_srv_cb _bt_mesh_dfd_srv_blob_cb; /*!< Internal BLOB Server callbacks for DFD Server. */ + +/** + * @def ESP_BLE_MESH_DFD_SRV_INIT + * + * @brief Initialize a Device Firmware Distribution Server. + * + * Initialize a DFD Server instance with the provided callback structure + * and set up the internal DFU Client and BLOB Server components. + * + * @param _cb Pointer to a `bt_mesh_dfd_srv_cb` instance containing the server callbacks. + * + * @return Initialized DFD Server structure with internal components configured. + */ +#define ESP_BLE_MESH_DFD_SRV_INIT(_cb) \ + { \ + .cb = _cb, \ + .dfu = ESP_BLE_MESH_DFU_CLI_INIT((struct esp_ble_mesh_dfu_cli_cb *) \ + &_bt_mesh_dfd_srv_dfu_cb), \ + .upload = { \ + .blob = { .cb = (esp_ble_mesh_blob_srv_cb_t *) \ + &_bt_mesh_dfd_srv_blob_cb }, \ + }, \ + } +#endif /* CONFIG_BLE_MESH_DFD_SRV */ + /** @brief DFU image structure. **/ typedef struct esp_ble_mesh_dfu_img esp_ble_mesh_dfu_img_t; @@ -298,6 +400,95 @@ typedef struct esp_ble_mesh_dfu_srv esp_ble_mesh_dfu_srv_t; typedef struct esp_ble_mesh_dfu_srv_cb esp_ble_mesh_dfu_srv_cb_t; #endif /* CONFIG_BLE_MESH_DFU_SRV */ +#if CONFIG_BLE_MESH_DFD_CLI +/* DFD Client Forward Declarations */ +typedef enum esp_ble_mesh_dfd_client_act esp_ble_mesh_dfd_client_act_t; /*!< DFD Client action enumeration. */ +typedef enum esp_ble_mesh_dfd_client_cb_evt esp_ble_mesh_dfd_client_cb_evt_t; /*!< DFD Client callback event enumeration. */ +typedef struct esp_ble_mesh_dfd_cli_receiver_entry esp_ble_mesh_dfd_cli_receiver_entry_t; /*!< DFD Client receiver entry structure. */ + +/* DFD Client Receiver Management Structures */ +typedef struct esp_ble_mesh_dfd_cli_receivers_add esp_ble_mesh_dfd_cli_receivers_add_t; /*!< Parameters for adding receivers to distribution list. */ +typedef struct esp_ble_mesh_dfd_receiver_status esp_ble_mesh_dfd_receiver_status_t; /*!< Status response for receiver operations. */ + +typedef struct esp_ble_mesh_dfd_receivers_get esp_ble_mesh_dfd_receivers_get_t; /*!< Parameters for getting distribution receivers list. */ +typedef struct esp_ble_mesh_dfd_target_node_entry esp_ble_mesh_dfd_target_node_entry_t; /*!< Target node entry information. */ +typedef struct esp_ble_mesh_dfd_receiver_list esp_ble_mesh_dfd_receiver_list_t; /*!< Distribution receivers list response. */ + +/* DFD Client Distribution Control Structures */ +typedef struct esp_ble_mesh_dfd_dist_caps esp_ble_mesh_dfd_dist_caps_t; /*!< Distribution capabilities of the DFD Server. */ + +typedef struct esp_ble_mesh_dfd_cli_dist_start esp_ble_mesh_dfd_cli_dist_start_t; /*!< Parameters for starting firmware distribution. */ +typedef struct esp_ble_mesh_dfd_dist_status esp_ble_mesh_dfd_dist_status_t; /*!< Firmware distribution status response. */ + +/* DFD Client Upload Management Structures */ +typedef struct esp_ble_mesh_dfd_cli_dist_upload_start esp_ble_mesh_dfd_cli_dist_upload_start_t; /*!< Parameters for starting in-band firmware upload. */ +typedef struct esp_ble_mesh_dfd_cli_dist_upload_oob_start esp_ble_mesh_dfd_cli_dist_upload_oob_start_t; /*!< Parameters for starting out-of-band firmware upload. */ +typedef struct esp_ble_mesh_dfd_upload_status esp_ble_mesh_dfd_upload_status_t; /*!< Firmware upload status and progress. */ + +/* DFD Client Firmware Management Structures */ +typedef struct esp_ble_mesh_dfd_cli_dist_fw_get esp_ble_mesh_dfd_cli_dist_fw_get_t; /*!< Parameters for getting firmware by FW ID. */ +typedef struct esp_ble_mesh_dfd_cli_dist_fw_get_by_idx esp_ble_mesh_dfd_cli_dist_fw_get_by_idx_t; /*!< Parameters for getting firmware by index. */ +typedef struct esp_ble_mesh_dfd_cli_dist_fw_del esp_ble_mesh_dfd_cli_dist_fw_del_t; /*!< Parameters for deleting firmware. */ +typedef struct esp_ble_mesh_dfd_firmware_status esp_ble_mesh_dfd_firmware_status_t; /*!< Firmware management status response. */ + +/* DFD Client Callback Structures */ +typedef struct esp_ble_mesh_dfd_client_cb_param esp_ble_mesh_dfd_client_cb_param_t; /*!< DFD Client callback parameters. */ +typedef union esp_ble_mesh_dfd_client_common_cb_param esp_ble_mesh_dfd_client_common_cb_param_t; /*!< Common callback parameter union. */ + +/* DFD Client Callback Function Type */ +typedef void (*esp_ble_mesh_dfd_client_cb_t)(esp_ble_mesh_dfd_client_cb_evt_t event, /*!< DFD Client callback function type. */ + esp_ble_mesh_dfd_client_cb_param_t *param); +#endif /* CONFIG_BLE_MESH_DFD_CLI */ + +#if CONFIG_BLE_MESH_DFD_SRV +/** + * @brief Firmware Distribution status enumeration. + * + * This enumeration defines the status codes used in DFD operations + * according to the Bluetooth Mesh Model Specification v1.0. These + * status codes indicate success, failure, and error conditions + * for various firmware distribution operations. + */ +typedef enum esp_ble_mesh_dfd_status esp_ble_mesh_dfd_status_t; + +/** + * @brief Firmware distribution phases enumeration. + * + * This enumeration defines the different phases of a firmware distribution + * operation as specified in the Bluetooth Mesh Model Specification v1.0. + * The phases track the state of firmware distribution from idle through + * transfer, verification, application, and completion states. + */ +typedef enum esp_ble_mesh_dfd_phase esp_ble_mesh_dfd_phase_t; + +/** + * @brief Firmware upload phases enumeration. + * + * This enumeration defines the phases of firmware upload operations + * on the DFD Server. It tracks the state of firmware storage procedures + * including in-band and out-of-band upload methods. + */ +typedef enum esp_ble_mesh_dfd_upload_phase esp_ble_mesh_dfd_upload_phase_t; + +/** + * @brief Firmware Distribution Server callback structure. + * + * This structure contains callback function pointers that allow the + * application to handle various DFD Server events including firmware + * reception, distribution control, and phase changes. + */ +typedef struct esp_ble_mesh_dfd_srv_cb esp_ble_mesh_dfd_srv_cb_t; + +/** + * @brief Firmware Distribution Server instance structure. + * + * This structure represents a DFD Server model instance that manages + * firmware distribution operations. It contains state information for + * ongoing distributions, firmware storage, and target node management. + */ +typedef struct esp_ble_mesh_dfd_srv esp_ble_mesh_dfd_srv_t; +#endif /* CONFIG_BLE_MESH_DFD_SRV */ + /** DFU transfer phase. */ typedef enum esp_ble_mesh_dfu_phase { /** Ready to start a Receive Firmware procedure. */ @@ -613,7 +804,7 @@ struct esp_ble_mesh_dfu_cli_xfer { struct esp_ble_mesh_device_firmware_update_info_get { uint8_t first_index; /*!< Index of the first requested entry from the Firmware Information List state */ uint8_t entries_limit; /*!< Maximum number of entries that the server includes in a Firmware Update Information Status message */ - esp_ble_mesh_dfu_img_cb_t img_cb; /*!< Added by Espressif, callback function used to walkthrough recceived images */ + esp_ble_mesh_dfu_img_cb_t img_cb; /*!< Added by Espressif, callback function used to walkthrough received images */ }; /** @@ -992,6 +1183,804 @@ bool esp_ble_mesh_dfu_srv_is_busy(const esp_ble_mesh_dfu_srv_t *srv); uint8_t esp_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 +/** + * @brief DFD Client receiver entry structure. + * + * This structure represents a single receiver node that will be added + * to the distribution list for firmware updates. Each entry contains + * the target node's address and the specific firmware image index + * that should be distributed to that node. + * + * @note This is used with the DFD Receivers Add message to build + * the distribution receiver list. + */ +struct esp_ble_mesh_dfd_cli_receiver_entry { + /** The unicast address of the target node to receive firmware updates */ + uint16_t addr; + /** Index of the firmware image that should be distributed to this target node */ + uint8_t fw_idx; +}; + +/** + * @brief DFD Client receivers add parameters. + * + * This structure contains the parameters for the DFD Receivers Add + * message. It is used to add multiple target nodes to the distribution + * receiver list. + * + * @note The receivers array should contain valid unicast addresses + * and corresponding firmware image indices. + */ +struct esp_ble_mesh_dfd_cli_receivers_add { + /** Pointer to array of receiver entries to add to the distribution list */ + esp_ble_mesh_dfd_cli_receiver_entry_t *receivers; + /** Number of receiver entries in the receivers array */ + uint16_t receivers_cnt; +}; + +/** + * @brief DFD receiver status response structure. + * + * This structure contains the response parameters for the DFD + * Receivers Add/Delete operations. + * + * The status indicates whether the receiver list modification + * was successful, and the receiver_list_cnt provides the current + * size of the distribution receiver list. + */ +struct esp_ble_mesh_dfd_receiver_status { + /** Status code for the receiver add/delete operation (see esp_ble_mesh_dfd_status) */ + uint8_t status; + /** Current number of entries in the Distribution Receivers List state */ + uint16_t receiver_list_cnt; +}; + +/** + * @brief DFD receivers get parameters. + * + * This structure contains the parameters for the DFD Receivers Get + * message. It is used to retrieve a portion of the distribution + * receiver list. + * + * @note This supports pagination of large receiver lists by allowing + * the client to request specific ranges of entries. + */ +struct esp_ble_mesh_dfd_receivers_get { + /** Index of the first entry in the Distribution Receivers List to return */ + uint16_t first_index; + /** Maximum number of entries to include in the response */ + uint16_t entries_limit; +}; + +/** + * @brief DFD target node entry structure. + * + * This structure represents the status of a single target node + * in the distribution receiver list. It contains detailed information + * about the target's current update phase, transfer status, and progress. + * + * This is returned in the DFD Receivers List message. + */ +struct esp_ble_mesh_dfd_target_node_entry { + /** Unicast address of the target node (15 bits) */ + uint32_t addr:15, + /** Retrieved update phase of the target node (4 bits, see esp_ble_mesh_dfu_phase) */ + retrieved_update_phase:4, + /** Update status of the target node (3 bits, see esp_ble_mesh_dfu_status) */ + update_status:3, + /** Transfer status of the target node (4 bits) */ + transfer_status:4, + /** Transfer progress percentage of the target node (6 bits, in 2 percent increments) */ + transfer_progress:6; + /** Index of the firmware image being updated on the target node */ + uint8_t update_fw_idx; +}; + +/** + * @brief DFD receiver list response structure. + * + * This structure contains the response parameters for the DFD Receivers Get + * message. It provides a list of target nodes in the distribution receiver + * list along with their current status. + */ +struct esp_ble_mesh_dfd_receiver_list { + /** Number of entries included in this response */ + uint16_t entries_cnt; + /** Index of the first entry in the Distribution Receivers List returned */ + uint16_t first_index; + /** Pointer to array of target node entries containing receiver status information */ + esp_ble_mesh_dfd_target_node_entry_t *entries; +}; + +/** + * @brief DFD distribution capabilities structure. + * + * This structure contains the capabilities of a DFD Server as + * returned by the DFD Capabilities Get message. + * + * It provides information about the server's capacity for handling + * firmware distribution operations, storage limits, and supported + * out-of-band retrieval methods. + */ +struct esp_ble_mesh_dfd_dist_caps { + /** Maximum number of receivers that can be stored in the Distribution Receivers List */ + uint16_t max_receiver_list_sz; + /** Maximum number of firmware images that can be stored in the Firmware Information List */ + uint16_t max_fw_list_sz; + /** Maximum size of a single firmware image that can be stored (in bytes) */ + uint32_t max_fw_sz; + /** Maximum upload space available for storing firmware images (in bytes) */ + uint32_t max_upload_space; + /** Remaining upload space available after current stored firmware (in bytes) */ + uint32_t remaining_upload_space; + /** Bit field indicating supported out-of-band retrieval methods (0 = none supported) */ + uint8_t oob_retrieval_supported; + /** Pointer to buffer containing supported URL scheme names (UTF-8, null-terminated) */ + struct net_buf_simple *supported_url_scheme_names; +}; + +/** + * @brief DFD Client distribution start parameters. + * + * This structure contains the parameters for the DFD Start message. + * It initiates the firmware distribution process to all target nodes + * in the Distribution Receivers List. + */ +struct esp_ble_mesh_dfd_cli_dist_start { + /** TTL value to be used for all messages sent during firmware distribution */ + uint8_t ttl; + /** Transfer mode: 0x00 = Push BLOB Transfer Mode, 0x01 = Pull BLOB Transfer Mode (2 bits) */ + uint8_t trans_mode : 2, + /** Update policy: 0x00 = Single Target Node, 0x01 = All Target Nodes (1 bit) */ + update_policy : 1, + /** Reserved for Future Use (5 bits) */ + RFU : 5; + /** Application Key Index to be used for securing firmware distribution messages */ + uint16_t app_idx; + /** Base time value used to calculate transfer timeout (in 100ms units) */ + uint16_t timeout_base; + /** Index of the firmware image in the Firmware Information List to distribute */ + uint16_t fw_idx; + /** Flag indicating whether the target address is a virtual address (true) or group address (false) */ + bool is_va; + /** Target address for firmware distribution (group address or virtual label UUID) */ + union { + /** Group address for firmware distribution (used when is_va is false) */ + uint16_t group_addr; + /** Virtual Label UUID for firmware distribution (used when is_va is true) */ + uint8_t label_uuid[16]; + }; +}; + +/** + * @brief DFD distribution status structure. + * + * This structure contains the response parameters for the DFD Get and + * DFD Start messages. It provides the current status and configuration + * of the firmware distribution operation. + */ +struct esp_ble_mesh_dfd_dist_status { + /** Status code for the distribution operation (see esp_ble_mesh_dfd_status) */ + uint8_t status; + /** Current firmware distribution phase (see esp_ble_mesh_dfd_phase) */ + uint8_t dist_phase; + /** Multicast address used for the firmware distribution (group address or virtual label) */ + uint16_t multicast_address; + /** Application Key Index being used for securing firmware distribution messages */ + uint16_t appkey_idx; + /** TTL value being used for firmware distribution messages */ + uint8_t ttl; + /** Base time value used to calculate transfer timeout (in 100ms units) */ + uint16_t timeout_base; + /** Transfer mode: 0x00 = Push BLOB Transfer Mode, 0x01 = Pull BLOB Transfer Mode (2 bits) */ + uint8_t trans_mode:2, + /** Update policy: 0x00 = Single Target Node, 0x01 = All Target Nodes (1 bit) */ + update_policy:1, + /** Reserved for Future Use (5 bits) */ + RFU:5; + /** Index of the firmware image currently being distributed */ + uint16_t firmware_image_index; +}; + +/** + * @brief DFD Client upload start parameters. + * + * This structure contains the parameters for the DFD Upload Start + * message. It initiates an in-band firmware + * upload to the DFD Server using BLOB Transfer. + * + * @note This is used for in-band firmware transfers where the firmware + * data is transferred through the mesh network. + */ +struct esp_ble_mesh_dfd_cli_dist_upload_start { + /** TTL value to be used for all messages during the upload */ + uint8_t ttl; + /** Base time value used to calculate upload timeout (in 100ms units) */ + uint16_t timeout_base; + /** Total size of the firmware image to be uploaded (in bytes) */ + uint32_t fw_size; + /** BLOB identifier that will be used for the firmware transfer */ + uint64_t blob_id; + /** Pointer to buffer containing the firmware ID of the image to upload */ + struct net_buf_simple *fwid; + /** Pointer to buffer containing the firmware metadata for the upload */ + struct net_buf_simple *fw_metadata; +}; + +/** + * @brief DFD Client out-of-band upload start parameters. + * + * This structure contains the parameters for the DFD Upload Start OOB + * message. It initiates an out-of-band firmware + * upload where the firmware is retrieved from an external source. + * + * @note This is used for out-of-band firmware transfers where the firmware + * is obtained from a URI or external source. + */ +struct esp_ble_mesh_dfd_cli_dist_upload_oob_start { + /** Pointer to buffer containing the current firmware ID to check against */ + struct net_buf_simple *fwid; + /** Pointer to buffer containing the URI for firmware retrieval (UTF-8 string) */ + struct net_buf_simple *url; +}; + +/** + * @brief DFD upload status structure. + * + * This structure contains the response parameters for the DFD Upload Get, + * DFD Upload Start, and DFD Upload Start OOB messages. + * + * It provides the current status and progress of an ongoing or completed + * firmware upload operation on the DFD Server. + */ +struct esp_ble_mesh_dfd_upload_status { + /** Status code for the upload operation (see esp_ble_mesh_dfd_status) */ + uint8_t status; + /** Current upload phase (see esp_ble_mesh_dfd_upload_phase) */ + uint8_t upload_phase; + /** Upload progress percentage (0-100%, only valid when progress != 101) */ + uint8_t upload_progress:7, + /** Upload type: 0x00 = In-band upload, 0x01 = Out-of-band upload */ + upload_type:1; + /** Union containing firmware ID information based on upload type */ + union { + /** Firmware ID for in-band upload operations */ + struct net_buf_simple *fwid; + /** Firmware ID for out-of-band upload operations */ + struct net_buf_simple *oob_fwid; + }; +}; + +/** + * @brief DFD Client firmware get parameters. + * + * This structure contains the parameters for the DFD Firmware Get + * message. It requests information about a specific + * firmware image identified by its firmware ID. + */ +struct esp_ble_mesh_dfd_cli_dist_fw_get { + /** Pointer to buffer containing the firmware ID to query */ + struct net_buf_simple *fwid; +}; + +/** + * @brief DFD Client firmware get by index parameters. + * + * This structure contains the parameters for the DFD Firmware Get By Index + * message. It requests information about a specific firmware image identified + * by its index in the Firmware Information List. + */ +struct esp_ble_mesh_dfd_cli_dist_fw_get_by_idx { + /** Index of the firmware image in the Firmware Information List */ + uint16_t dist_fw_idx; +}; + +/** + * @brief DFD Client firmware delete parameters. + * + * This structure contains the parameters for the DFD Firmware Delete + * message. It requests deletion of a specific firmware image from the + * DFD Server. + * + * @note Deleting a firmware image that is currently being distributed will + * cause the distribution to fail. + */ +struct esp_ble_mesh_dfd_cli_dist_fw_del { + /** Pointer to buffer containing the firmware ID of the image to delete */ + struct net_buf_simple *fwid; +}; + +/** + * @brief DFD firmware status structure. + * + * This structure contains the response parameters for the DFD Firmware Get + * and DFD Firmware Get By Index messages. + * + * It provides detailed information about a specific firmware image stored + * on the DFD Server. + */ +struct esp_ble_mesh_dfd_firmware_status { + /** Status code for the firmware query operation (see esp_ble_mesh_dfd_status) */ + uint8_t status; + /** Total number of entries in the Firmware Information List */ + uint16_t entry_cnt; + /** Index of the firmware image in the Firmware Information List */ + uint16_t fw_idx; + /** Pointer to buffer containing the firmware ID of the queried image */ + struct net_buf_simple *fwid; +}; + +/** + * @brief DFD Client action enumeration. + * + * This enumeration defines the different types of actions that can be performed + * by the DFD Client model. These actions are used internally to + * distinguish between different DFD message types when processing + * client requests. + */ +enum esp_ble_mesh_dfd_client_act { + /** DFD Client Get action - retrieving information from DFD Server */ + ESP_BLE_MESH_ACT_DFD_CLIENT_GET, + /** DFD Client Set action - sending commands/configuration to DFD Server */ + ESP_BLE_MESH_ACT_DFD_CLIENT_SET, + /** Maximum value for DFD Client action enumeration (bounds checking) */ + ESP_BLE_MESH_ACT_DFD_CLIENT_MAX, +}; + +/** + * @brief DFD Client callback event enumeration. + * + * This enumeration defines the different callback events that can be generated + * by the DFD Client model. These events notify the application + * about the status of DFD operations, message responses, timeouts, + * and completion of various procedures. + * + * Application should handle these events to properly manage firmware + * distribution operations and provide user feedback. + */ +enum esp_ble_mesh_dfd_client_cb_evt { + /** DFD Client timeout event - operation timed out waiting for response */ + ESP_BLE_MESH_EVT_DFD_CLIENT_TIMEOUT, + /** DFD Client receive response event - received a response from DFD Server */ + ESP_BLE_MESH_EVT_DFD_CLIENT_RECV_RSP, + /** DFD Client send complete event - message transmission completed */ + ESP_BLE_MESH_ACT_DFD_CLIEND_SEND_COMP, + /** Maximum value for DFD Client callback event enumeration (bounds checking) */ + ESP_BLE_MESH_EVT_DFD_CLIENT_MAX, +}; + +/** + * @brief DFD Client get parameters union. + * + * This union contains different parameter structures for various DFD Client + * Get messages. The specific structure used depends on the type of + * get operation being performed. + * + * This allows type-safe access to message-specific parameters while + * using a single parameter type in the API. + */ +typedef union { + /** Parameters for DFD Receivers Get operation */ + esp_ble_mesh_dfd_receivers_get_t receivers_get; + /** Parameters for DFD Firmware Get operation */ + esp_ble_mesh_dfd_cli_dist_fw_get_t dist_fw_get; + /** Parameters for DFD Firmware Get By Index operation */ + esp_ble_mesh_dfd_cli_dist_fw_get_by_idx_t dist_fw_get_by_idx; +} esp_ble_mesh_dfd_client_get_param_t; + +/** + * @brief DFD Client set parameters union. + * + * This union contains different parameter structures for various DFD Client + * Set messages. The specific structure used depends on the type of + * set operation being performed. + * + * This allows type-safe access to message-specific parameters while + * using a single parameter type in the API. + */ +typedef union { + /** Parameters for DFD Receivers Add operation */ + esp_ble_mesh_dfd_cli_receivers_add_t receivers_add; + /** Parameters for DFD Start operation */ + esp_ble_mesh_dfd_cli_dist_start_t dist_start; + /** Parameters for DFD Upload Start operation */ + esp_ble_mesh_dfd_cli_dist_upload_start_t dist_upload_start; + /** Parameters for DFD Upload Start OOB operation */ + esp_ble_mesh_dfd_cli_dist_upload_oob_start_t dist_upload_oob_start; + /** Parameters for DFD Firmware Get operation */ + esp_ble_mesh_dfd_cli_dist_fw_get_t dist_fw_get; + /** Parameters for DFD Firmware Delete operation */ + esp_ble_mesh_dfd_cli_dist_fw_del_t dist_fw_del; +} esp_ble_mesh_dfd_client_set_param_t; + +/** + * @brief DFD Client common callback parameters union. + * + * This union contains different response structures for various DFD Client + * received messages. The specific structure used depends on the type of + * message that triggered the callback. + * + * This allows type-safe access to message-specific response data + * while using a single callback parameter type. + */ +union esp_ble_mesh_dfd_client_common_cb_param { + /** Response parameters for DFD Receivers Add/Delete operations */ + esp_ble_mesh_dfd_receiver_status_t receiver_status; + /** Response parameters for DFD Receivers Get operation */ + esp_ble_mesh_dfd_receiver_list_t receiver_list; + /** Response parameters for DFD Capabilities Get operation */ + esp_ble_mesh_dfd_dist_caps_t dist_caps; + /** Response parameters for DFD Get/Start operations */ + esp_ble_mesh_dfd_dist_status_t dist_status; + /** Response parameters for DFD Upload Get/Start operations */ + esp_ble_mesh_dfd_upload_status_t upload_status; + /** Response parameters for DFD Firmware Get operations */ + esp_ble_mesh_dfd_firmware_status_t firmware_status; +}; + +/** + * @brief DFD Client callback parameters structure. + * + * This structure contains the parameters passed to the DFD Client + * callback function for various events. It provides information about + * the operation status, error codes, and event-specific data. + * + * Applications should examine the err_code field first to determine + * whether the operation was successful, then check the appropriate + * field in the status_cb union for operation-specific data. + */ +struct esp_ble_mesh_dfd_client_cb_param { + /** Error code indicating success (0) or failure (negative) of the operation */ + int err_code; + /** Common client parameters including source address, destination, etc. */ + esp_ble_mesh_client_common_param_t *params; + /** Union containing event-specific response data */ + esp_ble_mesh_dfd_client_common_cb_param_t status_cb; +}; + +/** + * @brief Register DFD Client callback function. + * + * This function registers a callback function that will be called when + * DFD Client events occur, such as message timeouts, responses, + * or operation completions. + * + * @param callback Pointer to the callback function to register. + * + * @return ESP_OK on success, or error code otherwise. + * + * @note Only one callback can be registered at a time. Calling this + * function with a NULL callback will deregister the current callback. + */ +esp_err_t esp_ble_mesh_register_dfd_cli_callback(esp_ble_mesh_dfd_client_cb_t callback); + +/** + * @brief Send DFD Client Get message. + * + * This function sends a DFD Get message to retrieve information + * from the DFD Server. The specific type of information requested + * depends on the get_param structure provided. + * + * @param params Common client parameters including destination address, TTL, etc. + * @param get_param Union containing the specific get message parameters. + * + * @return ESP_OK on success, or error code otherwise. + * + * @note The response will be delivered through the registered callback + * function with the ESP_BLE_MESH_EVT_DFD_CLIENT_RECV_RSP event. + */ +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); + +/** + * @brief Send DFD Client Set message. + * + * This function sends a DFD Set message to perform various operations + * on the DFD Server, such as starting firmware distribution, + * uploading firmware, or managing the receiver list. + * + * @param params Common client parameters including destination address, TTL, etc. + * @param set_param Union containing the specific set message parameters. + * + * @return ESP_OK on success, or error code otherwise. + * + * @note The response will be delivered through the registered callback + * function with the ESP_BLE_MESH_EVT_DFD_CLIENT_RECV_RSP event. + */ +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); + +#endif /* CONFIG_BLE_MESH_DFD_CLI */ + +#if CONFIG_BLE_MESH_DFD_SRV +/** + * @brief Firmware Distribution status enumeration. + * + * This enumeration defines the status codes used in DFD operations. + * These status codes indicate success, failure, and error conditions + * for various firmware distribution operations. + */ +enum esp_ble_mesh_dfd_status { + /** The message was processed successfully. */ + ESP_BLE_MESH_DFD_SUCCESS, + + /** Insufficient resources on the node. */ + ESP_BLE_MESH_DFD_ERR_INSUFFICIENT_RESOURCES, + + /** The operation cannot be performed while the Server is in the current phase. */ + ESP_BLE_MESH_DFD_ERR_WRONG_PHASE, + + /** An internal error occurred on the node. */ + ESP_BLE_MESH_DFD_ERR_INTERNAL, + + /** The requested firmware image is not stored on the Distributor. */ + ESP_BLE_MESH_DFD_ERR_FW_NOT_FOUND, + + /** The AppKey identified by the AppKey Index is not known to the node. */ + ESP_BLE_MESH_DFD_ERR_INVALID_APPKEY_INDEX, + + /** There are no Target nodes in the Distribution Receivers List state. */ + ESP_BLE_MESH_DFD_ERR_RECEIVERS_LIST_EMPTY, + + /** Another firmware image distribution is in progress. */ + ESP_BLE_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION, + + /** Another upload is in progress. */ + ESP_BLE_MESH_DFD_ERR_BUSY_WITH_UPLOAD, + + /** The URI scheme name indicated by the Update URI is not supported. */ + ESP_BLE_MESH_DFD_ERR_URI_NOT_SUPPORTED, + + /** The format of the Update URI is invalid. */ + ESP_BLE_MESH_DFD_ERR_URI_MALFORMED, + + /** The URI is currently unreachable. */ + ESP_BLE_MESH_DFD_ERR_URI_UNREACHABLE, + + /** The Check Firmware OOB procedure did not find any new firmware. */ + ESP_BLE_MESH_DFD_ERR_NEW_FW_NOT_AVAILABLE, + + /** The suspension of the Distribute Firmware procedure failed. */ + ESP_BLE_MESH_DFD_ERR_SUSPEND_FAILED, +}; + +/** + * @brief Firmware distribution phases enumeration. + * + * This enumeration defines the different phases of a firmware distribution + * operation. The phases track the state of firmware distribution from + * idle through transfer, verification, application, and completion states. + */ +enum esp_ble_mesh_dfd_phase { + /** No firmware distribution is in progress. */ + ESP_BLE_MESH_DFD_PHASE_IDLE, + + /** Firmware distribution is in progress. */ + ESP_BLE_MESH_DFD_PHASE_TRANSFER_ACTIVE, + + /** The Transfer BLOB procedure has completed successfully. */ + ESP_BLE_MESH_DFD_PHASE_TRANSFER_SUCCESS, + + /** The Apply Firmware on Target Nodes procedure is being executed. */ + ESP_BLE_MESH_DFD_PHASE_APPLYING_UPDATE, + + /** The Distribute Firmware procedure has completed successfully. */ + ESP_BLE_MESH_DFD_PHASE_COMPLETED, + + /** The Distribute Firmware procedure has failed. */ + ESP_BLE_MESH_DFD_PHASE_FAILED, + + /** The Cancel Firmware Update procedure is being executed. */ + ESP_BLE_MESH_DFD_PHASE_CANCELING_UPDATE, + + /** The Transfer BLOB procedure is suspended. */ + ESP_BLE_MESH_DFD_PHASE_TRANSFER_SUSPENDED, +}; + +/** + * @brief Firmware upload phases enumeration. + * + * This enumeration defines the phases of firmware upload operations + * on the DFD Server. It tracks the state of firmware storage procedures + * including both in-band and out-of-band upload methods. + */ +enum esp_ble_mesh_dfd_upload_phase { + /** No firmware upload is in progress. */ + ESP_BLE_MESH_DFD_UPLOAD_PHASE_IDLE, + + /** The Store Firmware procedure is being executed. */ + ESP_BLE_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE, + + /** The Store Firmware procedure or Store Firmware OOB procedure failed. */ + ESP_BLE_MESH_DFD_UPLOAD_PHASE_TRANSFER_ERROR, + + /** The Store Firmware procedure or the Store Firmware OOB procedure completed successfully. */ + ESP_BLE_MESH_DFD_UPLOAD_PHASE_TRANSFER_SUCCESS, +}; + +#if 0 +/** + * @brief Flash partition + * + * This structure represents a fixed-size partition on a flash device. + * Each partition contains one or more flash sectors. + */ +struct flash_area { + /** ID number */ + uint8_t fa_id; + uint16_t pad16; + /** Start offset from the beginning of the flash device */ + off_t fa_off; + /** Total size */ + size_t fa_size; + /** Backing flash device */ + const struct device *fa_dev; +#if CONFIG_FLASH_MAP_LABELS + /** Partition label if defined in DTS. Otherwise nullptr; */ + const char *fa_label; +#endif +}; +#endif + +/** Firmware Distribution Server callbacks: */ +struct esp_ble_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)(esp_ble_mesh_dfd_srv_t *srv, + const esp_ble_mesh_dfu_slot_t *slot, + const esp_ble_mesh_blob_io_t **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 + * 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 + * 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 ESP_BLE_MESH_DFD_SUCCESS on success, or error code otherwise. + */ + int (*start_oob_upload)(esp_ble_mesh_dfd_srv_t *srv, + const esp_ble_mesh_dfu_slot_t *slot, + const uint8_t *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)(esp_ble_mesh_dfd_srv_t *srv, + const esp_ble_mesh_dfu_slot_t *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)(esp_ble_mesh_dfd_srv_t *srv, + const esp_ble_mesh_dfu_slot_t *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)(esp_ble_mesh_dfd_srv_t *srv, + const esp_ble_mesh_dfu_slot_t *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)(esp_ble_mesh_dfd_srv_t *srv, + const esp_ble_mesh_dfu_slot_t *slot, + const esp_ble_mesh_blob_io_t **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)(esp_ble_mesh_dfd_srv_t *srv, esp_ble_mesh_dfd_phase_t phase); +}; + +/** Firmware Distribution Server instance. */ +struct esp_ble_mesh_dfd_srv { + const esp_ble_mesh_dfd_srv_cb_t *cb; + esp_ble_mesh_model_t *mod; + esp_ble_mesh_dfu_cli_t dfu; + esp_ble_mesh_dfu_target_t targets[CONFIG_BLE_MESH_DFD_SRV_TARGETS_MAX]; + esp_ble_mesh_blob_target_pull_t pull_ctxs[CONFIG_BLE_MESH_DFD_SRV_TARGETS_MAX]; + const esp_ble_mesh_blob_io_t *io; + uint16_t target_cnt; + uint16_t slot_idx; + bool apply; + esp_ble_mesh_dfd_phase_t phase; + esp_ble_mesh_blob_cli_inputs_t inputs; + + struct { + esp_ble_mesh_dfd_upload_phase_t phase; + esp_ble_mesh_dfu_slot_t *slot; +#if 0 + const struct flash_area *area; +#endif + esp_ble_mesh_blob_srv_t blob; +#ifdef CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD + bool is_oob; + bool is_pending_oob_check; + struct { + uint8_t uri_len; + uint8_t uri[CONFIG_BLE_MESH_DFU_URI_MAXLEN]; + uint16_t current_fwid_len; + uint8_t current_fwid[CONFIG_BLE_MESH_DFU_FWID_MAXLEN]; + esp_ble_mesh_msg_ctx_t 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 */ +}; +#endif /* CONFIG_BLE_MESH_DFD_SRV */ + #ifdef __cplusplus } #endif diff --git a/components/bt/esp_ble_mesh/v1.1/btc/btc_ble_mesh_dfu_model.c b/components/bt/esp_ble_mesh/v1.1/btc/btc_ble_mesh_dfu_model.c index 54fd9c03af..b6fe3ecdbd 100644 --- a/components/bt/esp_ble_mesh/v1.1/btc/btc_ble_mesh_dfu_model.c +++ b/components/bt/esp_ble_mesh/v1.1/btc/btc_ble_mesh_dfu_model.c @@ -12,6 +12,9 @@ #include "esp_ble_mesh_dfu_model_api.h" #include "mesh_v1.1/dfu/dfu_cli.h" #include "mesh_v1.1/dfu/dfu_srv.h" +#include "mesh_v1.1/dfu/dfd.h" +#include "mesh_v1.1/dfu/dfd_cli.h" +#include "mesh_v1.1/dfu/dfd_srv.h" #if CONFIG_BLE_MESH_DFU_CLI /* Device Firmware Update Client model related functions */ @@ -59,15 +62,20 @@ void btc_ble_mesh_dfu_client_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p src->dfu_get.get->dfu_metadata_check.metadata->data, src->dfu_get.get->dfu_metadata_check.metadata->len); } else { + bt_mesh_free(dst->dfu_get.get); + bt_mesh_free(dst->dfu_get.params); BT_ERR("Out of memory for metadata"); return; } } else { + bt_mesh_free(dst->dfu_get.get); + bt_mesh_free(dst->dfu_get.params); BT_ERR("Metadata should be exists"); return; } } } else { + bt_mesh_free(dst->dfu_get.params); BT_ERR("%s, Out of memory, act %d", __func__, msg->act); } } @@ -92,12 +100,21 @@ void btc_ble_mesh_dfu_client_arg_deep_free(btc_msg_t *msg) switch (msg->act) { case BTC_BLE_MESH_ACT_DFU_CLIENT_GET_STATE: + if (arg->dfu_get.get) { + switch (arg->dfu_get.params->opcode) { + case ESP_BLE_MESH_DFU_OP_UPDATE_METADATA_CHECK: + if (arg->dfu_get.get->dfu_metadata_check.metadata) { + bt_mesh_free_buf(arg->dfu_get.get->dfu_metadata_check.metadata); + } + break; + default: + break; + } + bt_mesh_free(arg->dfu_get.get); + } if (arg->dfu_get.params) { bt_mesh_free(arg->dfu_get.params); } - if (arg->dfu_get.get) { - bt_mesh_free(arg->dfu_get.get); - } break; default: break; @@ -134,12 +151,15 @@ static void btc_ble_mesh_dfu_client_copy_req_data(btc_msg_t *msg, void *p_dest, length = p_src_data->recv.dfu_update_info_status.fw_info_list_cnt * sizeof(esp_ble_mesh_firmware_info_t); p_dest_data->recv.dfu_update_info_status.fw_info_list = bt_mesh_calloc(length); if (!p_dest_data->recv.dfu_update_info_status.fw_info_list) { + bt_mesh_free(p_dest_data->params); BT_ERR("%s, Out of memory, act %d", __func__, msg->act); return; } memcpy(p_dest_data->recv.dfu_update_info_status.fw_info_list, p_src_data->recv.dfu_update_info_status.fw_info_list, length); + } else { + p_dest_data->recv.dfu_update_info_status.fw_info_list = NULL; } break; default: @@ -412,3 +432,785 @@ uint8_t btc_ble_mesh_dfu_srv_progress(const esp_ble_mesh_dfu_srv_t *srv) return bt_mesh_dfu_srv_progress((struct bt_mesh_dfu_srv *)srv); } #endif /* CONFIG_BLE_MESH_DFU_SRV */ + +#if CONFIG_BLE_MESH_DFD_CLI +static inline void btc_ble_mesh_dfd_client_cb_to_app(btc_ble_mesh_dfd_client_cb_evt_t event, + esp_ble_mesh_dfd_client_cb_param_t *param) +{ + esp_ble_mesh_dfd_client_cb_t btc_ble_mesh_cb = + (esp_ble_mesh_dfd_client_cb_t)btc_profile_cb_get(BTC_PID_DFD_CLIENT); + if (btc_ble_mesh_cb) { + btc_ble_mesh_cb(event, param); + } +} + +static inline bool dfd_client_param_need(uint32_t opcode) +{ + switch (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: + 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: + break; + } + return false; +} + +static int btc_ble_mesh_dfd_client_get(esp_ble_mesh_client_common_param_t *params, + esp_ble_mesh_dfd_client_get_param_t *get) +{ + bt_mesh_client_common_param_t param = {0}; + + if (params == NULL) { + BT_ERR("%s:InvParam", __func__); + return -EINVAL; + } + + if (dfd_client_param_need(params->opcode) != (!!get)) { + BT_ERR("%s:InvParam", __func__); + return -EINVAL; + } + + switch(params->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: + if (get == NULL) { + BT_ERR("%s:InvParam", __func__); + return -EINVAL; + } + break; + default: + break; + } + + btc_ble_mesh_set_client_common_param(params, ¶m, false); + + switch (params->opcode) { + case ESP_BLE_MESH_DFD_OP_RECEIVERS_GET: + return bt_mesh_dfd_cli_receivers_get(¶m, get->receivers_get.first_index, + get->receivers_get.entries_limit); + case ESP_BLE_MESH_DFD_OP_CAPABILITIES_GET: + return bt_mesh_dfd_cli_distribution_capabilities_get(¶m); + case ESP_BLE_MESH_DFD_OP_GET: + return bt_mesh_dfd_cli_distribution_get(¶m); + case ESP_BLE_MESH_DFD_OP_UPLOAD_GET: + return bt_mesh_dfd_cli_distribution_upload_get(¶m); + case ESP_BLE_MESH_DFD_OP_FW_GET: + return bt_mesh_dfd_cli_firmware_get(¶m, get->dist_fw_get.fwid); + case ESP_BLE_MESH_DFD_OP_FW_GET_BY_INDEX: + return bt_mesh_dfd_cli_firmware_get_by_index(¶m, get->dist_fw_get_by_idx.dist_fw_idx); + default: + BT_ERR("UknOpc:%04x", params->opcode); + return -EINVAL; + } +} + +static int btc_ble_mesh_dfd_client_set(esp_ble_mesh_client_common_param_t *params, + esp_ble_mesh_dfd_client_set_param_t *set) +{ + bt_mesh_client_common_param_t param = {0}; + + if (params == NULL) { + BT_ERR("%s:InvParam", __func__); + return -EINVAL; + } + + if (dfd_client_param_need(params->opcode) != (!!set)) { + BT_ERR("%s:InvParam", __func__); + return -EINVAL; + } + + btc_ble_mesh_set_client_common_param(params, ¶m, false); + + switch (params->opcode) { + case ESP_BLE_MESH_DFD_OP_RECEIVERS_ADD: + return bt_mesh_dfd_cli_receivers_add(¶m, (dfd_cli_receiver_entry_t *)set->receivers_add.receivers, set->receivers_add.receivers_cnt); + case ESP_BLE_MESH_DFD_OP_RECEIVERS_DELETE_ALL: + return bt_mesh_dfd_cli_receivers_delete_all(¶m); + case ESP_BLE_MESH_DFD_OP_START: + return bt_mesh_dfd_cli_distribution_start(¶m, (dfd_cli_dist_start_t *)&set->dist_start); + case ESP_BLE_MESH_DFD_OP_SUSPEND: + return bt_mesh_dfd_cli_distribution_suspend(¶m); + case ESP_BLE_MESH_DFD_OP_CANCEL: + return bt_mesh_dfd_cli_distribution_cancel(¶m); + case ESP_BLE_MESH_DFD_OP_APPLY: + return bt_mesh_dfd_cli_distribution_apply(¶m); + case ESP_BLE_MESH_DFD_OP_UPLOAD_START: + return bt_mesh_dfd_cli_distribution_upload_start(¶m, (dfd_cli_dist_upload_start_t *)&set->dist_upload_start); + case ESP_BLE_MESH_DFD_OP_UPLOAD_START_OOB: + return bt_mesh_dfd_cli_distribution_upload_oob_start(¶m, (dfd_cli_dist_upload_oob_start_t *)&set->dist_upload_oob_start); + case ESP_BLE_MESH_DFD_OP_UPLOAD_CANCEL: + return bt_mesh_dfd_cli_distribution_upload_oob_cancel(¶m); + case ESP_BLE_MESH_DFD_OP_FW_DELETE: + return bt_mesh_dfd_cli_firmware_get_delete(¶m, set->dist_fw_del.fwid); + case ESP_BLE_MESH_DFD_OP_FW_DELETE_ALL: + return bt_mesh_dfd_cli_firmware_delete_all(¶m); + default: + BT_ERR("UknOpc:%04x", params->opcode); + return -EINVAL; + } +} + +void btc_ble_mesh_dfd_client_cb_handler(btc_msg_t *msg) +{ + esp_ble_mesh_dfd_client_cb_param_t *arg = NULL; + + if (!msg) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + arg = (esp_ble_mesh_dfd_client_cb_param_t *)msg->arg; + + if (msg->act < ESP_BLE_MESH_EVT_DFD_CLIENT_MAX) { + btc_ble_mesh_dfd_client_cb_to_app(msg->act, arg); + } else { + BT_ERR("%s, Unknown act %d", __func__, msg->act); + } + + btc_ble_mesh_dfd_client_rsp_deep_free(msg); +} + +void btc_ble_mesh_dfd_client_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) +{ + btc_ble_mesh_dfd_client_args_t *dst = (btc_ble_mesh_dfd_client_args_t *)p_dest; + btc_ble_mesh_dfd_client_args_t *src = (btc_ble_mesh_dfd_client_args_t *)p_src; + + if (!msg || !dst || !src) { + BT_ERR("%s,InvParam", __func__); + return; + } + + switch (msg->act) { + case BTC_BLE_MESH_ACT_DFD_CLIENT_GET: + dst->dfd_client_get.params = + (esp_ble_mesh_client_common_param_t *)bt_mesh_calloc(sizeof(esp_ble_mesh_client_common_param_t)); + if (dst->dfd_client_get.params == NULL) { + BT_ERR("%s:%d,OutMem", __func__, __LINE__); + break; + } + memcpy(dst->dfd_client_get.params, src->dfd_client_get.params, sizeof(esp_ble_mesh_client_common_param_t)); + + if (src->dfd_client_get.get) { + dst->dfd_client_get.get = (esp_ble_mesh_dfd_client_get_param_t *)bt_mesh_calloc(sizeof(esp_ble_mesh_dfd_client_get_param_t)); + if (dst->dfd_client_get.get == NULL) { + bt_mesh_free(dst->dfd_client_get.params); + dst->dfd_client_get.params = NULL; + BT_ERR("%s:%d,OutMem", __func__, __LINE__); + break; + } + memcpy(dst->dfd_client_get.get, src->dfd_client_get.get, sizeof(esp_ble_mesh_dfd_client_get_param_t)); + } + + switch (dst->dfd_client_get.params->opcode) { + case ESP_BLE_MESH_DFD_OP_FW_GET: + if (src->dfd_client_get.get->dist_fw_get.fwid == NULL) { + BT_ERR("%s:%d,InvParam", __func__, __LINE__); + bt_mesh_free(dst->dfd_client_get.params); + dst->dfd_client_get.params = NULL; + bt_mesh_free(dst->dfd_client_get.get); + dst->dfd_client_get.get = NULL; + break; + } + + dst->dfd_client_get.get->dist_fw_get.fwid = + bt_mesh_alloc_buf(src->dfd_client_get.get->dist_fw_get.fwid->len); + if (dst->dfd_client_get.get->dist_fw_get.fwid == NULL) { + bt_mesh_free(dst->dfd_client_get.params); + dst->dfd_client_get.params = NULL; + bt_mesh_free(dst->dfd_client_get.get); + dst->dfd_client_get.get = NULL; + BT_ERR("%s:%d,OutMem", __func__, __LINE__); + break; + } + net_buf_simple_add_mem( + dst->dfd_client_get.get->dist_fw_get.fwid, + src->dfd_client_get.get->dist_fw_get.fwid->data, + src->dfd_client_get.get->dist_fw_get.fwid->len); + break; + default: + break; + } + break; + case BTC_BLE_MESH_ACT_DFD_CLIENT_SET: + dst->dfd_client_set.params = + (esp_ble_mesh_client_common_param_t *)bt_mesh_calloc(sizeof(esp_ble_mesh_client_common_param_t)); + if (dst->dfd_client_set.params == NULL) { + BT_ERR("%s:%d,OutMem", __func__, __LINE__); + break; + } + memcpy(dst->dfd_client_set.params, src->dfd_client_set.params, sizeof(esp_ble_mesh_client_common_param_t)); + + if (src->dfd_client_set.set) { + dst->dfd_client_set.set = (esp_ble_mesh_dfd_client_set_param_t *)bt_mesh_calloc(sizeof(esp_ble_mesh_dfd_client_set_param_t)); + if (dst->dfd_client_set.set == NULL) { + bt_mesh_free(dst->dfd_client_set.params); + dst->dfd_client_set.params = NULL; + BT_ERR("%s:%d,OutMem", __func__, __LINE__); + break; + } + memcpy(dst->dfd_client_set.set, src->dfd_client_set.set, sizeof(esp_ble_mesh_dfd_client_set_param_t)); + } + switch (dst->dfd_client_set.params->opcode) { + case ESP_BLE_MESH_DFD_OP_RECEIVERS_ADD: + if (src->dfd_client_set.set->receivers_add.receivers_cnt == 0) { + dst->dfd_client_set.set->receivers_add.receivers = NULL; + bt_mesh_free(dst->dfd_client_set.params); + dst->dfd_client_set.params = NULL; + bt_mesh_free(dst->dfd_client_set.set); + dst->dfd_client_set.set = NULL; + BT_ERR("%s:%d,InvParam", __func__, __LINE__); + break; + } + dst->dfd_client_set.set->receivers_add.receivers = + (esp_ble_mesh_dfd_cli_receiver_entry_t *)bt_mesh_calloc(dst->dfd_client_set.set->receivers_add.receivers_cnt * + sizeof(esp_ble_mesh_dfd_cli_receiver_entry_t)); + if (dst->dfd_client_set.set->receivers_add.receivers == NULL) { + bt_mesh_free(dst->dfd_client_set.params); + dst->dfd_client_set.params = NULL; + bt_mesh_free(dst->dfd_client_set.set); + dst->dfd_client_set.set = NULL; + BT_ERR("%s:%d,OutMem", __func__, __LINE__); + break; + } + memcpy(dst->dfd_client_set.set->receivers_add.receivers, src->dfd_client_set.set->receivers_add.receivers, + dst->dfd_client_set.set->receivers_add.receivers_cnt * sizeof(esp_ble_mesh_dfd_cli_receiver_entry_t)); + break; + case ESP_BLE_MESH_DFD_OP_UPLOAD_START: + if (src->dfd_client_set.set->dist_upload_start.fwid == NULL) { + dst->dfd_client_set.set->dist_upload_start.fwid = NULL; + bt_mesh_free(dst->dfd_client_set.params); + dst->dfd_client_set.params = NULL; + bt_mesh_free(dst->dfd_client_set.set); + dst->dfd_client_set.set = NULL; + BT_ERR("%s:%d,InvParam", __func__, __LINE__); + break; + } + + dst->dfd_client_set.set->dist_upload_start.fwid = + bt_mesh_alloc_buf(src->dfd_client_set.set->dist_upload_start.fwid->len); + if (dst->dfd_client_set.set->dist_upload_start.fwid == NULL) { + bt_mesh_free(dst->dfd_client_set.params); + dst->dfd_client_set.params = NULL; + bt_mesh_free(dst->dfd_client_set.set); + dst->dfd_client_set.set = NULL; + BT_ERR("%s:%d,OutMem", __func__, __LINE__); + break; + } + net_buf_simple_add_mem( + dst->dfd_client_set.set->dist_upload_start.fwid, + src->dfd_client_set.set->dist_upload_start.fwid->data, + src->dfd_client_set.set->dist_upload_start.fwid->len); + + if (src->dfd_client_set.set->dist_upload_start.fw_metadata->len == 0) { + dst->dfd_client_set.set->dist_upload_start.fw_metadata = NULL; + break; + } else { + dst->dfd_client_set.set->dist_upload_start.fw_metadata = + bt_mesh_alloc_buf(src->dfd_client_set.set->dist_upload_start.fw_metadata->len); + if (dst->dfd_client_set.set->dist_upload_start.fw_metadata == NULL) { + bt_mesh_free(dst->dfd_client_set.params); + dst->dfd_client_set.params = NULL; + bt_mesh_free(dst->dfd_client_set.set); + dst->dfd_client_set.set = NULL; + bt_mesh_free_buf(dst->dfd_client_set.set->dist_upload_start.fwid); + dst->dfd_client_set.set->dist_upload_start.fwid = NULL; + BT_ERR("%s:%d,OutMem", __func__, __LINE__); + break; + } + net_buf_simple_add_mem( + dst->dfd_client_set.set->dist_upload_start.fw_metadata, + src->dfd_client_set.set->dist_upload_start.fw_metadata->data, + src->dfd_client_set.set->dist_upload_start.fw_metadata->len); + } + break; + case ESP_BLE_MESH_DFD_OP_UPLOAD_START_OOB: + if (src->dfd_client_set.set->dist_upload_oob_start.url == NULL || + src->dfd_client_set.set->dist_upload_oob_start.fwid == NULL) { + bt_mesh_free(dst->dfd_client_set.params); + dst->dfd_client_set.params = NULL; + bt_mesh_free(dst->dfd_client_set.set); + dst->dfd_client_set.set = NULL; + BT_ERR("%s:%d,InvParam", __func__, __LINE__); + break; + } + dst->dfd_client_set.set->dist_upload_oob_start.url = + bt_mesh_alloc_buf(src->dfd_client_set.set->dist_upload_oob_start.url->len); + if (dst->dfd_client_set.set->dist_upload_oob_start.url == NULL) { + bt_mesh_free(dst->dfd_client_set.params); + dst->dfd_client_set.params = NULL; + bt_mesh_free(dst->dfd_client_set.set); + dst->dfd_client_set.set = NULL; + BT_ERR("%s:%d,OutMem", __func__, __LINE__); + break; + } + dst->dfd_client_set.set->dist_upload_oob_start.fwid = + bt_mesh_alloc_buf(src->dfd_client_set.set->dist_upload_oob_start.fwid->len); + if (dst->dfd_client_set.set->dist_upload_oob_start.fwid == NULL) { + bt_mesh_free(dst->dfd_client_set.params); + dst->dfd_client_set.params = NULL; + bt_mesh_free(dst->dfd_client_set.set); + dst->dfd_client_set.set = NULL; + bt_mesh_free_buf(dst->dfd_client_set.set->dist_upload_oob_start.url); + dst->dfd_client_set.set->dist_upload_oob_start.url = NULL; + BT_ERR("%s:%d,OutMem", __func__, __LINE__); + break; + } + net_buf_simple_add_mem( + dst->dfd_client_set.set->dist_upload_oob_start.url, + src->dfd_client_set.set->dist_upload_oob_start.url->data, + src->dfd_client_set.set->dist_upload_oob_start.url->len); + net_buf_simple_add_mem( + dst->dfd_client_set.set->dist_upload_oob_start.fwid, + src->dfd_client_set.set->dist_upload_oob_start.fwid->data, + src->dfd_client_set.set->dist_upload_oob_start.fwid->len); + break; + case ESP_BLE_MESH_DFD_OP_FW_DELETE: + if (src->dfd_client_set.set->dist_fw_del.fwid == NULL) { + bt_mesh_free(dst->dfd_client_set.params); + dst->dfd_client_set.params = NULL; + bt_mesh_free(dst->dfd_client_set.set); + dst->dfd_client_set.set = NULL; + BT_ERR("%s:%d,InvParam", __func__, __LINE__); + break; + } + dst->dfd_client_set.set->dist_fw_del.fwid = + bt_mesh_alloc_buf(src->dfd_client_set.set->dist_fw_del.fwid->len); + if (dst->dfd_client_set.set->dist_fw_del.fwid == NULL) { + bt_mesh_free(dst->dfd_client_set.params); + dst->dfd_client_set.params = NULL; + bt_mesh_free(dst->dfd_client_set.set); + dst->dfd_client_set.set = NULL; + BT_ERR("%s:%d,OutMem", __func__, __LINE__); + break; + } + net_buf_simple_add_mem( + dst->dfd_client_set.set->dist_fw_del.fwid, + src->dfd_client_set.set->dist_fw_del.fwid->data, + src->dfd_client_set.set->dist_fw_del.fwid->len); + break; + default: + break; + } + default: + BT_DBG("%s, Unknown act %d", __func__, msg->act); + break; + } +} + +void btc_ble_mesh_dfd_client_arg_deep_free(btc_msg_t *msg) +{ + btc_ble_mesh_dfd_client_args_t *arg = NULL; + + if (!msg) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + if (msg->act >= ESP_BLE_MESH_ACT_DFD_CLIENT_MAX) { + BT_ERR("%s, Invalid event %d", __func__, msg->act); + return; + } + + arg = (btc_ble_mesh_dfd_client_args_t *)msg->arg; + + switch (msg->act) { + case ESP_BLE_MESH_ACT_DFD_CLIENT_GET: + if (arg->dfd_client_get.params == NULL) { + BT_ERR("%s:%d,InvParam", __func__, __LINE__); + break; + } + switch (arg->dfd_client_get.params->opcode) { + case ESP_BLE_MESH_DFD_OP_FW_GET: + if (arg->dfd_client_get.get->dist_fw_get.fwid == NULL) { + BT_ERR("%s:%d,InvParam", __func__, __LINE__); + break; + } + bt_mesh_free_buf(arg->dfd_client_get.get->dist_fw_get.fwid); + break; + default: + break; + } + if (arg->dfd_client_get.get) { + bt_mesh_free(arg->dfd_client_get.get); + } + bt_mesh_free(arg->dfd_client_get.params); + break; + case ESP_BLE_MESH_ACT_DFD_CLIENT_SET: + if (arg->dfd_client_set.params == NULL) { + BT_ERR("%s:%d,InvParam", __func__, __LINE__); + break; + } + switch (arg->dfd_client_set.params->opcode) { + case ESP_BLE_MESH_DFD_OP_RECEIVERS_ADD: + if (arg->dfd_client_set.set->receivers_add.receivers == NULL) { + BT_ERR("%s:%d,InvParam", __func__, __LINE__); + break; + } + bt_mesh_free(arg->dfd_client_set.set->receivers_add.receivers); + break; + case ESP_BLE_MESH_DFD_OP_UPLOAD_START: + if (arg->dfd_client_set.set->dist_upload_start.fwid == NULL) { + BT_ERR("%s:%d,InvParam", __func__, __LINE__); + break; + } + bt_mesh_free_buf(arg->dfd_client_set.set->dist_upload_start.fwid); + if (arg->dfd_client_set.set->dist_upload_start.fw_metadata) { + bt_mesh_free_buf(arg->dfd_client_set.set->dist_upload_start.fw_metadata); + } + break; + case ESP_BLE_MESH_DFD_OP_UPLOAD_START_OOB: + if (arg->dfd_client_set.set->dist_upload_oob_start.url == NULL || + arg->dfd_client_set.set->dist_upload_oob_start.fwid == NULL) { + BT_ERR("%s:%d,InvParam", __func__, __LINE__); + break; + } + bt_mesh_free_buf(arg->dfd_client_set.set->dist_upload_oob_start.url); + bt_mesh_free_buf(arg->dfd_client_set.set->dist_upload_oob_start.fwid); + break; + case ESP_BLE_MESH_DFD_OP_FW_DELETE: + if (arg->dfd_client_set.set->dist_fw_del.fwid == NULL) { + BT_ERR("%s:%d,InvParam", __func__, __LINE__); + break; + } + bt_mesh_free_buf(arg->dfd_client_set.set->dist_fw_del.fwid); + break; + } + if (arg->dfd_client_set.set) { + bt_mesh_free(arg->dfd_client_set.set); + } + bt_mesh_free(arg->dfd_client_set.params); + break; + default: + BT_WARN("Unprocessed event %d", msg->act); + break; + } + + return; +} + +void btc_ble_mesh_dfd_client_rsp_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) +{ + esp_ble_mesh_dfd_client_cb_param_t *dst =(esp_ble_mesh_dfd_client_cb_param_t *) p_dest; + esp_ble_mesh_dfd_client_cb_param_t *src =(esp_ble_mesh_dfd_client_cb_param_t *) p_src; + + if (!msg || !dst || !src) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + dst->err_code = src->err_code; + + if (src->params) { + dst->params = bt_mesh_calloc(sizeof(esp_ble_mesh_client_common_param_t)); + if (dst->params == NULL) { + BT_ERR("%s:%d,OutOfMem", __func__, __LINE__); + return; + } + memcpy(dst->params, src->params, sizeof(esp_ble_mesh_client_common_param_t)); + } + + switch (msg->act) { + case ESP_BLE_MESH_EVT_DFD_CLIENT_RECV_RSP: + switch(dst->params->opcode) { + case BLE_MESH_DFD_OP_RECEIVERS_LIST: + dst->status_cb.receiver_list.first_index = src->status_cb.receiver_list.first_index; + dst->status_cb.receiver_list.entries_cnt = src->status_cb.receiver_list.entries_cnt; + if (dst->status_cb.receiver_list.entries_cnt) { + dst->status_cb.receiver_list.entries = bt_mesh_calloc(sizeof(esp_ble_mesh_dfd_target_node_entry_t) * dst->status_cb.receiver_list.entries_cnt); + if (dst->status_cb.receiver_list.entries == NULL) { + BT_ERR("%s:%d,OutOfMem", __func__, __LINE__); + return; + } + memcpy(dst->status_cb.receiver_list.entries, src->status_cb.receiver_list.entries, + sizeof(esp_ble_mesh_dfd_target_node_entry_t) * dst->status_cb.receiver_list.entries_cnt); + } else { + dst->status_cb.receiver_list.entries = NULL; + } + break; + case BLE_MESH_DFD_OP_CAPABILITIES_STATUS: + dst->status_cb.dist_caps.max_receiver_list_sz = src->status_cb.dist_caps.max_receiver_list_sz; + dst->status_cb.dist_caps.max_fw_list_sz = src->status_cb.dist_caps.max_fw_list_sz; + dst->status_cb.dist_caps.max_fw_sz = src->status_cb.dist_caps.max_fw_sz; + dst->status_cb.dist_caps.max_upload_space = src->status_cb.dist_caps.max_upload_space; + dst->status_cb.dist_caps.remaining_upload_space = src->status_cb.dist_caps.remaining_upload_space; + dst->status_cb.dist_caps.oob_retrieval_supported = src->status_cb.dist_caps.oob_retrieval_supported; + if (src->status_cb.dist_caps.supported_url_scheme_names) { + dst->status_cb.dist_caps.supported_url_scheme_names = + bt_mesh_alloc_buf(src->status_cb.dist_caps.supported_url_scheme_names->len); + if (dst->status_cb.dist_caps.supported_url_scheme_names == NULL) { + BT_ERR("%s:%d,OutOfMem", __func__, __LINE__); + return; + } + net_buf_simple_add_mem( + dst->status_cb.dist_caps.supported_url_scheme_names, + src->status_cb.dist_caps.supported_url_scheme_names->data, + src->status_cb.dist_caps.supported_url_scheme_names->len); + } else { + dst->status_cb.dist_caps.supported_url_scheme_names = NULL; + } + break; + case BLE_MESH_DFD_OP_UPLOAD_STATUS: + dst->status_cb.upload_status.status = src->status_cb.upload_status.status; + dst->status_cb.upload_status.upload_phase = src->status_cb.upload_status.upload_phase; + dst->status_cb.upload_status.upload_progress = src->status_cb.upload_status.upload_progress; + dst->status_cb.upload_status.upload_type = src->status_cb.upload_status.upload_type; + + if (dst->status_cb.upload_status.upload_progress == ESP_BLE_MESH_DFD_UPLOAD_PROGRESS_UNSET) { + dst->status_cb.upload_status.fwid = NULL; + return; + } + + if (dst->status_cb.upload_status.upload_type == ESP_BLE_MESH_DFD_UPLOAD_TYPE_INBAND) { + if (src->status_cb.upload_status.fwid) { + dst->status_cb.upload_status.fwid = bt_mesh_alloc_buf(src->status_cb.upload_status.fwid->len); + if (dst->status_cb.upload_status.fwid == NULL) { + BT_ERR("%s:%d,OutOfMem", __func__, __LINE__); + return; + } + net_buf_simple_add_mem( + dst->status_cb.upload_status.fwid, + src->status_cb.upload_status.fwid->data, + src->status_cb.upload_status.fwid->len); + } else { + BT_ERR("%s:%d,InvParam", __func__, __LINE__); + } + } else { + if(src->status_cb.upload_status.oob_fwid) { + dst->status_cb.upload_status.oob_fwid = bt_mesh_alloc_buf(src->status_cb.upload_status.oob_fwid->len); + if (dst->status_cb.upload_status.oob_fwid == NULL) { + BT_ERR("%s:%d,OutOfMem", __func__, __LINE__); + return; + } + net_buf_simple_add_mem( + dst->status_cb.upload_status.oob_fwid, + src->status_cb.upload_status.oob_fwid->data, + src->status_cb.upload_status.oob_fwid->len); + } else { + BT_ERR("%s:%d,InvParam", __func__, __LINE__); + } + } + break; + case BLE_MESH_DFD_OP_FW_STATUS: + dst->status_cb.firmware_status.status = src->status_cb.firmware_status.status; + dst->status_cb.firmware_status.entry_cnt = src->status_cb.firmware_status.entry_cnt; + dst->status_cb.firmware_status.fw_idx = src->status_cb.firmware_status.fw_idx; + if (src->status_cb.firmware_status.fwid) { + dst->status_cb.firmware_status.fwid = bt_mesh_alloc_buf(src->status_cb.firmware_status.fwid->len); + if (dst->status_cb.firmware_status.fwid == NULL) { + BT_ERR("%s:%d,OutOfMem", __func__, __LINE__); + return; + } + net_buf_simple_add_mem( + dst->status_cb.firmware_status.fwid, + src->status_cb.firmware_status.fwid->data, + src->status_cb.firmware_status.fwid->len); + } else { + dst->status_cb.firmware_status.fwid = NULL; + } + break; + case BLE_MESH_DFD_OP_RECEIVERS_STATUS: + dst->status_cb.receiver_status.status = src->status_cb.receiver_status.status; + dst->status_cb.receiver_status.receiver_list_cnt = src->status_cb.receiver_status.receiver_list_cnt; + break; + case BLE_MESH_DFD_OP_STATUS: + dst->status_cb.dist_status.status = src->status_cb.dist_status.status; + dst->status_cb.dist_status.dist_phase = src->status_cb.dist_status.dist_phase; + dst->status_cb.dist_status.multicast_address = src->status_cb.dist_status.multicast_address; + dst->status_cb.dist_status.appkey_idx = src->status_cb.dist_status.appkey_idx; + dst->status_cb.dist_status.ttl = src->status_cb.dist_status.ttl; + dst->status_cb.dist_status.timeout_base = src->status_cb.dist_status.timeout_base; + dst->status_cb.dist_status.trans_mode = src->status_cb.dist_status.trans_mode; + dst->status_cb.dist_status.update_policy = src->status_cb.dist_status.update_policy; + dst->status_cb.dist_status.firmware_image_index = src->status_cb.dist_status.firmware_image_index; + break; + default: + BT_ERR("Unknown opcode %04x", dst->params->opcode); + break; + + } + break; + case ESP_BLE_MESH_EVT_DFD_CLIENT_TIMEOUT: + break; + case ESP_BLE_MESH_ACT_DFD_CLIEND_SEND_COMP: + break; + default: + BT_ERR("Unknown event %d", msg->act); + } + +} + +void btc_ble_mesh_dfd_client_rsp_deep_free(btc_msg_t *msg) +{ + esp_ble_mesh_dfd_client_cb_param_t *arg = NULL; + + if (!msg) { + BT_ERR("%s:%d,InvParam", __func__, __LINE__); + return; + } + + arg = (esp_ble_mesh_dfd_client_cb_param_t *)(msg->arg); + + if (arg->params == NULL && + msg->act != ESP_BLE_MESH_ACT_DFD_CLIEND_SEND_COMP) { + BT_ERR("%s:%d,InvParam", __func__, __LINE__); + return; + } + + switch (msg->act) { + case ESP_BLE_MESH_EVT_DFD_CLIENT_RECV_RSP: + switch (arg->params->opcode) { + case BLE_MESH_DFD_OP_RECEIVERS_LIST: + if (arg->status_cb.receiver_list.entries) { + bt_mesh_free(arg->status_cb.receiver_list.entries); + arg->status_cb.receiver_list.entries = NULL; + } + break; + case BLE_MESH_DFD_OP_CAPABILITIES_STATUS: + if (arg->status_cb.dist_caps.supported_url_scheme_names) { + bt_mesh_free_buf(arg->status_cb.dist_caps.supported_url_scheme_names); + arg->status_cb.dist_caps.supported_url_scheme_names = NULL; + } + break; + case BLE_MESH_DFD_OP_UPLOAD_STATUS: + /** + * firmware_id and upload_oob_firmware_id are a union + * structure, so only one pointer needs to be released + */ + if (arg->status_cb.upload_status.fwid) { + bt_mesh_free_buf(arg->status_cb.upload_status.fwid); + arg->status_cb.upload_status.fwid = NULL; + } + break; + case BLE_MESH_DFD_OP_FW_STATUS: + if (arg->status_cb.firmware_status.fwid) { + bt_mesh_free_buf(arg->status_cb.firmware_status.fwid); + arg->status_cb.firmware_status.fwid = NULL; + } + break; + } + break; + default: + break; + } + + if (arg->params) { + bt_mesh_free(arg->params); + } +} + +static void btc_ble_mesh_dfd_client_callback(esp_ble_mesh_dfd_client_cb_param_t *cb_params, + uint8_t act) +{ + btc_msg_t msg = {0}; + + /* If corresponding callback is not registered, event will not be posted. */ + if (!btc_profile_cb_get(BTC_PID_DFD_CLIENT)) { + return; + } + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_DFD_CLIENT; + msg.act = act; + + btc_transfer_context(&msg, cb_params, cb_params == NULL ? 0 : sizeof(esp_ble_mesh_dfd_client_cb_param_t), + btc_ble_mesh_dfd_client_rsp_deep_copy, btc_ble_mesh_dfd_client_rsp_deep_free); +} + +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) +{ + esp_ble_mesh_dfd_client_cb_param_t cb_params = {0}; + esp_ble_mesh_client_common_param_t params = {0}; + uint8_t act = 0U; + + if (!model || !ctx || len > sizeof(cb_params.status_cb)) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + switch (event) { + case BTC_BLE_MESH_EVT_DFD_CLIENT_RECV_RSP: + act = ESP_BLE_MESH_EVT_DFD_CLIENT_RECV_RSP; + break; + case BTC_BLE_MESH_EVT_DFD_CLIENT_TIMEOUT: + act = ESP_BLE_MESH_EVT_DFD_CLIENT_TIMEOUT; + break; + default: + BT_ERR("Unknown event %d", event); + break; + } + + params.opcode = ctx->recv_op; + params.model = (esp_ble_mesh_model_t *)model; + btc_ble_mesh_msg_ctx_copy((struct bt_mesh_msg_ctx *)¶ms.ctx, ctx, false); + + cb_params.params = ¶ms; + cb_params.err_code = 0; + + if (val && len) { + memcpy(&cb_params.status_cb, val, len); + } + + btc_ble_mesh_dfd_client_callback(&cb_params, act); + return; +} + +void btc_ble_mesh_dfd_client_call_handler(btc_msg_t *msg) +{ + esp_ble_mesh_dfd_client_cb_param_t cb = {0}; + btc_ble_mesh_dfd_client_args_t *arg = NULL; + + if (!msg) { + BT_ERR("%s,InvParam", __func__); + return; + } + + arg = (btc_ble_mesh_dfd_client_args_t *)msg->arg; + + switch (msg->act) { + case BTC_BLE_MESH_ACT_DFD_CLIENT_GET: + cb.params = arg->dfd_client_get.params; + cb.err_code = btc_ble_mesh_dfd_client_get(arg->dfd_client_get.params, arg->dfd_client_get.get); + btc_ble_mesh_dfd_client_callback(&cb, ESP_BLE_MESH_ACT_DFD_CLIEND_SEND_COMP); + break; + case BTC_BLE_MESH_ACT_DFD_CLIENT_SET: + cb.params = arg->dfd_client_set.params; + cb.err_code = btc_ble_mesh_dfd_client_set(arg->dfd_client_set.params, arg->dfd_client_set.set); + btc_ble_mesh_dfd_client_callback(&cb, ESP_BLE_MESH_ACT_DFD_CLIEND_SEND_COMP); + break; + default: + break; + } + + btc_ble_mesh_dfd_client_arg_deep_free(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) +{ + bt_mesh_dfd_srv_oob_check_complete((struct bt_mesh_dfd_srv *)srv, (struct bt_mesh_dfu_slot *)slot, status, fwid, fwid_len); + return 0; +} +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) +{ + bt_mesh_dfd_srv_oob_store_complete((struct bt_mesh_dfd_srv *)srv, (struct bt_mesh_dfu_slot *)slot, success, size, metadata, metadata_len); + return 0; +} +#endif /* CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD */ +#endif /* CONFIG_BLE_MESH_DFD_SRV */ diff --git a/components/bt/esp_ble_mesh/v1.1/btc/include/btc_ble_mesh_dfu_model.h b/components/bt/esp_ble_mesh/v1.1/btc/include/btc_ble_mesh_dfu_model.h index a74aeb5453..0111e86549 100644 --- a/components/bt/esp_ble_mesh/v1.1/btc/include/btc_ble_mesh_dfu_model.h +++ b/components/bt/esp_ble_mesh/v1.1/btc/include/btc_ble_mesh_dfu_model.h @@ -67,6 +67,55 @@ 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 diff --git a/components/bt/esp_ble_mesh/v1.1/dfu/dfd.h b/components/bt/esp_ble_mesh/v1.1/dfu/dfd.h deleted file mode 100644 index ee94be24e6..0000000000 --- a/components/bt/esp_ble_mesh/v1.1/dfu/dfd.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA - * SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "access.h" - -/* @todo: adapt to dfd client */ -#if CONFIG_BLE_MESH_DFD_SRV -#define BT_MESH_DFD_OP_RECEIVERS_ADD BLE_MESH_MODEL_OP_2(0x83, 0x11) -#define BT_MESH_DFD_OP_RECEIVERS_DELETE_ALL BLE_MESH_MODEL_OP_2(0x83, 0x12) -#define BT_MESH_DFD_OP_RECEIVERS_STATUS BLE_MESH_MODEL_OP_2(0x83, 0x13) -#define BT_MESH_DFD_OP_RECEIVERS_GET BLE_MESH_MODEL_OP_2(0x83, 0x14) -#define BT_MESH_DFD_OP_RECEIVERS_LIST BLE_MESH_MODEL_OP_2(0x83, 0x15) -#define BT_MESH_DFD_OP_CAPABILITIES_GET BLE_MESH_MODEL_OP_2(0x83, 0x16) -#define BT_MESH_DFD_OP_CAPABILITIES_STATUS BLE_MESH_MODEL_OP_2(0x83, 0x17) -#define BT_MESH_DFD_OP_GET BLE_MESH_MODEL_OP_2(0x83, 0x18) -#define BT_MESH_DFD_OP_START BLE_MESH_MODEL_OP_2(0x83, 0x19) -#define BT_MESH_DFD_OP_SUSPEND BLE_MESH_MODEL_OP_2(0x83, 0x1a) -#define BT_MESH_DFD_OP_CANCEL BLE_MESH_MODEL_OP_2(0x83, 0x1b) -#define BT_MESH_DFD_OP_APPLY BLE_MESH_MODEL_OP_2(0x83, 0x1c) -#define BT_MESH_DFD_OP_STATUS BLE_MESH_MODEL_OP_2(0x83, 0x1d) -#define BT_MESH_DFD_OP_UPLOAD_GET BLE_MESH_MODEL_OP_2(0x83, 0x1e) -#define BT_MESH_DFD_OP_UPLOAD_START BLE_MESH_MODEL_OP_2(0x83, 0x1f) -#define BT_MESH_DFD_OP_UPLOAD_START_OOB BLE_MESH_MODEL_OP_2(0x83, 0x20) -#define BT_MESH_DFD_OP_UPLOAD_CANCEL BLE_MESH_MODEL_OP_2(0x83, 0x21) -#define BT_MESH_DFD_OP_UPLOAD_STATUS BLE_MESH_MODEL_OP_2(0x83, 0x22) -#define BT_MESH_DFD_OP_FW_GET BLE_MESH_MODEL_OP_2(0x83, 0x23) -#define BT_MESH_DFD_OP_FW_GET_BY_INDEX BLE_MESH_MODEL_OP_2(0x83, 0x24) -#define BT_MESH_DFD_OP_FW_DELETE BLE_MESH_MODEL_OP_2(0x83, 0x25) -#define BT_MESH_DFD_OP_FW_DELETE_ALL BLE_MESH_MODEL_OP_2(0x83, 0x26) -#define BT_MESH_DFD_OP_FW_STATUS BLE_MESH_MODEL_OP_2(0x83, 0x27) -#endif diff --git a/components/bt/esp_ble_mesh/v1.1/dfu/dfd_cli.c b/components/bt/esp_ble_mesh/v1.1/dfu/dfd_cli.c new file mode 100644 index 0000000000..19fce3b9a8 --- /dev/null +++ b/components/bt/esp_ble_mesh/v1.1/dfu/dfd_cli.c @@ -0,0 +1,699 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#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 diff --git a/components/bt/esp_ble_mesh/v1.1/dfu/dfd_srv.c b/components/bt/esp_ble_mesh/v1.1/dfu/dfd_srv.c index 7821b21b88..955419ef1f 100644 --- a/components/bt/esp_ble_mesh/v1.1/dfu/dfd_srv.c +++ b/components/bt/esp_ble_mesh/v1.1/dfu/dfd_srv.c @@ -6,7 +6,6 @@ */ #include #include "dfu_slot.h" -#include "dfd.h" #include "dfu.h" #include "dfd_srv_internal.h" #include "net.h" @@ -19,7 +18,7 @@ #if CONFIG_BLE_MESH_DFD_SRV #define DFD_UPLOAD_STATUS_MSG_MAXLEN (5 + CONFIG_BLE_MESH_DFU_FWID_MAXLEN) -_Static_assert((DFD_UPLOAD_STATUS_MSG_MAXLEN + BLE_MESH_MODEL_OP_LEN(BT_MESH_DFD_OP_UPLOAD_STATUS) + +_Static_assert((DFD_UPLOAD_STATUS_MSG_MAXLEN + BLE_MESH_MODEL_OP_LEN(BLE_MESH_DFD_OP_UPLOAD_STATUS) + BLE_MESH_MIC_SHORT) <= BLE_MESH_TX_SDU_MAX, "The Firmware Distribution Upload Status message does not fit into the maximum " "outgoing SDU size."); @@ -27,21 +26,21 @@ _Static_assert((DFD_UPLOAD_STATUS_MSG_MAXLEN + BLE_MESH_MODEL_OP_LEN(BT_MESH_DFD #define DFD_UPLOAD_START_MSG_MAXLEN (16 + CONFIG_BLE_MESH_DFU_FWID_MAXLEN + \ CONFIG_BLE_MESH_DFU_METADATA_MAXLEN) -_Static_assert((DFD_UPLOAD_START_MSG_MAXLEN + BLE_MESH_MODEL_OP_LEN(BT_MESH_DFD_OP_UPLOAD_START) + +_Static_assert((DFD_UPLOAD_START_MSG_MAXLEN + BLE_MESH_MODEL_OP_LEN(BLE_MESH_DFD_OP_UPLOAD_START) + BLE_MESH_MIC_SHORT) <= BLE_MESH_RX_SDU_MAX, "The Firmware Distribution Upload Start message does not fit into the maximum " "incoming SDU size."); #define DFD_RECEIVERS_LIST_MSG_MAXLEN (4 + CONFIG_BLE_MESH_DFD_SRV_TARGETS_MAX * 5) -_Static_assert((DFD_RECEIVERS_LIST_MSG_MAXLEN + BLE_MESH_MODEL_OP_LEN(BT_MESH_DFD_OP_RECEIVERS_LIST) + +_Static_assert((DFD_RECEIVERS_LIST_MSG_MAXLEN + BLE_MESH_MODEL_OP_LEN(BLE_MESH_DFD_OP_RECEIVERS_LIST) + BLE_MESH_MIC_SHORT) <= BLE_MESH_TX_SDU_MAX, "The Firmware Distribution Receivers List message does not fit into the maximum " "outgoing SDU size."); #define DFD_RECEIVERS_ADD_MSG_MAXLEN (CONFIG_BLE_MESH_DFD_SRV_TARGETS_MAX * 3) -_Static_assert((DFD_RECEIVERS_ADD_MSG_MAXLEN + BLE_MESH_MODEL_OP_LEN(BT_MESH_DFD_OP_RECEIVERS_ADD) + +_Static_assert((DFD_RECEIVERS_ADD_MSG_MAXLEN + BLE_MESH_MODEL_OP_LEN(BLE_MESH_DFD_OP_RECEIVERS_ADD) + BLE_MESH_MIC_SHORT) <= BLE_MESH_RX_SDU_MAX, "The Firmware Distribution Receivers Add message does not fit into the maximum " "incoming SDU size."); @@ -76,15 +75,15 @@ static struct bt_mesh_dfu_target *target_get(struct bt_mesh_dfd_srv *srv, static bool is_busy(const struct bt_mesh_dfd_srv *srv) { - return srv->phase == BT_MESH_DFD_PHASE_TRANSFER_ACTIVE || - srv->phase == BT_MESH_DFD_PHASE_TRANSFER_SUCCESS || - srv->phase == BT_MESH_DFD_PHASE_APPLYING_UPDATE; + return srv->phase == BLE_MESH_DFD_PHASE_TRANSFER_ACTIVE || + srv->phase == BLE_MESH_DFD_PHASE_TRANSFER_SUCCESS || + srv->phase == BLE_MESH_DFD_PHASE_APPLYING_UPDATE; } static bool upload_is_busy(const struct bt_mesh_dfd_srv *srv) { return bt_mesh_blob_srv_is_busy(&srv->upload.blob) || - srv->upload.phase == BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE; + srv->upload.phase == BLE_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE; } static int slot_del(struct bt_mesh_dfd_srv *srv, const struct bt_mesh_dfu_slot *slot) @@ -100,8 +99,8 @@ static void receivers_status_rsp(struct bt_mesh_dfd_srv *srv, struct bt_mesh_msg_ctx *ctx, enum bt_mesh_dfd_status status) { - BLE_MESH_MODEL_BUF_DEFINE(buf, BT_MESH_DFD_OP_RECEIVERS_STATUS, 3); - bt_mesh_model_msg_init(&buf, BT_MESH_DFD_OP_RECEIVERS_STATUS); + BLE_MESH_MODEL_BUF_DEFINE(buf, BLE_MESH_DFD_OP_RECEIVERS_STATUS, 3); + bt_mesh_model_msg_init(&buf, BLE_MESH_DFD_OP_RECEIVERS_STATUS); net_buf_simple_add_u8(&buf, status); net_buf_simple_add_le16(&buf, srv->target_cnt); @@ -112,7 +111,7 @@ static void receivers_status_rsp(struct bt_mesh_dfd_srv *srv, static int handle_receivers_add(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - enum bt_mesh_dfd_status status = BT_MESH_DFD_SUCCESS; + enum bt_mesh_dfd_status status = BLE_MESH_DFD_SUCCESS; struct bt_mesh_dfd_srv *srv = mod->user_data; if (buf->len % 3) { @@ -121,11 +120,11 @@ static int handle_receivers_add(const struct bt_mesh_model *mod, struct bt_mesh_ if (bt_mesh_dfu_cli_is_busy(&srv->dfu)) { receivers_status_rsp(srv, ctx, - BT_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION); + BLE_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION); return 0; } - while (buf->len >= 3 && status == BT_MESH_DFD_SUCCESS) { + while (buf->len >= 3 && status == BLE_MESH_DFD_SUCCESS) { uint8_t img_idx; uint16_t addr; @@ -166,9 +165,9 @@ static int handle_receivers_get(const struct bt_mesh_model *mod, struct bt_mesh_ /* Create a buffer that can fit the full target list, maxing out at TX_SDU_MAX: */ NET_BUF_SIMPLE_DEFINE( - rsp, BLE_MESH_MODEL_BUF_LEN(BT_MESH_DFD_OP_RECEIVERS_LIST, + rsp, BLE_MESH_MODEL_BUF_LEN(BLE_MESH_DFD_OP_RECEIVERS_LIST, DFD_RECEIVERS_LIST_MSG_MAXLEN)); - bt_mesh_model_msg_init(&rsp, BT_MESH_DFD_OP_RECEIVERS_LIST); + bt_mesh_model_msg_init(&rsp, BLE_MESH_DFD_OP_RECEIVERS_LIST); net_buf_simple_add_le16(&rsp, srv->target_cnt); net_buf_simple_add_le16(&rsp, first); @@ -208,8 +207,8 @@ static int handle_capabilities_get(const struct bt_mesh_model *mod, struct bt_me { size_t size = 0; - BLE_MESH_MODEL_BUF_DEFINE(rsp, BT_MESH_DFD_OP_CAPABILITIES_STATUS, 17); - bt_mesh_model_msg_init(&rsp, BT_MESH_DFD_OP_CAPABILITIES_STATUS); + BLE_MESH_MODEL_BUF_DEFINE(rsp, BLE_MESH_DFD_OP_CAPABILITIES_GET, 17); + bt_mesh_model_msg_init(&rsp, BLE_MESH_DFD_OP_CAPABILITIES_GET); net_buf_simple_add_le16(&rsp, CONFIG_BLE_MESH_DFD_SRV_TARGETS_MAX); net_buf_simple_add_le16(&rsp, CONFIG_BLE_MESH_DFU_SLOT_CNT); @@ -243,13 +242,13 @@ static int handle_capabilities_get(const struct bt_mesh_model *mod, struct bt_me static void status_rsp(struct bt_mesh_dfd_srv *srv, struct bt_mesh_msg_ctx *ctx, enum bt_mesh_dfd_status status) { - BLE_MESH_MODEL_BUF_DEFINE(rsp, BT_MESH_DFD_OP_STATUS, 12); - bt_mesh_model_msg_init(&rsp, BT_MESH_DFD_OP_STATUS); + BLE_MESH_MODEL_BUF_DEFINE(rsp, BLE_MESH_DFD_OP_STATUS, 12); + bt_mesh_model_msg_init(&rsp, BLE_MESH_DFD_OP_STATUS); net_buf_simple_add_u8(&rsp, status); net_buf_simple_add_u8(&rsp, srv->phase); - if (srv->phase == BT_MESH_DFD_PHASE_IDLE || !srv->dfu.xfer.slot) { + if (srv->phase == BLE_MESH_DFD_PHASE_IDLE || !srv->dfu.xfer.slot) { bt_mesh_model_send(srv->mod, ctx, &rsp, NULL, NULL); return; } @@ -270,7 +269,7 @@ static int handle_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *c { struct bt_mesh_dfd_srv *srv = mod->user_data; - status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS); + status_rsp(srv, ctx, BLE_MESH_DFD_SUCCESS); return 0; } @@ -292,7 +291,7 @@ static int handle_start(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx if (buf->len == 16) { /* TODO: Virtual addresses not supported. */ - status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL); + status_rsp(srv, ctx, BLE_MESH_DFD_ERR_INTERNAL); return 0; } @@ -343,14 +342,14 @@ static void upload_status_rsp_with_progress(struct bt_mesh_dfd_srv *srv, enum bt_mesh_dfd_status status, uint8_t progress) { - BLE_MESH_MODEL_BUF_DEFINE(rsp, BT_MESH_DFD_OP_UPLOAD_STATUS, + BLE_MESH_MODEL_BUF_DEFINE(rsp, BLE_MESH_DFD_OP_UPLOAD_STATUS, DFD_UPLOAD_STATUS_MSG_MAXLEN); - bt_mesh_model_msg_init(&rsp, BT_MESH_DFD_OP_UPLOAD_STATUS); + bt_mesh_model_msg_init(&rsp, BLE_MESH_DFD_OP_UPLOAD_STATUS); net_buf_simple_add_u8(&rsp, status); net_buf_simple_add_u8(&rsp, srv->upload.phase); - if (srv->upload.phase == BT_MESH_DFD_UPLOAD_PHASE_IDLE || + if (srv->upload.phase == BLE_MESH_DFD_UPLOAD_PHASE_IDLE || !srv->upload.slot) { bt_mesh_model_send(srv->mod, ctx, &rsp, NULL, NULL); return; @@ -395,7 +394,7 @@ static int handle_upload_get(const struct bt_mesh_model *mod, struct bt_mesh_msg { struct bt_mesh_dfd_srv *srv = mod->user_data; - upload_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS); + upload_status_rsp(srv, ctx, BLE_MESH_DFD_SUCCESS); return 0; } @@ -410,22 +409,22 @@ static inline int set_upload_fwid(struct bt_mesh_dfd_srv *srv, struct bt_mesh_ms case -EALREADY: /* Other server is in progress with this fwid */ bt_mesh_dfu_slot_release(srv->upload.slot); srv->upload.slot = NULL; - upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL); + upload_status_rsp(srv, ctx, BLE_MESH_DFD_ERR_INTERNAL); break; case -EEXIST: /* Img with this fwid already is in list */ - srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_SUCCESS; + srv->upload.phase = BLE_MESH_DFD_UPLOAD_PHASE_TRANSFER_SUCCESS; bt_mesh_dfu_slot_release(srv->upload.slot); err = bt_mesh_dfu_slot_get(fwid, fwid_len, &srv->upload.slot); if (!err) { - upload_status_rsp_with_progress(srv, ctx, BT_MESH_DFD_SUCCESS, 100); + upload_status_rsp_with_progress(srv, ctx, BLE_MESH_DFD_SUCCESS, 100); } else { srv->upload.slot = NULL; - upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL); + upload_status_rsp(srv, ctx, BLE_MESH_DFD_ERR_INTERNAL); } break; case 0: - srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE; + srv->upload.phase = BLE_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE; break; case -EINVAL: /* Slot in wrong state. */ default: @@ -464,14 +463,14 @@ static int handle_upload_start(const struct bt_mesh_model *mod, struct bt_mesh_m if (size > CONFIG_BLE_MESH_DFD_SRV_SLOT_MAX_SIZE) { upload_status_rsp(srv, ctx, - BT_MESH_DFD_ERR_INSUFFICIENT_RESOURCES); + BLE_MESH_DFD_ERR_INSUFFICIENT_RESOURCES); return 0; } if (upload_is_busy(srv)) { if (!srv->upload.slot) { BT_WARN("Busy with no upload slot"); - upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL); + upload_status_rsp(srv, ctx, BLE_MESH_DFD_ERR_INTERNAL); return 0; } @@ -487,12 +486,12 @@ static int handle_upload_start(const struct bt_mesh_model *mod, struct bt_mesh_m #endif ) { BT_DBG("Duplicate upload start"); - upload_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS); + upload_status_rsp(srv, ctx, BLE_MESH_DFD_SUCCESS); return 0; } BT_WARN("Upload already in progress"); - upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_BUSY_WITH_UPLOAD); + upload_status_rsp(srv, ctx, BLE_MESH_DFD_ERR_BUSY_WITH_UPLOAD); return 0; } @@ -511,7 +510,7 @@ static int handle_upload_start(const struct bt_mesh_model *mod, struct bt_mesh_m if (!srv->upload.slot) { BT_WARN("No space for slot"); upload_status_rsp(srv, ctx, - BT_MESH_DFD_ERR_INSUFFICIENT_RESOURCES); + BLE_MESH_DFD_ERR_INSUFFICIENT_RESOURCES); return 0; } @@ -523,7 +522,7 @@ static int handle_upload_start(const struct bt_mesh_model *mod, struct bt_mesh_m err = bt_mesh_dfu_slot_info_set(srv->upload.slot, size, meta, meta_len); switch (err) { case -EFBIG: - upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL); + upload_status_rsp(srv, ctx, BLE_MESH_DFD_ERR_INTERNAL); break; case 0: break; @@ -536,7 +535,7 @@ static int handle_upload_start(const struct bt_mesh_model *mod, struct bt_mesh_m if (err || !srv->io) { BT_ERR("App rejected upload. err: %d io: %p", err, srv->io); bt_mesh_dfu_slot_release(srv->upload.slot); - upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL); + upload_status_rsp(srv, ctx, BLE_MESH_DFD_ERR_INTERNAL); return 0; } @@ -545,14 +544,14 @@ static int handle_upload_start(const struct bt_mesh_model *mod, struct bt_mesh_m if (err) { BT_ERR("BLOB Server rejected upload (err: %d)", err); bt_mesh_dfu_slot_release(srv->upload.slot); - upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL); + upload_status_rsp(srv, ctx, BLE_MESH_DFD_ERR_INTERNAL); return 0; } BT_DBG("%s", bt_hex(fwid, fwid_len)); - srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE; - upload_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS); + srv->upload.phase = BLE_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE; + upload_status_rsp(srv, ctx, BLE_MESH_DFD_SUCCESS); return 0; } @@ -588,11 +587,11 @@ static int handle_upload_start_oob(const struct bt_mesh_model *mod, struct bt_me !memcmp(uri, srv->upload.oob.uri, uri_len) && !memcmp(fwid, srv->upload.oob.current_fwid, fwid_len)) { /* Same image, return SUCCESS for idempotency */ - upload_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS); + upload_status_rsp(srv, ctx, BLE_MESH_DFD_SUCCESS); return 0; } #endif - upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_BUSY_WITH_UPLOAD); + upload_status_rsp(srv, ctx, BLE_MESH_DFD_ERR_BUSY_WITH_UPLOAD); return 0; #ifdef CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD } else if (srv->upload.is_oob && srv->upload.is_pending_oob_check) { @@ -604,14 +603,14 @@ static int handle_upload_start_oob(const struct bt_mesh_model *mod, struct bt_me #ifdef CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD if (uri_len > CONFIG_BLE_MESH_DFU_URI_MAXLEN || fwid_len > CONFIG_BLE_MESH_DFU_FWID_MAXLEN) { - upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL); + upload_status_rsp(srv, ctx, BLE_MESH_DFD_ERR_INTERNAL); return 0; } struct bt_mesh_dfu_slot *slot = bt_mesh_dfu_slot_reserve(); if (slot == NULL) { - upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INSUFFICIENT_RESOURCES); + upload_status_rsp(srv, ctx, BLE_MESH_DFD_ERR_INSUFFICIENT_RESOURCES); return 0; } @@ -635,14 +634,14 @@ static int handle_upload_start_oob(const struct bt_mesh_model *mod, struct bt_me srv->upload.oob.current_fwid, srv->upload.oob.current_fwid_len); - if (status != BT_MESH_DFD_SUCCESS) { + if (status != BLE_MESH_DFD_SUCCESS) { upload_status_rsp(srv, ctx, status); bt_mesh_dfu_slot_release(srv->upload.slot); } else { srv->upload.is_pending_oob_check = true; } #else - upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_URI_NOT_SUPPORTED); + upload_status_rsp(srv, ctx, BLE_MESH_DFD_ERR_URI_NOT_SUPPORTED); #endif /* CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD */ return 0; @@ -653,7 +652,7 @@ static int handle_upload_cancel(const struct bt_mesh_model *mod, struct bt_mesh_ { struct bt_mesh_dfd_srv *srv = mod->user_data; - srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_IDLE; + srv->upload.phase = BLE_MESH_DFD_UPLOAD_PHASE_IDLE; #ifdef CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD if (srv->upload.is_oob) { srv->cb->cancel_oob_upload(srv, srv->upload.slot); @@ -662,7 +661,7 @@ static int handle_upload_cancel(const struct bt_mesh_model *mod, struct bt_mesh_ { (void)bt_mesh_blob_srv_cancel(&srv->upload.blob); } - upload_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS); + upload_status_rsp(srv, ctx, BLE_MESH_DFD_SUCCESS); return 0; } @@ -672,9 +671,9 @@ static void fw_status_rsp(struct bt_mesh_dfd_srv *srv, enum bt_mesh_dfd_status status, uint16_t idx, const uint8_t *fwid, size_t fwid_len) { - BLE_MESH_MODEL_BUF_DEFINE(rsp, BT_MESH_DFD_OP_FW_STATUS, + BLE_MESH_MODEL_BUF_DEFINE(rsp, BLE_MESH_DFD_OP_FW_STATUS, 7 + CONFIG_BLE_MESH_DFU_FWID_MAXLEN); - bt_mesh_model_msg_init(&rsp, BT_MESH_DFD_OP_FW_STATUS); + bt_mesh_model_msg_init(&rsp, BLE_MESH_DFD_OP_FW_STATUS); net_buf_simple_add_u8(&rsp, status); net_buf_simple_add_le16(&rsp, bt_mesh_dfu_slot_count()); @@ -701,10 +700,10 @@ static int handle_fw_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx idx = bt_mesh_dfu_slot_get(fwid, fwid_len, &slot); if (idx >= 0) { - fw_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS, idx, fwid, + fw_status_rsp(srv, ctx, BLE_MESH_DFD_SUCCESS, idx, fwid, fwid_len); } else { - fw_status_rsp(srv, ctx, BT_MESH_DFD_ERR_FW_NOT_FOUND, 0xffff, + fw_status_rsp(srv, ctx, BLE_MESH_DFD_ERR_FW_NOT_FOUND, 0xffff, fwid, fwid_len); } @@ -722,10 +721,10 @@ static int handle_fw_get_by_index(const struct bt_mesh_model *mod, struct bt_mes slot = bt_mesh_dfu_slot_at(idx); if (slot) { - fw_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS, idx, slot->fwid, + fw_status_rsp(srv, ctx, BLE_MESH_DFD_SUCCESS, idx, slot->fwid, slot->fwid_len); } else { - fw_status_rsp(srv, ctx, BT_MESH_DFD_ERR_FW_NOT_FOUND, idx, + fw_status_rsp(srv, ctx, BLE_MESH_DFD_ERR_FW_NOT_FOUND, idx, NULL, 0); } @@ -772,23 +771,23 @@ static int handle_fw_delete_all(const struct bt_mesh_model *mod, struct bt_mesh_ } const struct bt_mesh_model_op _bt_mesh_dfd_srv_op[] = { - { BT_MESH_DFD_OP_RECEIVERS_ADD, 3, (void *)handle_receivers_add }, - { BT_MESH_DFD_OP_RECEIVERS_DELETE_ALL, 0, (void *)handle_receivers_delete_all }, - { BT_MESH_DFD_OP_RECEIVERS_GET, 4, (void *)handle_receivers_get }, - { BT_MESH_DFD_OP_CAPABILITIES_GET, 0, (void *)handle_capabilities_get }, - { BT_MESH_DFD_OP_GET, 0, (void *)handle_get }, - { BT_MESH_DFD_OP_START, 10, (void *)handle_start }, - { BT_MESH_DFD_OP_SUSPEND, 0, (void *)handle_suspend }, - { BT_MESH_DFD_OP_CANCEL, 0, (void *)handle_cancel }, - { BT_MESH_DFD_OP_APPLY, 0, (void *)handle_apply }, - { BT_MESH_DFD_OP_UPLOAD_GET, 0, (void *)handle_upload_get }, - { BT_MESH_DFD_OP_UPLOAD_START, 16, (void *)handle_upload_start }, - { BT_MESH_DFD_OP_UPLOAD_START_OOB, 2, (void *)handle_upload_start_oob }, - { BT_MESH_DFD_OP_UPLOAD_CANCEL, 0, (void *)handle_upload_cancel }, - { BT_MESH_DFD_OP_FW_GET, 0, (void *)handle_fw_get }, - { BT_MESH_DFD_OP_FW_GET_BY_INDEX, 2, (void *)handle_fw_get_by_index }, - { BT_MESH_DFD_OP_FW_DELETE, 0, (void *)handle_fw_delete }, - { BT_MESH_DFD_OP_FW_DELETE_ALL, 0, (void *)handle_fw_delete_all }, + { BLE_MESH_DFD_OP_RECEIVERS_ADD, 3, (void *)handle_receivers_add }, + { BLE_MESH_DFD_OP_RECEIVERS_DELETE_ALL, 0, (void *)handle_receivers_delete_all }, + { BLE_MESH_DFD_OP_RECEIVERS_GET, 4, (void *)handle_receivers_get }, + { BLE_MESH_DFD_OP_CAPABILITIES_GET, 0, (void *)handle_capabilities_get }, + { BLE_MESH_DFD_OP_GET, 0, (void *)handle_get }, + { BLE_MESH_DFD_OP_START, 10, (void *)handle_start }, + { BLE_MESH_DFD_OP_SUSPEND, 0, (void *)handle_suspend }, + { BLE_MESH_DFD_OP_CANCEL, 0, (void *)handle_cancel }, + { BLE_MESH_DFD_OP_APPLY, 0, (void *)handle_apply }, + { BLE_MESH_DFD_OP_UPLOAD_GET, 0, (void *)handle_upload_get }, + { BLE_MESH_DFD_OP_UPLOAD_START, 16, (void *)handle_upload_start }, + { BLE_MESH_DFD_OP_UPLOAD_START_OOB, 2, (void *)handle_upload_start_oob }, + { BLE_MESH_DFD_OP_UPLOAD_CANCEL, 0, (void *)handle_upload_cancel }, + { BLE_MESH_DFD_OP_FW_GET, 0, (void *)handle_fw_get }, + { BLE_MESH_DFD_OP_FW_GET_BY_INDEX, 2, (void *)handle_fw_get_by_index }, + { BLE_MESH_DFD_OP_FW_DELETE, 0, (void *)handle_fw_delete }, + { BLE_MESH_DFD_OP_FW_DELETE_ALL, 0, (void *)handle_fw_delete_all }, BLE_MESH_MODEL_OP_END }; @@ -798,7 +797,7 @@ static void dfu_suspended(struct bt_mesh_dfu_cli *cli) struct bt_mesh_dfd_srv *srv = CONTAINER_OF(cli, struct bt_mesh_dfd_srv, dfu); - dfd_phase_set(srv, BT_MESH_DFD_PHASE_TRANSFER_SUSPENDED); + dfd_phase_set(srv, BLE_MESH_DFD_PHASE_TRANSFER_SUSPENDED); } static void dfu_ended(struct bt_mesh_dfu_cli *cli, @@ -810,31 +809,31 @@ static void dfu_ended(struct bt_mesh_dfu_cli *cli, BT_DBG("reason: %u, phase: %u, apply: %u", reason, srv->phase, srv->apply); - if (srv->phase == BT_MESH_DFD_PHASE_IDLE) { + if (srv->phase == BLE_MESH_DFD_PHASE_IDLE) { return; } - if (srv->phase == BT_MESH_DFD_PHASE_CANCELING_UPDATE) { - dfd_phase_set(srv, BT_MESH_DFD_PHASE_IDLE); + if (srv->phase == BLE_MESH_DFD_PHASE_CANCELING_UPDATE) { + dfd_phase_set(srv, BLE_MESH_DFD_PHASE_IDLE); return; } if (reason != BLE_MESH_DFU_SUCCESS) { - dfd_phase_set(srv, BT_MESH_DFD_PHASE_FAILED); + dfd_phase_set(srv, BLE_MESH_DFD_PHASE_FAILED); return; } if (!srv->apply) { - dfd_phase_set(srv, BT_MESH_DFD_PHASE_TRANSFER_SUCCESS); + dfd_phase_set(srv, BLE_MESH_DFD_PHASE_TRANSFER_SUCCESS); return; } - dfd_phase_set(srv, BT_MESH_DFD_PHASE_APPLYING_UPDATE); + dfd_phase_set(srv, BLE_MESH_DFD_PHASE_APPLYING_UPDATE); err = bt_mesh_dfu_cli_apply(cli); if (err) { BT_ERR("Apply failed: %d", err); - dfd_phase_set(srv, BT_MESH_DFD_PHASE_FAILED); + dfd_phase_set(srv, BLE_MESH_DFD_PHASE_FAILED); } } @@ -844,19 +843,19 @@ static void dfu_applied(struct bt_mesh_dfu_cli *cli) CONTAINER_OF(cli, struct bt_mesh_dfd_srv, dfu); int err; - if (srv->phase == BT_MESH_DFD_PHASE_CANCELING_UPDATE) { - dfd_phase_set(srv, BT_MESH_DFD_PHASE_FAILED); + if (srv->phase == BLE_MESH_DFD_PHASE_CANCELING_UPDATE) { + dfd_phase_set(srv, BLE_MESH_DFD_PHASE_FAILED); return; } - if (srv->phase != BT_MESH_DFD_PHASE_APPLYING_UPDATE) { + if (srv->phase != BLE_MESH_DFD_PHASE_APPLYING_UPDATE) { return; } err = bt_mesh_dfu_cli_confirm(cli); if (err) { BT_ERR("Confirm failed: %d", err); - dfd_phase_set(srv, BT_MESH_DFD_PHASE_FAILED); + dfd_phase_set(srv, BLE_MESH_DFD_PHASE_FAILED); } } @@ -865,12 +864,12 @@ static void dfu_confirmed(struct bt_mesh_dfu_cli *cli) struct bt_mesh_dfd_srv *srv = CONTAINER_OF(cli, struct bt_mesh_dfd_srv, dfu); - if (srv->phase != BT_MESH_DFD_PHASE_APPLYING_UPDATE && - srv->phase != BT_MESH_DFD_PHASE_CANCELING_UPDATE) { + if (srv->phase != BLE_MESH_DFD_PHASE_APPLYING_UPDATE && + srv->phase != BLE_MESH_DFD_PHASE_CANCELING_UPDATE) { return; } - dfd_phase_set(srv, BT_MESH_DFD_PHASE_COMPLETED); + dfd_phase_set(srv, BLE_MESH_DFD_PHASE_COMPLETED); } const struct bt_mesh_dfu_cli_cb _bt_mesh_dfd_srv_dfu_cb = { @@ -892,19 +891,19 @@ static void upload_end(struct bt_mesh_blob_srv *b, uint64_t id, bool success) struct bt_mesh_dfd_srv *srv = CONTAINER_OF(b, struct bt_mesh_dfd_srv, upload.blob); - if (srv->upload.phase != BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE) { + if (srv->upload.phase != BLE_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE) { return; } BT_DBG("%u", success); if (success && (bt_mesh_dfu_slot_commit(srv->upload.slot) == 0)) { - srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_SUCCESS; + srv->upload.phase = BLE_MESH_DFD_UPLOAD_PHASE_TRANSFER_SUCCESS; return; } /* Will delete slot when we start a new upload */ - srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ERROR; + srv->upload.phase = BLE_MESH_DFD_UPLOAD_PHASE_TRANSFER_ERROR; } static void upload_timeout(struct bt_mesh_blob_srv *b) @@ -933,9 +932,9 @@ static void dfd_srv_reset(struct bt_mesh_model *mod) { struct bt_mesh_dfd_srv *srv = mod->user_data; - dfd_phase_set(srv, BT_MESH_DFD_PHASE_IDLE); + dfd_phase_set(srv, BLE_MESH_DFD_PHASE_IDLE); - srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_IDLE; + srv->upload.phase = BLE_MESH_DFD_UPLOAD_PHASE_IDLE; sys_slist_init(&srv->inputs.targets); srv->target_cnt = 0; @@ -963,19 +962,19 @@ enum bt_mesh_dfd_status bt_mesh_dfd_srv_receiver_add(struct bt_mesh_dfd_srv *srv struct bt_mesh_blob_target_pull *p; if (!BLE_MESH_ADDR_IS_UNICAST(addr)) { - return BT_MESH_DFD_SUCCESS; + return BLE_MESH_DFD_SUCCESS; } t = target_get(srv, addr); if (t) { t->img_idx = img_idx; - return BT_MESH_DFD_SUCCESS; + return BLE_MESH_DFD_SUCCESS; } /* New target node, add it to the list */ if (srv->target_cnt == ARRAY_SIZE(srv->targets)) { - return BT_MESH_DFD_ERR_INSUFFICIENT_RESOURCES; + return BLE_MESH_DFD_ERR_INSUFFICIENT_RESOURCES; } t = &srv->targets[srv->target_cnt]; @@ -991,19 +990,19 @@ enum bt_mesh_dfd_status bt_mesh_dfd_srv_receiver_add(struct bt_mesh_dfd_srv *srv BT_DBG("Added receiver 0x%04x img: %u", t->blob.addr, t->img_idx); - return BT_MESH_DFD_SUCCESS; + return BLE_MESH_DFD_SUCCESS; } enum bt_mesh_dfd_status bt_mesh_dfd_srv_receivers_delete_all(struct bt_mesh_dfd_srv *srv) { if (bt_mesh_dfu_cli_is_busy(&srv->dfu)) { - return BT_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION; + return BLE_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION; } sys_slist_init(&srv->inputs.targets); srv->target_cnt = 0; - return BT_MESH_DFD_SUCCESS; + return BLE_MESH_DFD_SUCCESS; } enum bt_mesh_dfd_status bt_mesh_dfd_srv_start(struct bt_mesh_dfd_srv *srv, @@ -1013,17 +1012,17 @@ enum bt_mesh_dfd_status bt_mesh_dfd_srv_start(struct bt_mesh_dfd_srv *srv, struct bt_mesh_dfu_cli_xfer xfer = { 0 }; if (!srv->target_cnt) { - return BT_MESH_DFD_ERR_RECEIVERS_LIST_EMPTY; + return BLE_MESH_DFD_ERR_RECEIVERS_LIST_EMPTY; } if (!bt_mesh_app_key_get(params->app_idx)) { - return BT_MESH_DFD_ERR_INVALID_APPKEY_INDEX; + return BLE_MESH_DFD_ERR_INVALID_APPKEY_INDEX; } xfer.mode = params->xfer_mode; xfer.slot = bt_mesh_dfu_slot_at(params->slot_idx); if (!xfer.slot) { - return BT_MESH_DFD_ERR_FW_NOT_FOUND; + return BLE_MESH_DFD_ERR_FW_NOT_FOUND; } if (srv->inputs.app_idx == params->app_idx && @@ -1032,29 +1031,29 @@ enum bt_mesh_dfd_status bt_mesh_dfd_srv_start(struct bt_mesh_dfd_srv *srv, srv->dfu.xfer.blob.mode == xfer.mode && srv->apply == params->apply && srv->slot_idx == params->slot_idx) { if (is_busy(srv) || - srv->phase == BT_MESH_DFD_PHASE_COMPLETED) { + srv->phase == BLE_MESH_DFD_PHASE_COMPLETED) { BT_WARN("Already completed or in progress"); - return BT_MESH_DFD_SUCCESS; - } else if (srv->phase == BT_MESH_DFD_PHASE_TRANSFER_SUSPENDED) { + return BLE_MESH_DFD_SUCCESS; + } else if (srv->phase == BLE_MESH_DFD_PHASE_TRANSFER_SUSPENDED) { bt_mesh_dfu_cli_resume(&srv->dfu); - dfd_phase_set(srv, BT_MESH_DFD_PHASE_TRANSFER_ACTIVE); - return BT_MESH_DFD_SUCCESS; + dfd_phase_set(srv, BLE_MESH_DFD_PHASE_TRANSFER_ACTIVE); + return BLE_MESH_DFD_SUCCESS; } } else if (is_busy(srv) || - srv->phase == BT_MESH_DFD_PHASE_TRANSFER_SUSPENDED) { + srv->phase == BLE_MESH_DFD_PHASE_TRANSFER_SUSPENDED) { BT_WARN("Busy with distribution"); - return BT_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION; + return BLE_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION; } - if (srv->phase == BT_MESH_DFD_PHASE_CANCELING_UPDATE) { + if (srv->phase == BLE_MESH_DFD_PHASE_CANCELING_UPDATE) { BT_WARN("Canceling distribution"); - return BT_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION; + return BLE_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION; } srv->io = NULL; err = srv->cb->send(srv, xfer.slot, &srv->io); if (err || !srv->io) { - return BT_MESH_DFD_ERR_INTERNAL; + return BLE_MESH_DFD_ERR_INTERNAL; } sys_slist_init(&srv->inputs.targets); @@ -1083,35 +1082,35 @@ enum bt_mesh_dfd_status bt_mesh_dfd_srv_start(struct bt_mesh_dfd_srv *srv, /* DFD Server will always retrieve targets' capabilities before distributing a firmware.*/ xfer.blob_params = NULL; - dfd_phase_set(srv, BT_MESH_DFD_PHASE_TRANSFER_ACTIVE); + dfd_phase_set(srv, BLE_MESH_DFD_PHASE_TRANSFER_ACTIVE); err = bt_mesh_dfu_cli_send(&srv->dfu, &srv->inputs, srv->io, &xfer); if (err) { - dfd_phase_set(srv, BT_MESH_DFD_PHASE_IDLE); - return BT_MESH_DFD_ERR_INTERNAL; + dfd_phase_set(srv, BLE_MESH_DFD_PHASE_IDLE); + return BLE_MESH_DFD_ERR_INTERNAL; } - return BT_MESH_DFD_SUCCESS; + return BLE_MESH_DFD_SUCCESS; } enum bt_mesh_dfd_status bt_mesh_dfd_srv_suspend(struct bt_mesh_dfd_srv *srv) { int err; - if (srv->phase == BT_MESH_DFD_PHASE_TRANSFER_SUSPENDED) { - return BT_MESH_DFD_SUCCESS; + if (srv->phase == BLE_MESH_DFD_PHASE_TRANSFER_SUSPENDED) { + return BLE_MESH_DFD_SUCCESS; } - if (srv->phase != BT_MESH_DFD_PHASE_TRANSFER_ACTIVE) { - return BT_MESH_DFD_ERR_WRONG_PHASE; + if (srv->phase != BLE_MESH_DFD_PHASE_TRANSFER_ACTIVE) { + return BLE_MESH_DFD_ERR_WRONG_PHASE; } err = bt_mesh_dfu_cli_suspend(&srv->dfu); if (err) { - return BT_MESH_DFD_ERR_SUSPEND_FAILED; + return BLE_MESH_DFD_ERR_SUSPEND_FAILED; } - srv->phase = BT_MESH_DFD_PHASE_TRANSFER_SUSPENDED; - return BT_MESH_DFD_SUCCESS; + srv->phase = BLE_MESH_DFD_PHASE_TRANSFER_SUSPENDED; + return BLE_MESH_DFD_SUCCESS; } enum bt_mesh_dfd_status bt_mesh_dfd_srv_cancel(struct bt_mesh_dfd_srv *srv, @@ -1120,36 +1119,36 @@ enum bt_mesh_dfd_status bt_mesh_dfd_srv_cancel(struct bt_mesh_dfd_srv *srv, enum bt_mesh_dfd_phase prev_phase; int err; - if (srv->phase == BT_MESH_DFD_PHASE_CANCELING_UPDATE || - srv->phase == BT_MESH_DFD_PHASE_IDLE) { + if (srv->phase == BLE_MESH_DFD_PHASE_CANCELING_UPDATE || + srv->phase == BLE_MESH_DFD_PHASE_IDLE) { if (ctx != NULL) { - status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS); + status_rsp(srv, ctx, BLE_MESH_DFD_SUCCESS); } - return BT_MESH_DFD_SUCCESS; + return BLE_MESH_DFD_SUCCESS; } - if (srv->phase == BT_MESH_DFD_PHASE_COMPLETED || - srv->phase == BT_MESH_DFD_PHASE_FAILED) { - dfd_phase_set(srv, BT_MESH_DFD_PHASE_IDLE); + if (srv->phase == BLE_MESH_DFD_PHASE_COMPLETED || + srv->phase == BLE_MESH_DFD_PHASE_FAILED) { + dfd_phase_set(srv, BLE_MESH_DFD_PHASE_IDLE); if (ctx != NULL) { - status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS); + status_rsp(srv, ctx, BLE_MESH_DFD_SUCCESS); } - return BT_MESH_DFD_SUCCESS; + return BLE_MESH_DFD_SUCCESS; } /* Phase TRANSFER_ACTIVE, TRANSFER_SUSPENDED, TRANSFER_SUCCESS, APPLYING_UPDATE: */ prev_phase = srv->phase; - dfd_phase_set(srv, BT_MESH_DFD_PHASE_CANCELING_UPDATE); + dfd_phase_set(srv, BLE_MESH_DFD_PHASE_CANCELING_UPDATE); err = bt_mesh_dfu_cli_cancel(&srv->dfu, NULL); if (err) { if (ctx != NULL) { - status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL); + status_rsp(srv, ctx, BLE_MESH_DFD_ERR_INTERNAL); } - return BT_MESH_DFD_ERR_INTERNAL; + return BLE_MESH_DFD_ERR_INTERNAL; } - if (prev_phase == BT_MESH_DFD_PHASE_APPLYING_UPDATE && ctx) { + if (prev_phase == BLE_MESH_DFD_PHASE_APPLYING_UPDATE && ctx) { /* Disable randomization for the Firmware Distribution State message to avoid * reordering when Firmware Distribution Server sends 2 messages in a row when * cancelling the update (see section 6.2.3.10 of MshDFUv1.0). @@ -1161,43 +1160,43 @@ enum bt_mesh_dfd_status bt_mesh_dfd_srv_cancel(struct bt_mesh_dfd_srv *srv, } if (ctx != NULL) { - status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS); + status_rsp(srv, ctx, BLE_MESH_DFD_SUCCESS); } - if (prev_phase == BT_MESH_DFD_PHASE_APPLYING_UPDATE) { - dfd_phase_set(srv, BT_MESH_DFD_PHASE_IDLE); + if (prev_phase == BLE_MESH_DFD_PHASE_APPLYING_UPDATE) { + dfd_phase_set(srv, BLE_MESH_DFD_PHASE_IDLE); if (ctx != NULL) { - status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS); + status_rsp(srv, ctx, BLE_MESH_DFD_SUCCESS); } } - return BT_MESH_DFD_SUCCESS; + return BLE_MESH_DFD_SUCCESS; } enum bt_mesh_dfd_status bt_mesh_dfd_srv_apply(struct bt_mesh_dfd_srv *srv) { int err; - if (srv->phase == BT_MESH_DFD_PHASE_IDLE || - srv->phase == BT_MESH_DFD_PHASE_CANCELING_UPDATE || - srv->phase == BT_MESH_DFD_PHASE_TRANSFER_ACTIVE || - srv->phase == BT_MESH_DFD_PHASE_TRANSFER_SUSPENDED || - srv->phase == BT_MESH_DFD_PHASE_FAILED) { - return BT_MESH_DFD_ERR_WRONG_PHASE; + if (srv->phase == BLE_MESH_DFD_PHASE_IDLE || + srv->phase == BLE_MESH_DFD_PHASE_CANCELING_UPDATE || + srv->phase == BLE_MESH_DFD_PHASE_TRANSFER_ACTIVE || + srv->phase == BLE_MESH_DFD_PHASE_TRANSFER_SUSPENDED || + srv->phase == BLE_MESH_DFD_PHASE_FAILED) { + return BLE_MESH_DFD_ERR_WRONG_PHASE; } - if (srv->phase == BT_MESH_DFD_PHASE_APPLYING_UPDATE || - srv->phase == BT_MESH_DFD_PHASE_COMPLETED) { - return BT_MESH_DFD_SUCCESS; + if (srv->phase == BLE_MESH_DFD_PHASE_APPLYING_UPDATE || + srv->phase == BLE_MESH_DFD_PHASE_COMPLETED) { + return BLE_MESH_DFD_SUCCESS; } err = bt_mesh_dfu_cli_apply(&srv->dfu); if (err) { - return BT_MESH_DFD_ERR_INTERNAL; + return BLE_MESH_DFD_ERR_INTERNAL; } - dfd_phase_set(srv, BT_MESH_DFD_PHASE_APPLYING_UPDATE); - return BT_MESH_DFD_SUCCESS; + dfd_phase_set(srv, BLE_MESH_DFD_PHASE_APPLYING_UPDATE); + return BLE_MESH_DFD_SUCCESS; } enum bt_mesh_dfd_status bt_mesh_dfd_srv_fw_delete(struct bt_mesh_dfd_srv *srv, size_t *fwid_len, @@ -1206,38 +1205,38 @@ enum bt_mesh_dfd_status bt_mesh_dfd_srv_fw_delete(struct bt_mesh_dfd_srv *srv, s struct bt_mesh_dfu_slot *slot; int idx, err; - if (srv->phase != BT_MESH_DFD_PHASE_IDLE) { + if (srv->phase != BLE_MESH_DFD_PHASE_IDLE) { *fwid = NULL; *fwid_len = 0; - return BT_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION; + return BLE_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION; } idx = bt_mesh_dfu_slot_get(*fwid, *fwid_len, &slot); if (idx < 0) { - return BT_MESH_DFD_SUCCESS; + return BLE_MESH_DFD_SUCCESS; } err = slot_del(srv, slot); if (err) { *fwid = NULL; *fwid_len = 0; - return BT_MESH_DFD_ERR_INTERNAL; + return BLE_MESH_DFD_ERR_INTERNAL; } else { - return BT_MESH_DFD_SUCCESS; + return BLE_MESH_DFD_SUCCESS; } } enum bt_mesh_dfd_status bt_mesh_dfd_srv_fw_delete_all(struct bt_mesh_dfd_srv *srv) { - if (srv->phase != BT_MESH_DFD_PHASE_IDLE) { - return BT_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION; + if (srv->phase != BLE_MESH_DFD_PHASE_IDLE) { + return BLE_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION; } bt_mesh_dfu_slot_foreach(slot_del_cb, srv); bt_mesh_dfu_slot_del_all(); - return BT_MESH_DFD_SUCCESS; + return BLE_MESH_DFD_SUCCESS; } #ifdef CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD @@ -1248,7 +1247,7 @@ int bt_mesh_dfd_srv_oob_check_complete(struct bt_mesh_dfd_srv *srv, int err; if (slot != srv->upload.slot || !srv->upload.is_oob || - srv->upload.phase == BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE || + srv->upload.phase == BLE_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE || !srv->upload.is_pending_oob_check) { /* This should not happen, unless the application calls the function with a * "wrong" pointer or at a wrong time. @@ -1258,7 +1257,7 @@ int bt_mesh_dfd_srv_oob_check_complete(struct bt_mesh_dfd_srv *srv, srv->upload.is_pending_oob_check = false; - if (status != BT_MESH_DFD_SUCCESS) { + if (status != BLE_MESH_DFD_SUCCESS) { bt_mesh_dfu_slot_release(srv->upload.slot); upload_status_rsp(srv, &srv->upload.oob.ctx, status); return -ECANCELED; @@ -1270,7 +1269,7 @@ int bt_mesh_dfd_srv_oob_check_complete(struct bt_mesh_dfd_srv *srv, return err; } - upload_status_rsp(srv, &srv->upload.oob.ctx, BT_MESH_DFD_SUCCESS); + upload_status_rsp(srv, &srv->upload.oob.ctx, BLE_MESH_DFD_SUCCESS); return 0; } @@ -1280,7 +1279,7 @@ int bt_mesh_dfd_srv_oob_store_complete(struct bt_mesh_dfd_srv *srv, { int err = 0; - if (srv->upload.phase != BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE || + if (srv->upload.phase != BLE_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE || srv->upload.slot != slot || !srv->upload.is_oob) { return -EINVAL; } @@ -1299,11 +1298,11 @@ int bt_mesh_dfd_srv_oob_store_complete(struct bt_mesh_dfd_srv *srv, goto error; } - srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_SUCCESS; + srv->upload.phase = BLE_MESH_DFD_UPLOAD_PHASE_TRANSFER_SUCCESS; return 0; error: - srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ERROR; + srv->upload.phase = BLE_MESH_DFD_UPLOAD_PHASE_TRANSFER_ERROR; bt_mesh_dfu_slot_release(srv->upload.slot); return err; } diff --git a/components/bt/esp_ble_mesh/v1.1/dfu/dfu_cli.c b/components/bt/esp_ble_mesh/v1.1/dfu/dfu_cli.c index 8ce345831d..e5ff20c328 100644 --- a/components/bt/esp_ble_mesh/v1.1/dfu/dfu_cli.c +++ b/components/bt/esp_ble_mesh/v1.1/dfu/dfu_cli.c @@ -105,8 +105,10 @@ static void req_timeout_handler(struct k_work *work) } bt_mesh_dfu_cli_rm_req_from_list(req); + if (req->params) { + bt_mesh_free(req->params); + } req_free(req); - bt_mesh_r_mutex_unlock(&dfu_req_list.op_lock); } @@ -897,7 +899,7 @@ static int handle_status(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx } bt_mesh_dfu_client_cb_evt_to_btc(req->opcode, BTC_BLE_MESH_EVT_DFU_CLIENT_RECV_GET_RSP, req->dfu_cli->mod, &req->ctx, req->params, - sizeof(struct bt_mesh_dfu_metadata_status)); + sizeof(struct bt_mesh_dfu_target_status)); bt_mesh_free(req->params); bt_mesh_dfu_cli_rm_req_from_list(req); k_delayed_work_cancel(&req->timer); diff --git a/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/dfu/dfd.h b/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/dfu/dfd.h index b91ee418e2..a9634ef220 100644 --- a/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/dfu/dfd.h +++ b/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/dfu/dfd.h @@ -12,6 +12,30 @@ 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 @@ -21,96 +45,96 @@ extern "C" { /** Firmware distribution status. */ enum bt_mesh_dfd_status { /** The message was processed successfully. */ - BT_MESH_DFD_SUCCESS, + BLE_MESH_DFD_SUCCESS, /** Insufficient resources on the node. */ - BT_MESH_DFD_ERR_INSUFFICIENT_RESOURCES, + BLE_MESH_DFD_ERR_INSUFFICIENT_RESOURCES, /** The operation cannot be performed while the Server is in the current * phase. */ - BT_MESH_DFD_ERR_WRONG_PHASE, + BLE_MESH_DFD_ERR_WRONG_PHASE, /** An internal error occurred on the node. */ - BT_MESH_DFD_ERR_INTERNAL, + BLE_MESH_DFD_ERR_INTERNAL, /** The requested firmware image is not stored on the Distributor. */ - BT_MESH_DFD_ERR_FW_NOT_FOUND, + BLE_MESH_DFD_ERR_FW_NOT_FOUND, /** The AppKey identified by the AppKey Index is not known to the node. */ - BT_MESH_DFD_ERR_INVALID_APPKEY_INDEX, + BLE_MESH_DFD_ERR_INVALID_APPKEY_INDEX, /** There are no Target nodes in the Distribution Receivers List * state. */ - BT_MESH_DFD_ERR_RECEIVERS_LIST_EMPTY, + BLE_MESH_DFD_ERR_RECEIVERS_LIST_EMPTY, /** Another firmware image distribution is in progress. */ - BT_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION, + BLE_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION, /** Another upload is in progress. */ - BT_MESH_DFD_ERR_BUSY_WITH_UPLOAD, + BLE_MESH_DFD_ERR_BUSY_WITH_UPLOAD, /** The URI scheme name indicated by the Update URI is not supported. */ - BT_MESH_DFD_ERR_URI_NOT_SUPPORTED, + BLE_MESH_DFD_ERR_URI_NOT_SUPPORTED, /** The format of the Update URI is invalid. */ - BT_MESH_DFD_ERR_URI_MALFORMED, + BLE_MESH_DFD_ERR_URI_MALFORMED, /** The URI is currently unreachable. */ - BT_MESH_DFD_ERR_URI_UNREACHABLE, + BLE_MESH_DFD_ERR_URI_UNREACHABLE, /** The Check Firmware OOB procedure did not find any new firmware. */ - BT_MESH_DFD_ERR_NEW_FW_NOT_AVAILABLE, + BLE_MESH_DFD_ERR_NEW_FW_NOT_AVAILABLE, /** The suspension of the Distribute Firmware procedure failed. */ - BT_MESH_DFD_ERR_SUSPEND_FAILED, + BLE_MESH_DFD_ERR_SUSPEND_FAILED, }; /** Firmware distribution phases. */ enum bt_mesh_dfd_phase { /** No firmware distribution is in progress. */ - BT_MESH_DFD_PHASE_IDLE, + BLE_MESH_DFD_PHASE_IDLE, /** Firmware distribution is in progress. */ - BT_MESH_DFD_PHASE_TRANSFER_ACTIVE, + BLE_MESH_DFD_PHASE_TRANSFER_ACTIVE, /** The Transfer BLOB procedure has completed successfully. */ - BT_MESH_DFD_PHASE_TRANSFER_SUCCESS, + BLE_MESH_DFD_PHASE_TRANSFER_SUCCESS, /** The Apply Firmware on Target Nodes procedure is being executed. */ - BT_MESH_DFD_PHASE_APPLYING_UPDATE, + BLE_MESH_DFD_PHASE_APPLYING_UPDATE, /** The Distribute Firmware procedure has completed successfully. */ - BT_MESH_DFD_PHASE_COMPLETED, + BLE_MESH_DFD_PHASE_COMPLETED, /** The Distribute Firmware procedure has failed. */ - BT_MESH_DFD_PHASE_FAILED, + BLE_MESH_DFD_PHASE_FAILED, /** The Cancel Firmware Update procedure is being executed. */ - BT_MESH_DFD_PHASE_CANCELING_UPDATE, + BLE_MESH_DFD_PHASE_CANCELING_UPDATE, /** The Transfer BLOB procedure is suspended. */ - BT_MESH_DFD_PHASE_TRANSFER_SUSPENDED, + BLE_MESH_DFD_PHASE_TRANSFER_SUSPENDED, }; /** Firmware upload phases. */ enum bt_mesh_dfd_upload_phase { /** No firmware upload is in progress. */ - BT_MESH_DFD_UPLOAD_PHASE_IDLE, + BLE_MESH_DFD_UPLOAD_PHASE_IDLE, /** The Store Firmware procedure is being executed. */ - BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE, + BLE_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE, /** The Store Firmware procedure or Store Firmware OOB procedure failed. */ - BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ERROR, + BLE_MESH_DFD_UPLOAD_PHASE_TRANSFER_ERROR, /** The Store Firmware procedure or the Store Firmware OOB procedure * completed successfully. */ - BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_SUCCESS, + BLE_MESH_DFD_UPLOAD_PHASE_TRANSFER_SUCCESS, }; /** @} */ diff --git a/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/dfu/dfd_cli.h b/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/dfu/dfd_cli.h new file mode 100644 index 0000000000..2fa96b0373 --- /dev/null +++ b/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/dfu/dfd_cli.h @@ -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__ */ diff --git a/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/dfu/dfd_srv.h b/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/dfu/dfd_srv.h index fd0223af1c..b494ce775d 100644 --- a/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/dfu/dfd_srv.h +++ b/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/dfu/dfd_srv.h @@ -42,15 +42,14 @@ 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. * - * @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. + * @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) \ { \ @@ -67,10 +66,9 @@ struct bt_mesh_dfd_srv; #endif /* CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD */ /** + * @brief Initialization parameters for the @ref bt_mesh_dfd_srv. * - * @brief Initialization parameters for the @ref bt_mesh_dfd_srv. - * - * @param[in] _cb Pointer to a @ref bt_mesh_dfd_srv_cb instance. + * @param[in] _cb Pointer to a @ref bt_mesh_dfd_srv_cb instance. */ #define BT_MESH_DFD_SRV_INIT(_cb) \ { \ @@ -82,10 +80,9 @@ struct bt_mesh_dfd_srv; } /** + * @brief Firmware Distribution Server model Composition Data entry. * - * @brief Firmware Distribution Server model Composition Data entry. - * - * @param _srv Pointer to a @ref bt_mesh_dfd_srv instance. + * @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), \ @@ -98,15 +95,15 @@ 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. + * 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. + * @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. + * @return 0 on success, or (negative) error code otherwise. */ int (*recv)(struct bt_mesh_dfd_srv *srv, const struct bt_mesh_dfu_slot *slot, @@ -136,7 +133,7 @@ struct bt_mesh_dfd_srv_cb { * available, or to 0 if new firmware is not * available. * - * @return BT_MESH_DFD_SUCCESS on success, or error code otherwise. + * @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, @@ -255,11 +252,11 @@ struct bt_mesh_dfd_srv { * callback has completed or failed. The @p status param should be set to one of the following * values: * - * * @c BT_MESH_DFD_SUCCESS if the check was successful and a new firmware ID was found. - * * @c BT_MESH_DFD_ERR_URI_MALFORMED if the URI is not formatted correctly. - * * @c BT_MESH_DFD_ERR_URI_NOT_SUPPORTED if the URI scheme is not supported by the node. - * * @c BT_MESH_DFD_ERR_URI_UNREACHABLE if the URI can't be reached. - * * @c BT_MESH_DFD_ERR_NEW_FW_NOT_AVAILABLE if the check completes successfully but no new + * * @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 diff --git a/docs/en/api-guides/esp-ble-mesh/ble-mesh-feature-list.rst b/docs/en/api-guides/esp-ble-mesh/ble-mesh-feature-list.rst index feb37fd477..94e7cccfe6 100644 --- a/docs/en/api-guides/esp-ble-mesh/ble-mesh-feature-list.rst +++ b/docs/en/api-guides/esp-ble-mesh/ble-mesh-feature-list.rst @@ -135,11 +135,11 @@ Mesh Models * Device Firmware Update Client models * Firmware Update Client model (Preview) - * Firmware Distribution Client model (coming soon) + * Firmware Distribution Client model (Preview) * Device Firmware Update Server models * Firmware Update Server model (Preview) - * Firmware Distribution Server model (coming soon) + * Firmware Distribution Server model (Preview) Mesh Examples """"""""""""" diff --git a/docs/zh_CN/api-guides/esp-ble-mesh/ble-mesh-feature-list.rst b/docs/zh_CN/api-guides/esp-ble-mesh/ble-mesh-feature-list.rst index 503ddd8058..72f1697b9a 100644 --- a/docs/zh_CN/api-guides/esp-ble-mesh/ble-mesh-feature-list.rst +++ b/docs/zh_CN/api-guides/esp-ble-mesh/ble-mesh-feature-list.rst @@ -135,11 +135,11 @@ Mesh 模型 * 设备固件更新客户端模型 * 固件更新客户端模型(预览) - * 固件分发客户端模型(即将推出) + * 固件分发客户端模型(预览) * 设备固件更新服务器模型 * 固件更新服务器模型(预览) - * 固件分发服务器模型(即将推出) + * 固件分发服务器模型(预览) Mesh 示例 """""""""""