Line data Source code
1 0 : /*
2 : * Copyright (c) 2020 Nordic Semiconductor ASA
3 : *
4 : * SPDX-License-Identifier: Apache-2.0
5 : */
6 :
7 : #ifndef ZEPHYR_INCLUDE_BLUETOOTH_MESH_BLOB_CLI_H_
8 : #define ZEPHYR_INCLUDE_BLUETOOTH_MESH_BLOB_CLI_H_
9 :
10 : #include <sys/types.h>
11 :
12 : #include <zephyr/bluetooth/mesh/access.h>
13 : #include <zephyr/bluetooth/mesh/blob.h>
14 :
15 : #ifdef __cplusplus
16 : extern "C" {
17 : #endif
18 :
19 : /**
20 : * @defgroup bt_mesh_blob_cli Bluetooth Mesh BLOB Transfer Client model API
21 : * @ingroup bt_mesh
22 : * @{
23 : */
24 :
25 : struct bt_mesh_blob_cli;
26 :
27 : /**
28 : *
29 : * @brief BLOB Transfer Client model Composition Data entry.
30 : *
31 : * @param _cli Pointer to a @ref bt_mesh_blob_cli instance.
32 : */
33 1 : #define BT_MESH_MODEL_BLOB_CLI(_cli) \
34 : BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_BLOB_CLI, _bt_mesh_blob_cli_op, \
35 : NULL, _cli, &_bt_mesh_blob_cli_cb)
36 :
37 : /** Target node's Pull mode (Pull BLOB Transfer Mode) context used
38 : * while sending chunks to the Target node.
39 : */
40 1 : struct bt_mesh_blob_target_pull {
41 : /** Timestamp when the Block Report Timeout Timer expires for this Target node. */
42 1 : int64_t block_report_timestamp;
43 :
44 : /** Missing chunks reported by this Target node. */
45 1 : uint8_t missing[DIV_ROUND_UP(CONFIG_BT_MESH_BLOB_CHUNK_COUNT_MAX, 8)];
46 : };
47 :
48 : /** BLOB Transfer Client Target node. */
49 1 : struct bt_mesh_blob_target {
50 : /** Linked list node */
51 1 : sys_snode_t n;
52 :
53 : /** Target node address. */
54 1 : uint16_t addr;
55 :
56 : /** Target node's Pull mode context.
57 : * Needs to be initialized when sending a BLOB in Pull mode.
58 : */
59 1 : struct bt_mesh_blob_target_pull *pull;
60 :
61 : /** BLOB transfer status, see @ref bt_mesh_blob_status. */
62 1 : uint8_t status;
63 :
64 0 : uint8_t procedure_complete:1, /* Procedure has been completed. */
65 0 : acked:1, /* Message has been acknowledged. Not used when sending. */
66 0 : timedout:1, /* Target node didn't respond after specified timeout. */
67 0 : skip:1; /* Skip Target node from broadcast. */
68 : };
69 :
70 : /** BLOB transfer information.
71 : *
72 : * If @c phase is @ref BT_MESH_BLOB_XFER_PHASE_INACTIVE,
73 : * the fields below @c phase are not initialized.
74 : * If @c phase is @ref BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_START,
75 : * the fields below @c id are not initialized.
76 : */
77 1 : struct bt_mesh_blob_xfer_info {
78 : /** BLOB transfer status. */
79 1 : enum bt_mesh_blob_status status;
80 :
81 : /** BLOB transfer mode. */
82 1 : enum bt_mesh_blob_xfer_mode mode;
83 :
84 : /** BLOB transfer phase. */
85 1 : enum bt_mesh_blob_xfer_phase phase;
86 :
87 : /** BLOB ID. */
88 1 : uint64_t id;
89 :
90 : /** BLOB size in octets. */
91 1 : uint32_t size;
92 :
93 : /** Logarithmic representation of the block size. */
94 1 : uint8_t block_size_log;
95 :
96 : /** MTU size in octets. */
97 1 : uint16_t mtu_size;
98 :
99 : /** Bit field indicating blocks that were not received. */
100 1 : const uint8_t *missing_blocks;
101 : };
102 :
103 : /** BLOB Transfer Client transfer inputs. */
104 1 : struct bt_mesh_blob_cli_inputs {
105 : /** Linked list of Target nodes. Each node should point to @ref
106 : * bt_mesh_blob_target::n.
107 : */
108 1 : sys_slist_t targets;
109 :
110 : /** AppKey index to send with. */
111 1 : uint16_t app_idx;
112 :
113 : /** Group address destination for the BLOB transfer, or @ref
114 : * BT_MESH_ADDR_UNASSIGNED to send every message to each Target
115 : * node individually.
116 : */
117 1 : uint16_t group;
118 :
119 : /** Time to live value of BLOB transfer messages. */
120 1 : uint8_t ttl;
121 :
122 : /** Additional response time for the Target nodes, in 10-second increments.
123 : *
124 : * The extra time can be used to give the Target nodes more time to respond
125 : * to messages from the Client. The actual timeout will be calculated
126 : * according to the following formula:
127 : *
128 : * @verbatim
129 : * timeout = 20 seconds + (10 seconds * timeout_base) + (100 ms * TTL)
130 : * @endverbatim
131 : *
132 : * If a Target node fails to respond to a message from the Client within the
133 : * configured transfer timeout, the Target node is dropped.
134 : */
135 1 : uint16_t timeout_base;
136 : };
137 :
138 : /** Transfer capabilities of a Target node. */
139 1 : struct bt_mesh_blob_cli_caps {
140 : /** Max BLOB size. */
141 1 : size_t max_size;
142 :
143 : /** Logarithmic representation of the minimum block size. */
144 1 : uint8_t min_block_size_log;
145 :
146 : /** Logarithmic representation of the maximum block size. */
147 1 : uint8_t max_block_size_log;
148 :
149 : /** Max number of chunks per block. */
150 1 : uint16_t max_chunks;
151 :
152 : /** Max chunk size. */
153 1 : uint16_t max_chunk_size;
154 :
155 : /** Max MTU size. */
156 1 : uint16_t mtu_size;
157 :
158 : /** Supported transfer modes. */
159 1 : enum bt_mesh_blob_xfer_mode modes;
160 : };
161 :
162 : /** BLOB Transfer Client state. */
163 1 : enum bt_mesh_blob_cli_state {
164 : /** No transfer is active. */
165 : BT_MESH_BLOB_CLI_STATE_NONE,
166 : /** Retrieving transfer capabilities. */
167 : BT_MESH_BLOB_CLI_STATE_CAPS_GET,
168 : /** Sending transfer start. */
169 : BT_MESH_BLOB_CLI_STATE_START,
170 : /** Sending block start. */
171 : BT_MESH_BLOB_CLI_STATE_BLOCK_START,
172 : /** Sending block chunks. */
173 : BT_MESH_BLOB_CLI_STATE_BLOCK_SEND,
174 : /** Checking block status. */
175 : BT_MESH_BLOB_CLI_STATE_BLOCK_CHECK,
176 : /** Checking transfer status. */
177 : BT_MESH_BLOB_CLI_STATE_XFER_CHECK,
178 : /** Cancelling transfer. */
179 : BT_MESH_BLOB_CLI_STATE_CANCEL,
180 : /** Transfer is suspended. */
181 : BT_MESH_BLOB_CLI_STATE_SUSPENDED,
182 : /** Checking transfer progress. */
183 : BT_MESH_BLOB_CLI_STATE_XFER_PROGRESS_GET,
184 : };
185 :
186 : /** Event handler callbacks for the BLOB Transfer Client model.
187 : *
188 : * All handlers are optional.
189 : */
190 1 : struct bt_mesh_blob_cli_cb {
191 : /** @brief Capabilities retrieval completion callback.
192 : *
193 : * Called when the capabilities retrieval procedure completes, indicating that
194 : * a common set of acceptable transfer parameters have been established
195 : * for the given list of Target nodes. All compatible Target nodes have
196 : * status code @ref BT_MESH_BLOB_SUCCESS.
197 : *
198 : * @param cli BLOB Transfer Client instance.
199 : * @param caps Safe transfer capabilities if the transfer capabilities
200 : * of at least one Target node has satisfied the Client, or NULL otherwise.
201 : */
202 1 : void (*caps)(struct bt_mesh_blob_cli *cli,
203 : const struct bt_mesh_blob_cli_caps *caps);
204 :
205 : /** @brief Target node loss callback.
206 : *
207 : * Called whenever a Target node has been lost due to some error in the
208 : * transfer. Losing a Target node is not considered a fatal error for
209 : * the Client until all Target nodes have been lost.
210 : *
211 : * @param cli BLOB Transfer Client instance.
212 : * @param target Target node that was lost.
213 : * @param reason Reason for the Target node loss.
214 : */
215 1 : void (*lost_target)(struct bt_mesh_blob_cli *cli,
216 : struct bt_mesh_blob_target *target,
217 : enum bt_mesh_blob_status reason);
218 :
219 : /** @brief Transfer is suspended.
220 : *
221 : * Called when the transfer is suspended due to response timeout from all Target nodes.
222 : *
223 : * @param cli BLOB Transfer Client instance.
224 : */
225 1 : void (*suspended)(struct bt_mesh_blob_cli *cli);
226 :
227 : /** @brief Transfer end callback.
228 : *
229 : * Called when the transfer ends.
230 : *
231 : * @param cli BLOB Transfer Client instance.
232 : * @param xfer Completed transfer.
233 : * @param success Status of the transfer.
234 : * Is @c true if at least one Target
235 : * node received the whole transfer.
236 : */
237 1 : void (*end)(struct bt_mesh_blob_cli *cli,
238 : const struct bt_mesh_blob_xfer *xfer, bool success);
239 :
240 : /** @brief Transfer progress callback
241 : *
242 : * The content of @c info is invalidated upon exit from the callback.
243 : * Therefore it needs to be copied if it is planned to be used later.
244 : *
245 : * @param cli BLOB Transfer Client instance.
246 : * @param target Target node that responded to the request.
247 : * @param info BLOB transfer information.
248 : */
249 1 : void (*xfer_progress)(struct bt_mesh_blob_cli *cli,
250 : struct bt_mesh_blob_target *target,
251 : const struct bt_mesh_blob_xfer_info *info);
252 :
253 : /** @brief End of Get Transfer Progress procedure.
254 : *
255 : * Called when all Target nodes have responded or the procedure timed-out.
256 : *
257 : * @param cli BLOB Transfer Client instance.
258 : */
259 1 : void (*xfer_progress_complete)(struct bt_mesh_blob_cli *cli);
260 : };
261 :
262 : /** @cond INTERNAL_HIDDEN */
263 : struct blob_cli_broadcast_ctx {
264 : /** Called for every Target node in unicast mode, or once in case of multicast mode. */
265 : void (*send)(struct bt_mesh_blob_cli *cli, uint16_t dst);
266 : /** Called after every @ref blob_cli_broadcast_ctx::send callback. */
267 : void (*send_complete)(struct bt_mesh_blob_cli *cli, uint16_t dst);
268 : /** If @ref blob_cli_broadcast_ctx::acked is true, called after all Target nodes
269 : * have confirmed reception by @ref blob_cli_broadcast_rsp. Otherwise, called
270 : * after transmission has been completed.
271 : */
272 : void (*next)(struct bt_mesh_blob_cli *cli);
273 : /** If true, every transmission needs to be confirmed by @ref blob_cli_broadcast_rsp before
274 : * @ref blob_cli_broadcast_ctx::next is called.
275 : */
276 : bool acked;
277 : /** If true, the message is always sent in a unicast way. */
278 : bool force_unicast;
279 : /** If true, non-responsive Target nodes won't be dropped after transfer has timed out. */
280 : bool optional;
281 : /** Set to true by the BLOB Transfer Client between blob_cli_broadcast
282 : * and broadcast_complete calls.
283 : */
284 : bool is_inited;
285 : /* Defines a time in ms by which the broadcast API postpones sending the message to a next
286 : * target or completing the broadcast.
287 : */
288 : uint32_t post_send_delay_ms;
289 : };
290 : /** INTERNAL_HIDDEN @endcond */
291 :
292 : /** BLOB Transfer Client model instance. */
293 1 : struct bt_mesh_blob_cli {
294 : /** Event handler callbacks */
295 1 : const struct bt_mesh_blob_cli_cb *cb;
296 :
297 : /* Runtime state */
298 0 : const struct bt_mesh_model *mod;
299 :
300 : struct {
301 0 : struct bt_mesh_blob_target *target;
302 0 : struct blob_cli_broadcast_ctx ctx;
303 0 : struct k_work_delayable retry;
304 : /* Represents Client Timeout timer in a timestamp. Used in Pull mode only. */
305 0 : int64_t cli_timestamp;
306 0 : struct k_work_delayable complete;
307 0 : uint16_t pending;
308 0 : uint8_t retries;
309 0 : uint8_t sending : 1,
310 0 : cancelled : 1;
311 0 : } tx;
312 :
313 0 : const struct bt_mesh_blob_io *io;
314 0 : const struct bt_mesh_blob_cli_inputs *inputs;
315 0 : const struct bt_mesh_blob_xfer *xfer;
316 0 : uint32_t chunk_interval_ms;
317 0 : uint16_t block_count;
318 0 : uint16_t chunk_idx;
319 0 : uint16_t mtu_size;
320 0 : enum bt_mesh_blob_cli_state state;
321 0 : struct bt_mesh_blob_block block;
322 0 : struct bt_mesh_blob_cli_caps caps;
323 : };
324 :
325 : /** @brief Retrieve transfer capabilities for a list of Target nodes.
326 : *
327 : * Queries the availability and capabilities of all Target nodes, producing a
328 : * cumulative set of transfer capabilities for the Target nodes, and returning
329 : * it through the @ref bt_mesh_blob_cli_cb::caps callback.
330 : *
331 : * Retrieving the capabilities may take several seconds, depending on the
332 : * number of Target nodes and mesh network performance. The end of the procedure
333 : * is indicated through the @ref bt_mesh_blob_cli_cb::caps callback.
334 : *
335 : * This procedure is not required, but strongly recommended as a
336 : * preparation for a transfer to maximize performance and the chances of
337 : * success.
338 : *
339 : * @param cli BLOB Transfer Client instance.
340 : * @param inputs Statically allocated BLOB Transfer Client transfer inputs.
341 : *
342 : * @return 0 on success, or (negative) error code otherwise.
343 : */
344 1 : int bt_mesh_blob_cli_caps_get(struct bt_mesh_blob_cli *cli,
345 : const struct bt_mesh_blob_cli_inputs *inputs);
346 :
347 : /** @brief Perform a BLOB transfer.
348 : *
349 : * Starts sending the transfer to the Target nodes. Only Target nodes with a
350 : * @c status of @ref BT_MESH_BLOB_SUCCESS will be considered.
351 : *
352 : * The transfer will keep going either until all Target nodes have been dropped, or
353 : * the full BLOB has been sent.
354 : *
355 : * The BLOB transfer may take several minutes, depending on the number of
356 : * Target nodes, size of the BLOB and mesh network performance. The end of the
357 : * transfer is indicated through the @ref bt_mesh_blob_cli_cb::end callback.
358 : *
359 : * A Client only supports one transfer at the time.
360 : *
361 : * @param cli BLOB Transfer Client instance.
362 : * @param inputs Statically allocated BLOB Transfer Client transfer inputs.
363 : * @param xfer Statically allocated transfer parameters.
364 : * @param io BLOB stream to read the transfer from.
365 : *
366 : * @return 0 on success, or (negative) error code otherwise.
367 : */
368 1 : int bt_mesh_blob_cli_send(struct bt_mesh_blob_cli *cli,
369 : const struct bt_mesh_blob_cli_inputs *inputs,
370 : const struct bt_mesh_blob_xfer *xfer,
371 : const struct bt_mesh_blob_io *io);
372 :
373 : /** @brief Suspend the active transfer.
374 : *
375 : * @param cli BLOB Transfer Client instance.
376 : *
377 : * @return 0 on success, or (negative) error code otherwise.
378 : */
379 1 : int bt_mesh_blob_cli_suspend(struct bt_mesh_blob_cli *cli);
380 :
381 : /** @brief Resume the suspended transfer.
382 : *
383 : * @param cli BLOB Transfer Client instance.
384 : *
385 : * @return 0 on success, or (negative) error code otherwise.
386 : */
387 1 : int bt_mesh_blob_cli_resume(struct bt_mesh_blob_cli *cli);
388 :
389 : /** @brief Cancel an ongoing transfer.
390 : *
391 : * @param cli BLOB Transfer Client instance.
392 : */
393 1 : void bt_mesh_blob_cli_cancel(struct bt_mesh_blob_cli *cli);
394 :
395 : /** @brief Get the progress of BLOB transfer.
396 : *
397 : * This function can only be used if the BLOB Transfer Client is currently
398 : * not performing a BLOB transfer.
399 : * To get progress of the active BLOB transfer, use the
400 : * @ref bt_mesh_blob_cli_xfer_progress_active_get function.
401 : *
402 : * @param cli BLOB Transfer Client instance.
403 : * @param inputs Statically allocated BLOB Transfer Client transfer inputs.
404 : *
405 : * @return 0 on success, or (negative) error code otherwise.
406 : */
407 1 : int bt_mesh_blob_cli_xfer_progress_get(struct bt_mesh_blob_cli *cli,
408 : const struct bt_mesh_blob_cli_inputs *inputs);
409 :
410 : /** @brief Get the current progress of the active transfer in percent.
411 : *
412 : * @param cli BLOB Transfer Client instance.
413 : *
414 : * @return The current transfer progress, or 0 if no transfer is active.
415 : */
416 1 : uint8_t bt_mesh_blob_cli_xfer_progress_active_get(struct bt_mesh_blob_cli *cli);
417 :
418 : /** @brief Get the current state of the BLOB Transfer Client.
419 : *
420 : * @param cli BLOB Transfer Client instance.
421 : *
422 : * @return true if the BLOB Transfer Client is currently participating in a transfer or
423 : * retrieving the capabilities and false otherwise.
424 : */
425 1 : bool bt_mesh_blob_cli_is_busy(struct bt_mesh_blob_cli *cli);
426 :
427 : /** @brief Set chunk sending interval in ms
428 : *
429 : * This function is optional, and can be used to define how fast chunks are sent in the BLOB Client
430 : * Model.
431 : * Without an added delay, for example a Bluetooth Mesh DFU can cause network blockage by
432 : * constantly sending the next chunks, especially if the chunks are sent to group addresses or
433 : * multiple unicast addresses.
434 : *
435 : * @note: Big intervals may cause timeouts. Increasing the @c timeout_base accordingly can
436 : * circumvent this.
437 : *
438 : * @param cli BLOB Transfer Client instance.
439 : * @param interval_ms the delay before each chunk is sent out in ms.
440 : */
441 1 : void bt_mesh_blob_cli_set_chunk_interval_ms(struct bt_mesh_blob_cli *cli, uint32_t interval_ms);
442 :
443 : /** @cond INTERNAL_HIDDEN */
444 : extern const struct bt_mesh_model_op _bt_mesh_blob_cli_op[];
445 : extern const struct bt_mesh_model_cb _bt_mesh_blob_cli_cb;
446 : /** @endcond */
447 :
448 : /** @} */
449 :
450 : #ifdef __cplusplus
451 : }
452 : #endif
453 :
454 : #endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_BLOB_CLI_H_ */
|