1 /* 2 * Copyright (c) 2020 Nordic Semiconductor ASA 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 /** 8 * @file 9 * @defgroup bt_mesh_dfu_cli Firmware Uppdate Client model 10 * @ingroup bt_mesh_dfu 11 * @{ 12 * @brief API for the Bluetooth mesh Firmware Update Client model 13 */ 14 15 #ifndef ZEPHYR_INCLUDE_BLUETOOTH_MESH_DFU_CLI_H__ 16 #define ZEPHYR_INCLUDE_BLUETOOTH_MESH_DFU_CLI_H__ 17 18 #include <zephyr/bluetooth/mesh/access.h> 19 #include <zephyr/bluetooth/mesh/blob_cli.h> 20 #include <zephyr/bluetooth/mesh/dfu.h> 21 22 #ifdef __cplusplus 23 extern "C" { 24 #endif 25 26 struct bt_mesh_dfu_cli; 27 28 /** 29 * 30 * @brief Initialization parameters for the @ref bt_mesh_dfu_cli. 31 * 32 * @sa bt_mesh_dfu_cli_cb. 33 * 34 * @param _handlers Handler callback structure. 35 */ 36 #define BT_MESH_DFU_CLI_INIT(_handlers) \ 37 { \ 38 .cb = _handlers, \ 39 .blob = { .cb = &_bt_mesh_dfu_cli_blob_handlers }, \ 40 } 41 42 /** 43 * 44 * @brief Firmware Update Client model Composition Data entry. 45 * 46 * @param _cli Pointer to a @ref bt_mesh_dfu_cli instance. 47 */ 48 #define BT_MESH_MODEL_DFU_CLI(_cli) \ 49 BT_MESH_MODEL_BLOB_CLI(&(_cli)->blob), \ 50 BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_DFU_CLI, _bt_mesh_dfu_cli_op, NULL, \ 51 _cli, &_bt_mesh_dfu_cli_cb) 52 53 /** DFU Target node. */ 54 struct bt_mesh_dfu_target { 55 /** BLOB Target node */ 56 struct bt_mesh_blob_target blob; 57 /** Image index on the Target node */ 58 uint8_t img_idx; 59 /** Expected DFU effect, see @ref bt_mesh_dfu_effect. */ 60 uint8_t effect; 61 /** Current DFU status, see @ref bt_mesh_dfu_status. */ 62 uint8_t status; 63 /** Current DFU phase, see @ref bt_mesh_dfu_phase. */ 64 uint8_t phase; 65 }; 66 67 /** Metadata status response. */ 68 struct bt_mesh_dfu_metadata_status { 69 /** Image index. */ 70 uint8_t idx; 71 /** Status code. */ 72 enum bt_mesh_dfu_status status; 73 /** Effect of transfer. */ 74 enum bt_mesh_dfu_effect effect; 75 }; 76 77 /** DFU Target node status parameters. */ 78 struct bt_mesh_dfu_target_status { 79 /** Status of the previous operation. */ 80 enum bt_mesh_dfu_status status; 81 /** Phase of the current DFU transfer. */ 82 enum bt_mesh_dfu_phase phase; 83 /** The effect the update will have on the Target device's state. */ 84 enum bt_mesh_dfu_effect effect; 85 /** BLOB ID used in the transfer. */ 86 uint64_t blob_id; 87 /** Image index to transfer. */ 88 uint8_t img_idx; 89 /** TTL used in the transfer. */ 90 uint8_t ttl; 91 92 /** Additional response time for the Target nodes, in 10-second increments. 93 * 94 * The extra time can be used to give the Target nodes more time to respond 95 * to messages from the Client. The actual timeout will be calculated 96 * according to the following formula: 97 * 98 * @verbatim 99 * timeout = 20 seconds + (10 seconds * timeout_base) + (100 ms * TTL) 100 * @endverbatim 101 * 102 * If a Target node fails to respond to a message from the Client within the 103 * configured transfer timeout, the Target node is dropped. 104 */ 105 uint16_t timeout_base; 106 }; 107 108 /** @brief DFU image callback. 109 * 110 * The image callback is called for every DFU image on the Target node when 111 * calling @ref bt_mesh_dfu_cli_imgs_get. 112 * 113 * @param cli Firmware Update Client model instance. 114 * @param ctx Message context of the received message. 115 * @param idx Image index. 116 * @param total Total number of images on the Target node. 117 * @param img Image information for the given image index. 118 * @param cb_data Callback data. 119 * 120 * @retval BT_MESH_DFU_ITER_STOP Stop iterating through the image list and 121 * return from @ref bt_mesh_dfu_cli_imgs_get. 122 * @retval BT_MESH_DFU_ITER_CONTINUE Continue iterating through the image list 123 * if any images remain. 124 */ 125 typedef enum bt_mesh_dfu_iter (*bt_mesh_dfu_img_cb_t)( 126 struct bt_mesh_dfu_cli *cli, struct bt_mesh_msg_ctx *ctx, uint8_t idx, 127 uint8_t total, const struct bt_mesh_dfu_img *img, void *cb_data); 128 129 /** Firmware Update Client event callbacks. */ 130 struct bt_mesh_dfu_cli_cb { 131 /** @brief BLOB transfer is suspended. 132 * 133 * Called when the BLOB transfer is suspended due to response timeout from all Target nodes. 134 * 135 * @param cli Firmware Update Client model instance. 136 */ 137 void (*suspended)(struct bt_mesh_dfu_cli *cli); 138 139 /** @brief DFU ended. 140 * 141 * Called when the DFU transfer ends, either because all Target nodes were 142 * lost or because the transfer was completed successfully. 143 * 144 * @param cli Firmware Update Client model instance. 145 * @param reason Reason for ending. 146 */ 147 void (*ended)(struct bt_mesh_dfu_cli *cli, 148 enum bt_mesh_dfu_status reason); 149 150 /** @brief DFU transfer applied on all active Target nodes. 151 * 152 * Called at the end of the apply procedure started by @ref 153 * bt_mesh_dfu_cli_apply. 154 * 155 * @param cli Firmware Update Client model instance. 156 */ 157 void (*applied)(struct bt_mesh_dfu_cli *cli); 158 159 /** @brief DFU transfer confirmed on all active Target nodes. 160 * 161 * Called at the end of the apply procedure started by @ref 162 * bt_mesh_dfu_cli_confirm. 163 * 164 * @param cli Firmware Update Client model instance. 165 */ 166 void (*confirmed)(struct bt_mesh_dfu_cli *cli); 167 168 /** @brief DFU Target node was lost. 169 * 170 * A DFU Target node was dropped from the receivers list. The Target node's 171 * @c status is set to reflect the reason for the failure. 172 * 173 * @param cli Firmware Update Client model instance. 174 * @param target DFU Target node that was lost. 175 */ 176 void (*lost_target)(struct bt_mesh_dfu_cli *cli, 177 struct bt_mesh_dfu_target *target); 178 }; 179 180 /** Firmware Update Client model instance. 181 * 182 * Should be initialized with @ref BT_MESH_DFU_CLI_INIT. 183 */ 184 struct bt_mesh_dfu_cli { 185 /** Callback structure. */ 186 const struct bt_mesh_dfu_cli_cb *cb; 187 /** Underlying BLOB Transfer Client. */ 188 struct bt_mesh_blob_cli blob; 189 190 /* runtime state */ 191 192 uint32_t op; 193 struct bt_mesh_model *mod; 194 195 struct { 196 const struct bt_mesh_dfu_slot *slot; 197 const struct bt_mesh_blob_io *io; 198 struct bt_mesh_blob_xfer blob; 199 uint8_t state; 200 uint8_t flags; 201 } xfer; 202 203 struct { 204 uint8_t ttl; 205 uint8_t type; 206 uint8_t img_cnt; 207 uint16_t addr; 208 struct k_sem sem; 209 void *params; 210 bt_mesh_dfu_img_cb_t img_cb; 211 } req; 212 }; 213 214 /** BLOB parameters for Firmware Update Client transfer: */ 215 struct bt_mesh_dfu_cli_xfer_blob_params { 216 /* Logarithmic representation of the block size. */ 217 uint8_t block_size_log; 218 /** Base chunk size. May be smaller for the last chunk. */ 219 uint16_t chunk_size; 220 }; 221 222 /** Firmware Update Client transfer parameters: */ 223 struct bt_mesh_dfu_cli_xfer { 224 /** BLOB ID to use for this transfer, or 0 to set it randomly. */ 225 uint64_t blob_id; 226 /** DFU image slot to transfer. */ 227 const struct bt_mesh_dfu_slot *slot; 228 /** Transfer mode (Push (Push BLOB Transfer Mode) or Pull (Pull BLOB Transfer Mode)) */ 229 enum bt_mesh_blob_xfer_mode mode; 230 /** BLOB parameters to be used for the transfer, or NULL to retrieve Target nodes' 231 * capabilities before sending a firmware. 232 */ 233 const struct bt_mesh_dfu_cli_xfer_blob_params *blob_params; 234 }; 235 236 /** @brief Start distributing a DFU. 237 * 238 * Starts distribution of the firmware in the given slot to the list of DFU 239 * Target nodes in @c ctx. The transfer runs in the background, and its end is 240 * signalled through the @ref bt_mesh_dfu_cli_cb::ended callback. 241 * 242 * @note The BLOB Transfer Client transfer inputs @c targets list must point to a list of @ref 243 * bt_mesh_dfu_target nodes. 244 * 245 * @param cli Firmware Update Client model instance. 246 * @param inputs BLOB Transfer Client transfer inputs. 247 * @param io BLOB stream to read BLOB from. 248 * @param xfer Firmware Update Client transfer parameters. 249 * 250 * @return 0 on success, or (negative) error code otherwise. 251 */ 252 int bt_mesh_dfu_cli_send(struct bt_mesh_dfu_cli *cli, 253 const struct bt_mesh_blob_cli_inputs *inputs, 254 const struct bt_mesh_blob_io *io, 255 const struct bt_mesh_dfu_cli_xfer *xfer); 256 257 /** @brief Suspend a DFU transfer. 258 * 259 * @param cli Firmware Update Client instance. 260 * 261 * @return 0 on success, or (negative) error code otherwise. 262 */ 263 int bt_mesh_dfu_cli_suspend(struct bt_mesh_dfu_cli *cli); 264 265 /** @brief Resume the suspended transfer. 266 * 267 * @param cli Firmware Update Client instance. 268 * 269 * @return 0 on success, or (negative) error code otherwise. 270 */ 271 int bt_mesh_dfu_cli_resume(struct bt_mesh_dfu_cli *cli); 272 273 /** @brief Cancel a DFU transfer. 274 * 275 * Will cancel the ongoing DFU transfer, or the transfer on a specific Target 276 * node if @c ctx is valid. 277 * 278 * @param cli Firmware Update Client model instance. 279 * @param ctx Message context, or NULL to cancel the ongoing DFU transfer. 280 * 281 * @return 0 on success, or (negative) error code otherwise. 282 */ 283 int bt_mesh_dfu_cli_cancel(struct bt_mesh_dfu_cli *cli, 284 struct bt_mesh_msg_ctx *ctx); 285 286 /** @brief Apply the completed DFU transfer. 287 * 288 * A transfer can only be applied after it has ended successfully. The Firmware 289 * Update Client's @c applied callback is called at the end of the apply procedure. 290 * 291 * @param cli Firmware Update Client model instance. 292 * 293 * @return 0 on success, or (negative) error code otherwise. 294 */ 295 int bt_mesh_dfu_cli_apply(struct bt_mesh_dfu_cli *cli); 296 297 /** @brief Confirm that the active transfer has been applied on the Target nodes. 298 * 299 * A transfer can only be confirmed after it has been applied. The Firmware Update 300 * Client's @c confirmed callback is called at the end of the confirm 301 * procedure. 302 * 303 * Target nodes that have reported the effect as @ref BT_MESH_DFU_EFFECT_UNPROV 304 * are expected to not respond to the query, and will fail if they do. 305 * 306 * @param cli Firmware Update Client model instance. 307 * 308 * @return 0 on success, or (negative) error code otherwise. 309 */ 310 int bt_mesh_dfu_cli_confirm(struct bt_mesh_dfu_cli *cli); 311 312 /** @brief Get progress as a percentage of completion. 313 * 314 * @param cli Firmware Update Client model instance. 315 * 316 * @return The progress of the current transfer in percent, or 0 if no 317 * transfer is active. 318 */ 319 uint8_t bt_mesh_dfu_cli_progress(struct bt_mesh_dfu_cli *cli); 320 321 /** @brief Check whether a DFU transfer is in progress. 322 * 323 * @param cli Firmware Update Client model instance. 324 * 325 * @return true if the BLOB Transfer Client is currently participating in a transfer, 326 * false otherwise. 327 */ 328 bool bt_mesh_dfu_cli_is_busy(struct bt_mesh_dfu_cli *cli); 329 330 /** @brief Perform a DFU image list request. 331 * 332 * Requests the full list of DFU images on a Target node, and iterates through 333 * them, calling the @c cb for every image. 334 * 335 * The DFU image list request can be used to determine which image index the 336 * Target node holds its different firmwares in. 337 * 338 * Waits for a response until the procedure timeout expires. 339 * 340 * @param cli Firmware Update Client model instance. 341 * @param ctx Message context. 342 * @param cb Callback to call for each image index. 343 * @param cb_data Callback data to pass to @c cb. 344 * @param max_count Max number of images to return. 345 * 346 * @return 0 on success, or (negative) error code otherwise. 347 */ 348 int bt_mesh_dfu_cli_imgs_get(struct bt_mesh_dfu_cli *cli, 349 struct bt_mesh_msg_ctx *ctx, 350 bt_mesh_dfu_img_cb_t cb, void *cb_data, 351 uint8_t max_count); 352 353 /** @brief Perform a metadata check for the given DFU image slot. 354 * 355 * The metadata check procedure allows the Firmware Update Client to check if a Target 356 * node will accept a transfer of this DFU image slot, and what the effect would be. 357 * 358 * Waits for a response until the procedure timeout expires. 359 * 360 * @param cli Firmware Update Client model instance. 361 * @param ctx Message context. 362 * @param img_idx Target node's image index to check. 363 * @param slot DFU image slot to check for. 364 * @param rsp Metadata status response buffer. 365 * 366 * @return 0 on success, or (negative) error code otherwise. 367 */ 368 int bt_mesh_dfu_cli_metadata_check(struct bt_mesh_dfu_cli *cli, 369 struct bt_mesh_msg_ctx *ctx, uint8_t img_idx, 370 const struct bt_mesh_dfu_slot *slot, 371 struct bt_mesh_dfu_metadata_status *rsp); 372 373 /** @brief Get the status of a Target node. 374 * 375 * @param cli Firmware Update Client model instance. 376 * @param ctx Message context. 377 * @param rsp Response data buffer. 378 * 379 * @return 0 on success, or (negative) error code otherwise. 380 */ 381 int bt_mesh_dfu_cli_status_get(struct bt_mesh_dfu_cli *cli, 382 struct bt_mesh_msg_ctx *ctx, 383 struct bt_mesh_dfu_target_status *rsp); 384 385 /** @brief Get the current procedure timeout value. 386 * 387 * @return The configured procedure timeout. 388 */ 389 int32_t bt_mesh_dfu_cli_timeout_get(void); 390 391 /** @brief Set the procedure timeout value. 392 * 393 * @param timeout The new procedure timeout. 394 */ 395 void bt_mesh_dfu_cli_timeout_set(int32_t timeout); 396 397 /** @cond INTERNAL_HIDDEN */ 398 extern const struct bt_mesh_blob_cli_cb _bt_mesh_dfu_cli_blob_handlers; 399 extern const struct bt_mesh_model_cb _bt_mesh_dfu_cli_cb; 400 extern const struct bt_mesh_model_op _bt_mesh_dfu_cli_op[]; 401 /** @endcond */ 402 403 #ifdef __cplusplus 404 } 405 #endif 406 407 #endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_DFU_CLI_H__ */ 408 409 /** @} */ 410