1 /*
2  * Copyright (c) 2022-2023 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef H_MCUMGR_CALLBACKS_
8 #define H_MCUMGR_CALLBACKS_
9 
10 #include <inttypes.h>
11 #include <zephyr/sys/slist.h>
12 #include <zephyr/mgmt/mcumgr/mgmt/mgmt.h>
13 
14 #ifdef CONFIG_MCUMGR_GRP_FS
15 #include <zephyr/mgmt/mcumgr/grp/fs_mgmt/fs_mgmt_callbacks.h>
16 #endif
17 
18 #ifdef CONFIG_MCUMGR_GRP_IMG
19 #include <zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt_callbacks.h>
20 #endif
21 
22 #ifdef CONFIG_MCUMGR_GRP_OS
23 #include <zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt_callbacks.h>
24 #endif
25 
26 #ifdef CONFIG_MCUMGR_GRP_SETTINGS
27 #include <zephyr/mgmt/mcumgr/grp/settings_mgmt/settings_mgmt_callbacks.h>
28 #endif
29 
30 #ifdef CONFIG_MCUMGR_GRP_ENUM
31 #include <zephyr/mgmt/mcumgr/grp/enum_mgmt/enum_mgmt_callbacks.h>
32 #endif
33 
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37 
38 /**
39  * @brief MCUmgr callback API
40  * @defgroup mcumgr_callback_api MCUmgr callback API
41  * @ingroup mcumgr
42  * @{
43  */
44 
45 /** @cond INTERNAL_HIDDEN */
46 /** Event which signifies that all event IDs for a particular group should be enabled. */
47 #define MGMT_EVT_OP_ID_ALL 0xffff
48 
49 /** Get event for a particular group and event ID. */
50 #define MGMT_DEF_EVT_OP_ID(group, event_id) ((group << 16) | BIT(event_id))
51 
52 /** Get event used for enabling all event IDs of a particular group. */
53 #define MGMT_DEF_EVT_OP_ALL(group) ((group << 16) | MGMT_EVT_OP_ID_ALL)
54 /** @endcond  */
55 
56 /** Get group from event. */
57 #define MGMT_EVT_GET_GROUP(event) ((event >> 16) & MGMT_EVT_OP_ID_ALL)
58 
59 /** Get event ID from event. */
60 #define MGMT_EVT_GET_ID(event) (event & MGMT_EVT_OP_ID_ALL)
61 
62 /**
63  * MGMT event callback return value.
64  */
65 enum mgmt_cb_return {
66 	/** No error. */
67 	MGMT_CB_OK,
68 
69 	/** SMP protocol error and ``err_rc`` contains the #mcumgr_err_t error code. */
70 	MGMT_CB_ERROR_RC,
71 
72 	/**
73 	 * Group (application-level) error and ``err_group`` contains the group ID that caused
74 	 * the error and ``err_rc`` contains the error code of that group to return.
75 	 */
76 	MGMT_CB_ERROR_ERR,
77 };
78 
79 /* Deprecated after Zephyr 3.4, use MGMT_CB_ERROR_ERR instead */
80 #define MGMT_CB_ERROR_RET __DEPRECATED_MACRO MGMT_CB_ERROR_ERR
81 
82 /**
83  * @typedef mgmt_cb
84  * @brief Function to be called on MGMT notification/event.
85  *
86  * This callback function is used to notify an application or system about a MCUmgr mgmt event.
87  *
88  * @param event		#mcumgr_op_t.
89  * @param prev_status	#mgmt_cb_return of the previous handler calls, if it is an error then it
90  *			will be the first error that was returned by a handler (i.e. this handler
91  *			is being called for a notification only, the return code will be ignored).
92  * @param rc		If ``prev_status`` is #MGMT_CB_ERROR_RC then this is the SMP error that
93  *			was returned by the first handler that failed. If ``prev_status`` is
94  *			#MGMT_CB_ERROR_ERR then this will be the group error rc code returned by
95  *			the first handler that failed. If the handler wishes to raise an SMP
96  *			error, this must be set to the #mcumgr_err_t status and #MGMT_CB_ERROR_RC
97  *			must be returned by the function, if the handler wishes to raise a ret
98  *			error, this must be set to the group ret status and #MGMT_CB_ERROR_ERR
99  *			must be returned by the function.
100  * @param group		If ``prev_status`` is #MGMT_CB_ERROR_ERR then this is the group of the
101  *			ret error that was returned by the first handler that failed. If the
102  *			handler wishes to raise a ret error, this must be set to the group ret
103  *			status and #MGMT_CB_ERROR_ERR must be returned by the function.
104  * @param abort_more	Set to true to abort further processing by additional handlers.
105  * @param data		Optional event argument.
106  * @param data_size	Size of optional event argument (0 if no data is provided).
107  *
108  * @return		#mgmt_cb_return indicating the status to return to the calling code (only
109  *			checked when this is the first failure reported by a handler).
110  */
111 typedef enum mgmt_cb_return (*mgmt_cb)(uint32_t event, enum mgmt_cb_return prev_status,
112 				       int32_t *rc, uint16_t *group, bool *abort_more, void *data,
113 				       size_t data_size);
114 
115 /**
116  * MGMT event callback group IDs. Note that this is not a 1:1 mapping with #mcumgr_group_t values.
117  */
118 enum mgmt_cb_groups {
119 	MGMT_EVT_GRP_ALL			= 0,
120 	MGMT_EVT_GRP_SMP,
121 	MGMT_EVT_GRP_OS,
122 	MGMT_EVT_GRP_IMG,
123 	MGMT_EVT_GRP_FS,
124 	MGMT_EVT_GRP_SETTINGS,
125 	MGMT_EVT_GRP_ENUM,
126 
127 	MGMT_EVT_GRP_USER_CUSTOM_START		= MGMT_GROUP_ID_PERUSER,
128 };
129 
130 /**
131  * MGMT event opcodes for all command processing.
132  */
133 enum smp_all_events {
134 	/** Used to enable all events. */
135 	MGMT_EVT_OP_ALL				= MGMT_DEF_EVT_OP_ALL(MGMT_EVT_GRP_ALL),
136 };
137 
138 /**
139  * MGMT event opcodes for base SMP command processing.
140  */
141 enum smp_group_events {
142 	/** Callback when a command is received, data is mgmt_evt_op_cmd_arg(). */
143 	MGMT_EVT_OP_CMD_RECV			= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_SMP, 0),
144 
145 	/** Callback when a status is updated, data is mgmt_evt_op_cmd_arg(). */
146 	MGMT_EVT_OP_CMD_STATUS			= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_SMP, 1),
147 
148 	/** Callback when a command has been processed, data is mgmt_evt_op_cmd_arg(). */
149 	MGMT_EVT_OP_CMD_DONE			= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_SMP, 2),
150 
151 	/** Used to enable all smp_group events. */
152 	MGMT_EVT_OP_CMD_ALL			= MGMT_DEF_EVT_OP_ALL(MGMT_EVT_GRP_SMP),
153 };
154 
155 /**
156  * MGMT event opcodes for filesystem management group.
157  */
158 enum fs_mgmt_group_events {
159 	/** Callback when a file has been accessed, data is fs_mgmt_file_access(). */
160 	MGMT_EVT_OP_FS_MGMT_FILE_ACCESS		= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_FS, 0),
161 
162 	/** Used to enable all fs_mgmt_group events. */
163 	MGMT_EVT_OP_FS_MGMT_ALL			= MGMT_DEF_EVT_OP_ALL(MGMT_EVT_GRP_FS),
164 };
165 
166 /**
167  * MGMT event opcodes for image management group.
168  */
169 enum img_mgmt_group_events {
170 	/** Callback when a client sends a file upload chunk, data is img_mgmt_upload_check(). */
171 	MGMT_EVT_OP_IMG_MGMT_DFU_CHUNK			= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 0),
172 
173 	/** Callback when a DFU operation is stopped. */
174 	MGMT_EVT_OP_IMG_MGMT_DFU_STOPPED		= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 1),
175 
176 	/** Callback when a DFU operation is started. */
177 	MGMT_EVT_OP_IMG_MGMT_DFU_STARTED		= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 2),
178 
179 	/** Callback when a DFU operation has finished being transferred. */
180 	MGMT_EVT_OP_IMG_MGMT_DFU_PENDING		= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 3),
181 
182 	/** Callback when an image has been confirmed. */
183 	MGMT_EVT_OP_IMG_MGMT_DFU_CONFIRMED		= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 4),
184 
185 	/** Callback when an image write command has finished writing to flash. */
186 	MGMT_EVT_OP_IMG_MGMT_DFU_CHUNK_WRITE_COMPLETE	= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 5),
187 
188 	/** Callback when an image slot's state is encoded for a response. */
189 	MGMT_EVT_OP_IMG_MGMT_IMAGE_SLOT_STATE		= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 6),
190 
191 	/** Callback when an slot list command outputs fields for an image. */
192 	MGMT_EVT_OP_IMG_MGMT_SLOT_INFO_IMAGE		= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 7),
193 
194 	/** Callback when an slot list command outputs fields for a slot of an image. */
195 	MGMT_EVT_OP_IMG_MGMT_SLOT_INFO_SLOT		= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 8),
196 
197 	/** Used to enable all img_mgmt_group events. */
198 	MGMT_EVT_OP_IMG_MGMT_ALL			= MGMT_DEF_EVT_OP_ALL(MGMT_EVT_GRP_IMG),
199 };
200 
201 /**
202  * MGMT event opcodes for operating system management group.
203  */
204 enum os_mgmt_group_events {
205 	/** Callback when a reset command has been received, data is os_mgmt_reset_data. */
206 	MGMT_EVT_OP_OS_MGMT_RESET		= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_OS, 0),
207 
208 	/** Callback when an info command is processed, data is os_mgmt_info_check. */
209 	MGMT_EVT_OP_OS_MGMT_INFO_CHECK		= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_OS, 1),
210 
211 	/** Callback when an info command needs to output data, data is os_mgmt_info_append. */
212 	MGMT_EVT_OP_OS_MGMT_INFO_APPEND		= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_OS, 2),
213 
214 	/** Callback when a datetime get command has been received. */
215 	MGMT_EVT_OP_OS_MGMT_DATETIME_GET	= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_OS, 3),
216 
217 	/** Callback when a datetime set command has been received, data is struct rtc_time(). */
218 	MGMT_EVT_OP_OS_MGMT_DATETIME_SET	= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_OS, 4),
219 
220 	/**
221 	 * Callback when a bootloader info command has been received, data is
222 	 * os_mgmt_bootloader_info_data.
223 	 */
224 	MGMT_EVT_OP_OS_MGMT_BOOTLOADER_INFO	= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_OS, 5),
225 
226 	/** Used to enable all os_mgmt_group events. */
227 	MGMT_EVT_OP_OS_MGMT_ALL			= MGMT_DEF_EVT_OP_ALL(MGMT_EVT_GRP_OS),
228 };
229 
230 /**
231  * MGMT event opcodes for settings management group.
232  */
233 enum settings_mgmt_group_events {
234 	/** Callback when a setting is read/written/deleted. */
235 	MGMT_EVT_OP_SETTINGS_MGMT_ACCESS	= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_SETTINGS, 0),
236 
237 	/** Used to enable all settings_mgmt_group events. */
238 	MGMT_EVT_OP_SETTINGS_MGMT_ALL		= MGMT_DEF_EVT_OP_ALL(MGMT_EVT_GRP_SETTINGS),
239 };
240 
241 /**
242  * MGMT event opcodes for enumeration management group.
243  */
244 enum enum_mgmt_group_events {
245 	/** Callback when fetching details on supported command groups. */
246 	MGMT_EVT_OP_ENUM_MGMT_DETAILS		= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_ENUM, 0),
247 
248 	/** Used to enable all enum_mgmt_group events. */
249 	MGMT_EVT_OP_ENUM_MGMT_ALL		= MGMT_DEF_EVT_OP_ALL(MGMT_EVT_GRP_ENUM),
250 };
251 
252 /**
253  * MGMT callback struct
254  */
255 struct mgmt_callback {
256 	/** Entry list node. */
257 	sys_snode_t node;
258 
259 	/** Callback that will be called. */
260 	mgmt_cb callback;
261 
262 	/**
263 	 * MGMT_EVT_[...] Event ID for handler to be called on. This has special meaning if
264 	 * #MGMT_EVT_OP_ALL is used (which will cover all events for all groups), or
265 	 * MGMT_EVT_OP_*_MGMT_ALL (which will cover all events for a single group). For events
266 	 * that are part of a single group, they can be or'd together for this to have one
267 	 * registration trigger on multiple events, please note that this will only work for
268 	 * a single group, to register for events in different groups, they must be registered
269 	 * separately.
270 	 */
271 	uint32_t event_id;
272 };
273 
274 /**
275  * Arguments for #MGMT_EVT_OP_CMD_RECV, #MGMT_EVT_OP_CMD_STATUS and #MGMT_EVT_OP_CMD_DONE
276  */
277 struct mgmt_evt_op_cmd_arg {
278 	/** #mcumgr_group_t */
279 	uint16_t group;
280 
281 	/** Message ID within group */
282 	uint8_t id;
283 
284 	union {
285 		/** #mcumgr_op_t used in #MGMT_EVT_OP_CMD_RECV */
286 		uint8_t op;
287 
288 		/** #mcumgr_err_t, used in #MGMT_EVT_OP_CMD_DONE */
289 		int err;
290 
291 		/** #img_mgmt_id_upload_t, used in #MGMT_EVT_OP_CMD_STATUS */
292 		int status;
293 	};
294 };
295 
296 /**
297  * @brief Get event ID index from event.
298  *
299  * @param event		Event to get ID index from.
300  *
301  * @return		Event index.
302  */
303 uint8_t mgmt_evt_get_index(uint32_t event);
304 
305 /**
306  * @brief This function is called to notify registered callbacks about mcumgr notifications/events.
307  *
308  * @param event		#mcumgr_op_t.
309  * @param data		Optional event argument.
310  * @param data_size	Size of optional event argument (0 if none).
311  * @param err_rc	Pointer to rc value.
312  * @param err_group	Pointer to group value.
313  *
314  * @return		#mgmt_cb_return either #MGMT_CB_OK if all handlers returned it, or
315  *			#MGMT_CB_ERROR_RC if the first failed handler returned an SMP error (in
316  *			which case ``err_rc`` will be updated with the SMP error) or
317  *			#MGMT_CB_ERROR_ERR if the first failed handler returned a ret group and
318  *			error (in which case ``err_group`` will be updated with the failed group
319  *			ID and ``err_rc`` will be updated with the group-specific error code).
320  */
321 enum mgmt_cb_return mgmt_callback_notify(uint32_t event, void *data, size_t data_size,
322 					 int32_t *err_rc, uint16_t *err_group);
323 
324 /**
325  * @brief Register event callback function.
326  *
327  * @param callback Callback struct.
328  */
329 void mgmt_callback_register(struct mgmt_callback *callback);
330 
331 /**
332  * @brief Unregister event callback function.
333  *
334  * @param callback Callback struct.
335  */
336 void mgmt_callback_unregister(struct mgmt_callback *callback);
337 
338 /**
339  * @}
340  */
341 
342 #ifdef __cplusplus
343 }
344 #endif
345 
346 #endif /* H_MCUMGR_CALLBACKS_ */
347