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_SRV_H_
8 #define ZEPHYR_INCLUDE_BLUETOOTH_MESH_BLOB_SRV_H_
9 
10 #include <zephyr/bluetooth/mesh/access.h>
11 #include <zephyr/bluetooth/mesh/blob.h>
12 
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
16 
17 /**
18  * @defgroup bt_mesh_blob_srv Bluetooth Mesh BLOB Transfer Server model API
19  * @ingroup bt_mesh
20  * @{
21  */
22 
23 struct bt_mesh_blob_srv;
24 
25 /**
26  *
27  *  @brief Max number of blocks in a single transfer.
28  */
29 #if defined(CONFIG_BT_MESH_BLOB_SRV)
30 #define BT_MESH_BLOB_BLOCKS_MAX                                                \
31 	(DIV_ROUND_UP(CONFIG_BT_MESH_BLOB_SIZE_MAX,                        \
32 			  CONFIG_BT_MESH_BLOB_BLOCK_SIZE_MIN))
33 #else
34 #define BT_MESH_BLOB_BLOCKS_MAX 1
35 #endif
36 
37 /**
38  *
39  *  @brief BLOB Transfer Server model composition data entry.
40  *
41  *  @param _srv Pointer to a @ref bt_mesh_blob_srv instance.
42  */
43 #define BT_MESH_MODEL_BLOB_SRV(_srv)                                           \
44 	BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_BLOB_SRV, _bt_mesh_blob_srv_op,      \
45 			 NULL, _srv, &_bt_mesh_blob_srv_cb)
46 
47 /** @brief BLOB Transfer Server model event handlers.
48  *
49  *  All callbacks are optional.
50  */
51 struct bt_mesh_blob_srv_cb {
52 	/** @brief Transfer start callback.
53 	 *
54 	 *  Called when the transfer has started with the prepared BLOB ID.
55 	 *
56 	 *  @param srv  BLOB Transfer Server instance.
57 	 *  @param ctx  Message context for the incoming start message. The
58 	 *              entire transfer will be sent from the same source
59 	 *              address.
60 	 *  @param xfer Transfer parameters.
61 	 *
62 	 *  @return 0 on success, or (negative) error code to reject the
63 	 *          transfer.
64 	 */
65 	int (*start)(struct bt_mesh_blob_srv *srv, struct bt_mesh_msg_ctx *ctx,
66 		     struct bt_mesh_blob_xfer *xfer);
67 
68 	/** @brief Transfer end callback.
69 	 *
70 	 *  Called when the transfer ends, either because it was cancelled, or
71 	 *  because it finished successfully. A new transfer may be prepared.
72 	 *
73 	 *  @note The transfer may end before it's started if the start
74 	 *        parameters are invalid.
75 	 *
76 	 *  @param srv     BLOB Transfer Server instance.
77 	 *  @param id      BLOB ID of the cancelled transfer.
78 	 *  @param success Whether the transfer was successful.
79 	 */
80 	void (*end)(struct bt_mesh_blob_srv *srv, uint64_t id, bool success);
81 
82 	/** @brief Transfer suspended callback.
83 	 *
84 	 *  Called if the Server timed out while waiting for a transfer packet.
85 	 *  A suspended transfer may resume later from the start of the current
86 	 *  block. Any received chunks in the current block should be discarded,
87 	 *  they will be received again if the transfer resumes.
88 	 *
89 	 *  The transfer will call @c resumed again when resuming.
90 	 *
91 	 *  @note The BLOB Transfer Server does not run a timer in the suspended state,
92 	 *        and it's up to the application to determine whether the
93 	 *        transfer should be permanently cancelled. Without interaction,
94 	 *        the transfer will be suspended indefinitely, and the BLOB Transfer
95 	 *        Server will not accept any new transfers.
96 	 *
97 	 *  @param srv BLOB Transfer Server instance.
98 	 */
99 	void (*suspended)(struct bt_mesh_blob_srv *srv);
100 
101 	/** @brief Transfer resume callback.
102 	 *
103 	 *  Called if the transfer is resumed after being suspended.
104 	 *
105 	 *  @param srv BLOB Transfer Server instance.
106 	 */
107 	void (*resume)(struct bt_mesh_blob_srv *srv);
108 
109 	/** @brief Transfer recovery callback.
110 	 *
111 	 *  Called when the Bluetooth mesh subsystem is started if the device is rebooted
112 	 *  in the middle of a transfer.
113 	 *
114 	 *  Transfers will not be resumed after a reboot if this callback is not
115 	 *  defined.
116 	 *
117 	 *  @param srv  BLOB Transfer Server instance.
118 	 *  @param xfer Transfer to resume.
119 	 *  @param io   BLOB stream return parameter. Must be set to a valid
120 	 *              BLOB stream by the callback.
121 	 *
122 	 *  @return 0 on success, or (negative) error code to abandon the
123 	 *          transfer.
124 	 */
125 	int (*recover)(struct bt_mesh_blob_srv *srv,
126 		       struct bt_mesh_blob_xfer *xfer,
127 		       const struct bt_mesh_blob_io **io);
128 };
129 
130 /** @brief BLOB Transfer Server instance. */
131 struct bt_mesh_blob_srv {
132 	/** Event handler callbacks. */
133 	const struct bt_mesh_blob_srv_cb *cb;
134 
135 	/* Runtime state: */
136 	const struct bt_mesh_blob_io *io;
137 	struct k_work_delayable rx_timeout;
138 	struct bt_mesh_blob_block block;
139 	struct bt_mesh_model *mod;
140 	enum bt_mesh_blob_xfer_phase phase;
141 
142 	struct bt_mesh_blob_srv_state {
143 		struct bt_mesh_blob_xfer xfer;
144 		uint16_t cli;
145 		uint16_t app_idx;
146 		uint16_t timeout_base;
147 		uint16_t mtu_size;
148 		uint8_t ttl;
149 
150 		/* Bitfield of pending blocks. */
151 		ATOMIC_DEFINE(blocks, BT_MESH_BLOB_BLOCKS_MAX);
152 	} state;
153 
154 	/* Pull mode (Pull BLOB Transfer Mode) behavior. */
155 	struct {
156 		uint16_t chunk_idx;
157 		struct k_work_delayable report;
158 	} pull;
159 };
160 
161 /** @brief Prepare BLOB Transfer Server for an incoming transfer.
162  *
163  *  Before a BLOB Transfer Server can receive a transfer, the transfer must be prepared
164  *  through some application level mechanism. The BLOB Transfer Server will only accept
165  *  incoming transfers with a matching BLOB ID.
166  *
167  *  @param srv          BLOB Transfer Server instance.
168  *  @param id           BLOB ID to accept.
169  *  @param io           BLOB stream to write the incoming BLOB to.
170  *  @param ttl          Time to live value to use in responses to the BLOB Transfer Client.
171  *  @param timeout_base Extra time for the Client to respond in addition to the
172  *                      base 10 seconds, in 10-second increments.
173  *
174  *  @return 0 on success, or (negative) error code on failure.
175  */
176 int bt_mesh_blob_srv_recv(struct bt_mesh_blob_srv *srv, uint64_t id,
177 			  const struct bt_mesh_blob_io *io, uint8_t ttl,
178 			  uint16_t timeout_base);
179 
180 /** @brief Cancel the current BLOB transfer.
181  *
182  *  Tells the BLOB Transfer Client to drop this device from the list of Targets for the
183  *  current transfer. Note that the client may continue sending the transfer to
184  *  other Targets.
185  *
186  *  @param srv BLOB Transfer Server instance.
187  *
188  *  @return 0 on success, or (negative) error code on failure.
189  */
190 int bt_mesh_blob_srv_cancel(struct bt_mesh_blob_srv *srv);
191 
192 /** @brief Get the current state of the BLOB Transfer Server.
193  *
194  *  @param srv BLOB Transfer Server instance.
195  *
196  *  @return true if the BLOB Transfer Server is currently participating in a transfer,
197  *          false otherwise.
198  */
199 bool bt_mesh_blob_srv_is_busy(const struct bt_mesh_blob_srv *srv);
200 
201 /** @brief Get the current progress of the active transfer in percent.
202  *
203  *  @param srv BLOB Transfer Server instance.
204  *
205  *  @return The current transfer progress, or 0 if no transfer is active.
206  */
207 uint8_t bt_mesh_blob_srv_progress(const struct bt_mesh_blob_srv *srv);
208 
209 /** @cond INTERNAL_HIDDEN */
210 extern const struct bt_mesh_model_op _bt_mesh_blob_srv_op[];
211 extern const struct bt_mesh_model_cb _bt_mesh_blob_srv_cb;
212 /** @endcond */
213 
214 /** @} */
215 
216 #ifdef __cplusplus
217 }
218 #endif
219 
220 #endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_BLOB_SRV_H_ */
221