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