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