1 /*
2  * Copyright (c) 2020 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @defgroup bt_mesh_dfu_srv Firmware Update Server model
10  * @ingroup bt_mesh_dfu
11  * @{
12  * @brief API for the Bluetooth mesh Firmware Update Server model
13  */
14 
15 #ifndef ZEPHYR_INCLUDE_BLUETOOTH_MESH_DFU_SRV_H__
16 #define ZEPHYR_INCLUDE_BLUETOOTH_MESH_DFU_SRV_H__
17 
18 #include <zephyr/bluetooth/mesh/dfu.h>
19 #include <zephyr/bluetooth/mesh/blob_srv.h>
20 #include <zephyr/bluetooth/mesh/access.h>
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
26 struct bt_mesh_dfu_srv;
27 
28 /**
29  *
30  * @brief Initialization parameters for @ref bt_mesh_dfu_srv.
31  *
32  * @param _handlers   DFU handler function structure.
33  * @param _imgs       List of @ref bt_mesh_dfu_img managed by this Server.
34  * @param _img_count  Number of DFU images managed by this Server.
35  */
36 #define BT_MESH_DFU_SRV_INIT(_handlers, _imgs, _img_count)                     \
37 	{                                                                      \
38 		.blob = { .cb = &_bt_mesh_dfu_srv_blob_cb }, .cb = _handlers,  \
39 		.imgs = _imgs, .img_count = _img_count,                        \
40 	}
41 
42 /**
43  *
44  *  @brief Firmware Update Server model entry.
45  *
46  *  @param _srv Pointer to a @ref bt_mesh_dfu_srv instance.
47  */
48 #define BT_MESH_MODEL_DFU_SRV(_srv)                                            \
49 	BT_MESH_MODEL_BLOB_SRV(&(_srv)->blob),                                  \
50 	BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_DFU_SRV, _bt_mesh_dfu_srv_op, NULL,  \
51 			 _srv, &_bt_mesh_dfu_srv_cb)
52 
53 /** @brief Firmware Update Server event callbacks. */
54 struct bt_mesh_dfu_srv_cb {
55 	/** @brief Transfer check callback.
56 	 *
57 	 *  The transfer check can be used to validate the incoming transfer
58 	 *  before it starts. The contents of the metadata is implementation
59 	 *  specific, and should contain all the information the application
60 	 *  needs to determine whether this image should be accepted, and what
61 	 *  the effect of the transfer would be.
62 	 *
63 	 *  If applying the image will have an effect on the provisioning state
64 	 *  of the mesh stack, this can be communicated through the @c effect
65 	 *  return parameter.
66 	 *
67 	 *  The metadata check can be performed both as part of starting a new
68 	 *  transfer and as a separate procedure.
69 	 *
70 	 *  This handler is optional.
71 	 *
72 	 *  @param srv          Firmware Update Server instance.
73 	 *  @param img          DFU image the metadata check is performed on.
74 	 *  @param metadata     Image metadata.
75 	 *  @param effect       Return parameter for the image effect on the
76 	 *                      provisioning state of the mesh stack.
77 	 *
78 	 *  @return 0 on success, or (negative) error code otherwise.
79 	 */
80 	int (*check)(struct bt_mesh_dfu_srv *srv,
81 		     const struct bt_mesh_dfu_img *img,
82 		     struct net_buf_simple *metadata,
83 		     enum bt_mesh_dfu_effect *effect);
84 
85 	/** @brief Transfer start callback.
86 	 *
87 	 *  Called when the Firmware Update Server is ready to start a new DFU transfer.
88 	 *  The application must provide an initialized BLOB stream to be used
89 	 *  during the DFU transfer.
90 	 *
91 	 *  The following error codes are treated specially, and should be used
92 	 *  to communicate these issues:
93 	 *  - @c -ENOMEM: The device cannot fit this image.
94 	 *  - @c -EBUSY: The application is temporarily unable to accept the
95 	 *    transfer.
96 	 *  - @c -EALREADY: The device has already received and verified this
97 	 *    image, and there's no need to transfer it again. The Firmware Update model
98 	 *    will skip the transfer phase, and mark the image as verified.
99 	 *
100 	 *  This handler is mandatory.
101 	 *
102 	 *  @param srv          Firmware Update Server instance.
103 	 *  @param img          DFU image being updated.
104 	 *  @param metadata     Image metadata.
105 	 *  @param io           BLOB stream return parameter. Must be set to a
106 	 *                      valid BLOB stream by the callback.
107 	 *
108 	 *  @return 0 on success, or (negative) error code otherwise. Return
109 	 *          codes @c -ENOMEM, @c -EBUSY @c -EALREADY will be passed to
110 	 *          the updater, other error codes are reported as internal
111 	 *          errors.
112 	 */
113 	int (*start)(struct bt_mesh_dfu_srv *srv,
114 		     const struct bt_mesh_dfu_img *img,
115 		     struct net_buf_simple *metadata,
116 		     const struct bt_mesh_blob_io **io);
117 
118 	/** @brief Transfer end callback.
119 	 *
120 	 *  This handler is optional.
121 	 *
122 	 *  If the transfer is successful, the application should verify the
123 	 *  firmware image, and call either @ref bt_mesh_dfu_srv_verified or
124 	 *  @ref bt_mesh_dfu_srv_rejected depending on the outcome.
125 	 *
126 	 *  If the transfer fails, the Firmware Update Server will be available for new
127 	 *  transfers immediately after this function returns.
128 	 *
129 	 *  @param srv     Firmware Update Server instance.
130 	 *  @param img     DFU image that failed the update.
131 	 *  @param success Whether the DFU transfer was successful.
132 	 */
133 	void (*end)(struct bt_mesh_dfu_srv *srv,
134 		    const struct bt_mesh_dfu_img *img, bool success);
135 
136 	/** @brief Transfer recovery callback.
137 	 *
138 	 *  If the device reboots in the middle of a transfer, the Firmware Update Server
139 	 *  calls this function when the Bluetooth mesh subsystem is started.
140 	 *
141 	 *  This callback is optional, but transfers will not be recovered after
142 	 *  a reboot without it.
143 	 *
144 	 *  @param srv Firmware Update Server instance.
145 	 *  @param img DFU image being updated.
146 	 *  @param io  BLOB stream return parameter. Must be set to a valid BLOB
147 	 *             stream by the callback.
148 	 *
149 	 *  @return 0 on success, or (negative) error code to abandon the
150 	 *          transfer.
151 	 */
152 	int (*recover)(struct bt_mesh_dfu_srv *srv,
153 		       const struct bt_mesh_dfu_img *img,
154 		       const struct bt_mesh_blob_io **io);
155 
156 	/** @brief Transfer apply callback.
157 	 *
158 	 *  Called after a transfer has been validated, and the updater sends an
159 	 *  apply message to the Target nodes.
160 	 *
161 	 *  This handler is optional.
162 	 *
163 	 *  @param srv Firmware Update Server instance.
164 	 *  @param img DFU image that should be applied.
165 	 *
166 	 *  @return 0 on success, or (negative) error code otherwise.
167 	 */
168 	int (*apply)(struct bt_mesh_dfu_srv *srv,
169 		     const struct bt_mesh_dfu_img *img);
170 };
171 
172 /** @brief Firmware Update Server instance.
173  *
174  *  Should be initialized with @ref BT_MESH_DFU_SRV_INIT.
175  */
176 struct bt_mesh_dfu_srv {
177 	/** Underlying BLOB Transfer Server. */
178 	struct bt_mesh_blob_srv blob;
179 	/** Callback structure. */
180 	const struct bt_mesh_dfu_srv_cb *cb;
181 	/** List of updatable images. */
182 	const struct bt_mesh_dfu_img *imgs;
183 	/** Number of updatable images. */
184 	size_t img_count;
185 
186 	/* Runtime state */
187 	struct bt_mesh_model *mod;
188 	struct {
189 		/* Effect of transfer, @see bt_mesh_dfu_effect. */
190 		uint8_t effect;
191 		/* Current phase, @see bt_mesh_dfu_phase. */
192 		uint8_t phase;
193 		uint8_t ttl;
194 		uint8_t idx;
195 		uint16_t timeout_base;
196 		uint16_t meta;
197 	} update;
198 };
199 
200 /** @brief Accept the received DFU transfer.
201  *
202  *  Should be called at the end of a successful DFU transfer.
203  *
204  *  If the DFU transfer completes successfully, the application should verify
205  *  the image validity (including any image authentication or integrity checks),
206  *  and call this function if the image is ready to be applied.
207  *
208  *  @param srv Firmware Update Server instance.
209  */
210 void bt_mesh_dfu_srv_verified(struct bt_mesh_dfu_srv *srv);
211 
212 /** @brief Reject the received DFU transfer.
213  *
214  *  Should be called at the end of a successful DFU transfer.
215  *
216  *  If the DFU transfer completes successfully, the application should verify
217  *  the image validity (including any image authentication or integrity checks),
218  *  and call this function if one of the checks fail.
219  *
220  *  @param srv Firmware Update Server instance.
221  */
222 void bt_mesh_dfu_srv_rejected(struct bt_mesh_dfu_srv *srv);
223 
224 /** @brief Cancel the ongoing DFU transfer.
225  *
226  *  @param srv Firmware Update Server instance.
227  */
228 void bt_mesh_dfu_srv_cancel(struct bt_mesh_dfu_srv *srv);
229 
230 /** @brief Confirm that the received DFU transfer was applied.
231  *
232  *  Should be called as a result of the @ref bt_mesh_dfu_srv_cb.apply callback.
233  *
234  *  @param srv Firmware Update Server instance.
235  */
236 void bt_mesh_dfu_srv_applied(struct bt_mesh_dfu_srv *srv);
237 
238 /** @brief Check if the Firmware Update	Server is busy processing a transfer.
239  *
240  *  @param srv Firmware Update Server instance.
241  *
242  *  @return true if a DFU procedure is in progress, false otherwise.
243  */
244 bool bt_mesh_dfu_srv_is_busy(const struct bt_mesh_dfu_srv *srv);
245 
246 /** @brief Get the progress of the current DFU procedure, in percent.
247  *
248  *  @param srv Firmware Update Server instance.
249  *
250  *  @return The current transfer progress in percent.
251  */
252 uint8_t bt_mesh_dfu_srv_progress(const struct bt_mesh_dfu_srv *srv);
253 
254 /** @cond INTERNAL_HIDDEN */
255 extern const struct bt_mesh_model_op _bt_mesh_dfu_srv_op[];
256 extern const struct bt_mesh_model_cb _bt_mesh_dfu_srv_cb;
257 extern const struct bt_mesh_blob_srv_cb _bt_mesh_dfu_srv_blob_cb;
258 /** @endcond */
259 
260 #ifdef __cplusplus
261 }
262 #endif
263 
264 #endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_DFU_SRV_H__ */
265 
266 /** @} */
267