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