1 /*
2  * Copyright (c) 2020 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_INCLUDE_BLUETOOTH_MESH_BLOB_H__
8 #define ZEPHYR_INCLUDE_BLUETOOTH_MESH_BLOB_H__
9 
10 #include <sys/types.h>
11 
12 #include <zephyr/kernel.h>
13 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 
18 /**
19  * @defgroup bt_mesh_blob Bluetooth Mesh BLOB model API
20  * @ingroup bt_mesh
21  * @{
22  */
23 
24 #ifndef CONFIG_BT_MESH_BLOB_CHUNK_COUNT_MAX
25 #define CONFIG_BT_MESH_BLOB_CHUNK_COUNT_MAX 0
26 #endif
27 
28 /** BLOB transfer mode. */
29 enum bt_mesh_blob_xfer_mode {
30 	/** No valid transfer mode. */
31 	BT_MESH_BLOB_XFER_MODE_NONE,
32 	/** Push mode (Push BLOB Transfer Mode). */
33 	BT_MESH_BLOB_XFER_MODE_PUSH,
34 	/** Pull mode (Pull BLOB Transfer Mode). */
35 	BT_MESH_BLOB_XFER_MODE_PULL,
36 	/** Both modes are valid. */
37 	BT_MESH_BLOB_XFER_MODE_ALL,
38 };
39 
40 /** Transfer phase. */
41 enum bt_mesh_blob_xfer_phase {
42 	/** The BLOB Transfer Server is awaiting configuration. */
43 	BT_MESH_BLOB_XFER_PHASE_INACTIVE,
44 	/** The BLOB Transfer Server is ready to receive a BLOB transfer. */
45 	BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_START,
46 	/** The BLOB Transfer Server is waiting for the next block of data. */
47 	BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_BLOCK,
48 	/** The BLOB Transfer Server is waiting for the next chunk of data. */
49 	BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_CHUNK,
50 	/** The BLOB was transferred successfully. */
51 	BT_MESH_BLOB_XFER_PHASE_COMPLETE,
52 	/** The BLOB transfer is paused. */
53 	BT_MESH_BLOB_XFER_PHASE_SUSPENDED,
54 };
55 
56 /** BLOB model status codes. */
57 enum bt_mesh_blob_status {
58 	/** The message was processed successfully. */
59 	BT_MESH_BLOB_SUCCESS,
60 	/** The Block Number field value is not within the range of blocks being
61 	 *  transferred.
62 	 */
63 	BT_MESH_BLOB_ERR_INVALID_BLOCK_NUM,
64 	/** The block size is smaller than the size indicated by the Min Block
65 	 *  Size Log state or is larger than the size indicated by the Max Block
66 	 *  Size Log state.
67 	 */
68 	BT_MESH_BLOB_ERR_INVALID_BLOCK_SIZE,
69 	/** The chunk size exceeds the size indicated by the Max Chunk Size
70 	 *  state, or the number of chunks exceeds the number specified by the
71 	 *  Max Total Chunks state.
72 	 */
73 	BT_MESH_BLOB_ERR_INVALID_CHUNK_SIZE,
74 	/** The operation cannot be performed while the server is in the current
75 	 *  phase.
76 	 */
77 	BT_MESH_BLOB_ERR_WRONG_PHASE,
78 	/** A parameter value in the message cannot be accepted. */
79 	BT_MESH_BLOB_ERR_INVALID_PARAM,
80 	/** The message contains a BLOB ID value that is not expected. */
81 	BT_MESH_BLOB_ERR_WRONG_BLOB_ID,
82 	/** There is not enough space available in memory to receive the BLOB.
83 	 */
84 	BT_MESH_BLOB_ERR_BLOB_TOO_LARGE,
85 	/** The transfer mode is not supported by the BLOB Transfer Server
86 	 *  model.
87 	 */
88 	BT_MESH_BLOB_ERR_UNSUPPORTED_MODE,
89 	/** An internal error occurred on the node. */
90 	BT_MESH_BLOB_ERR_INTERNAL,
91 	/** The requested information cannot be provided while the server is in
92 	 *  the current phase.
93 	 */
94 	BT_MESH_BLOB_ERR_INFO_UNAVAILABLE,
95 };
96 
97 /** BLOB transfer data block. */
98 struct bt_mesh_blob_block {
99 	/** Block size in bytes */
100 	size_t size;
101 	/** Offset in bytes from the start of the BLOB. */
102 	off_t offset;
103 	/** Block number */
104 	uint16_t number;
105 	/** Number of chunks in block. */
106 	uint16_t chunk_count;
107 	/** Bitmap of missing chunks. */
108 	uint8_t missing[DIV_ROUND_UP(CONFIG_BT_MESH_BLOB_CHUNK_COUNT_MAX,
109 					 8)];
110 };
111 
112 /** BLOB data chunk. */
113 struct bt_mesh_blob_chunk {
114 	/** Offset of the chunk data from the start of the block. */
115 	off_t offset;
116 	/** Chunk data size. */
117 	size_t size;
118 	/** Chunk data. */
119 	uint8_t *data;
120 };
121 
122 /** BLOB transfer. */
123 struct bt_mesh_blob_xfer {
124 	/** BLOB ID. */
125 	uint64_t id;
126 	/** Total BLOB size in bytes. */
127 	size_t size;
128 	/** BLOB transfer mode. */
129 	enum bt_mesh_blob_xfer_mode mode;
130 	/* Logarithmic representation of the block size. */
131 	uint8_t block_size_log;
132 	/** Base chunk size. May be smaller for the last chunk. */
133 	uint16_t chunk_size;
134 };
135 
136 /** BLOB stream interaction mode. */
137 enum bt_mesh_blob_io_mode {
138 	/** Read data from the stream. */
139 	BT_MESH_BLOB_READ,
140 	/** Write data to the stream. */
141 	BT_MESH_BLOB_WRITE,
142 };
143 
144 /** BLOB stream. */
145 struct bt_mesh_blob_io {
146 	/** @brief Open callback.
147 	 *
148 	 *  Called when the reader is opened for reading.
149 	 *
150 	 *  @param io   BLOB stream.
151 	 *  @param xfer BLOB transfer.
152 	 *  @param mode Direction of the stream (read/write).
153 	 *
154 	 *  @return 0 on success, or (negative) error code otherwise.
155 	 */
156 	int (*open)(const struct bt_mesh_blob_io *io,
157 		    const struct bt_mesh_blob_xfer *xfer,
158 		    enum bt_mesh_blob_io_mode mode);
159 
160 	/** @brief Close callback.
161 	 *
162 	 *  Called when the reader is closed.
163 	 *
164 	 *  @param io   BLOB stream.
165 	 *  @param xfer BLOB transfer.
166 	 */
167 	void (*close)(const struct bt_mesh_blob_io *io,
168 		      const struct bt_mesh_blob_xfer *xfer);
169 
170 	/** @brief Block start callback.
171 	 *
172 	 *  Called when a new block is opened for sending. Each block is only
173 	 *  sent once, and are always sent in increasing order. The data chunks
174 	 *  inside a single block may be requested out of order and multiple
175 	 *  times.
176 	 *
177 	 *  @param io    BLOB stream.
178 	 *  @param xfer  BLOB transfer.
179 	 *  @param block Block that was started.
180 	 */
181 	int (*block_start)(const struct bt_mesh_blob_io *io,
182 			   const struct bt_mesh_blob_xfer *xfer,
183 			   const struct bt_mesh_blob_block *block);
184 
185 	/** @brief Block end callback.
186 	 *
187 	 *  Called when the current block has been transmitted in full.
188 	 *  No data from this block will be requested again, and the application
189 	 *  data associated with this block may be discarded.
190 	 *
191 	 *  @param io    BLOB stream.
192 	 *  @param xfer  BLOB transfer.
193 	 *  @param block Block that finished sending.
194 	 */
195 	void (*block_end)(const struct bt_mesh_blob_io *io,
196 			  const struct bt_mesh_blob_xfer *xfer,
197 			  const struct bt_mesh_blob_block *block);
198 
199 	/** @brief Chunk data write callback.
200 	 *
201 	 *  Used by the BLOB Transfer Server on incoming data.
202 	 *
203 	 *  Each block is divided into chunks of data. This callback is called
204 	 *  when a new chunk of data is received. Chunks may be received in
205 	 *  any order within their block.
206 	 *
207 	 *  If the callback returns successfully, this chunk will be marked as
208 	 *  received, and will not be received again unless the block is
209 	 *  restarted due to a transfer suspension. If the callback returns a
210 	 *  non-zero value, the chunk remains unreceived, and the BLOB Transfer
211 	 *  Client will attempt to resend it later.
212 	 *
213 	 *  Note that the Client will only perform a limited number of attempts
214 	 *  at delivering a chunk before dropping a Target node from the transfer.
215 	 *  The number of retries performed by the Client is implementation
216 	 *  specific.
217 	 *
218 	 *  @param io    BLOB stream.
219 	 *  @param xfer  BLOB transfer.
220 	 *  @param block Block the chunk is part of.
221 	 *  @param chunk Received chunk.
222 	 *
223 	 *  @return 0 on success, or (negative) error code otherwise.
224 	 */
225 	int (*wr)(const struct bt_mesh_blob_io *io,
226 		  const struct bt_mesh_blob_xfer *xfer,
227 		  const struct bt_mesh_blob_block *block,
228 		  const struct bt_mesh_blob_chunk *chunk);
229 
230 	/** @brief Chunk data read callback.
231 	 *
232 	 *  Used by the BLOB Transfer Client to fetch outgoing data.
233 	 *
234 	 *  The Client calls the chunk data request callback to populate a chunk
235 	 *  message going out to the Target nodes. The data request callback
236 	 *  may be called out of order and multiple times for each offset, and
237 	 *  cannot be used as an indication of progress.
238 	 *
239 	 *  Returning a non-zero status code on the chunk data request callback
240 	 *  results in termination of the transfer.
241 	 *
242 	 *  @param io    BLOB stream.
243 	 *  @param xfer  BLOB transfer.
244 	 *  @param block Block the chunk is part of.
245 	 *  @param chunk Chunk to get the data of. The buffer pointer to by the
246 	 *               @c data member should be filled by the callback.
247 	 *
248 	 *  @return 0 on success, or (negative) error code otherwise.
249 	 */
250 	int (*rd)(const struct bt_mesh_blob_io *io,
251 		  const struct bt_mesh_blob_xfer *xfer,
252 		  const struct bt_mesh_blob_block *block,
253 		  const struct bt_mesh_blob_chunk *chunk);
254 };
255 
256 /** @} */
257 
258 #ifdef __cplusplus
259 }
260 #endif
261 
262 #endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_BLOB_H__ */
263