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 /**
80  * @typedef mgmt_cb
81  * @brief Function to be called on MGMT notification/event.
82  *
83  * This callback function is used to notify an application or system about a MCUmgr mgmt event.
84  *
85  * @param event		#mcumgr_op_t.
86  * @param prev_status	#mgmt_cb_return of the previous handler calls, if it is an error then it
87  *			will be the first error that was returned by a handler (i.e. this handler
88  *			is being called for a notification only, the return code will be ignored).
89  * @param rc		If ``prev_status`` is #MGMT_CB_ERROR_RC then this is the SMP error that
90  *			was returned by the first handler that failed. If ``prev_status`` is
91  *			#MGMT_CB_ERROR_ERR then this will be the group error rc code returned by
92  *			the first handler that failed. If the handler wishes to raise an SMP
93  *			error, this must be set to the #mcumgr_err_t status and #MGMT_CB_ERROR_RC
94  *			must be returned by the function, if the handler wishes to raise a ret
95  *			error, this must be set to the group ret status and #MGMT_CB_ERROR_ERR
96  *			must be returned by the function.
97  * @param group		If ``prev_status`` is #MGMT_CB_ERROR_ERR then this is the group of the
98  *			ret error that was returned by the first handler that failed. If the
99  *			handler wishes to raise a ret error, this must be set to the group ret
100  *			status and #MGMT_CB_ERROR_ERR must be returned by the function.
101  * @param abort_more	Set to true to abort further processing by additional handlers.
102  * @param data		Optional event argument.
103  * @param data_size	Size of optional event argument (0 if no data is provided).
104  *
105  * @return		#mgmt_cb_return indicating the status to return to the calling code (only
106  *			checked when this is the first failure reported by a handler).
107  */
108 typedef enum mgmt_cb_return (*mgmt_cb)(uint32_t event, enum mgmt_cb_return prev_status,
109 				       int32_t *rc, uint16_t *group, bool *abort_more, void *data,
110 				       size_t data_size);
111 
112 /**
113  * MGMT event callback group IDs. Note that this is not a 1:1 mapping with #mcumgr_group_t values.
114  */
115 enum mgmt_cb_groups {
116 	MGMT_EVT_GRP_ALL			= 0,
117 	MGMT_EVT_GRP_SMP,
118 	MGMT_EVT_GRP_OS,
119 	MGMT_EVT_GRP_IMG,
120 	MGMT_EVT_GRP_FS,
121 	MGMT_EVT_GRP_SETTINGS,
122 	MGMT_EVT_GRP_ENUM,
123 
124 	MGMT_EVT_GRP_USER_CUSTOM_START		= MGMT_GROUP_ID_PERUSER,
125 };
126 
127 /**
128  * MGMT event opcodes for all command processing.
129  */
130 enum smp_all_events {
131 	/** Used to enable all events. */
132 	MGMT_EVT_OP_ALL				= MGMT_DEF_EVT_OP_ALL(MGMT_EVT_GRP_ALL),
133 };
134 
135 /**
136  * MGMT event opcodes for base SMP command processing.
137  */
138 enum smp_group_events {
139 	/** Callback when a command is received, data is mgmt_evt_op_cmd_arg(). */
140 	MGMT_EVT_OP_CMD_RECV			= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_SMP, 0),
141 
142 	/** Callback when a status is updated, data is mgmt_evt_op_cmd_arg(). */
143 	MGMT_EVT_OP_CMD_STATUS			= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_SMP, 1),
144 
145 	/** Callback when a command has been processed, data is mgmt_evt_op_cmd_arg(). */
146 	MGMT_EVT_OP_CMD_DONE			= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_SMP, 2),
147 
148 	/** Used to enable all smp_group events. */
149 	MGMT_EVT_OP_CMD_ALL			= MGMT_DEF_EVT_OP_ALL(MGMT_EVT_GRP_SMP),
150 };
151 
152 /**
153  * MGMT event opcodes for filesystem management group.
154  */
155 enum fs_mgmt_group_events {
156 	/** Callback when a file has been accessed, data is fs_mgmt_file_access(). */
157 	MGMT_EVT_OP_FS_MGMT_FILE_ACCESS		= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_FS, 0),
158 
159 	/** Used to enable all fs_mgmt_group events. */
160 	MGMT_EVT_OP_FS_MGMT_ALL			= MGMT_DEF_EVT_OP_ALL(MGMT_EVT_GRP_FS),
161 };
162 
163 /**
164  * MGMT event opcodes for image management group.
165  */
166 enum img_mgmt_group_events {
167 	/** Callback when a client sends a file upload chunk, data is img_mgmt_upload_check(). */
168 	MGMT_EVT_OP_IMG_MGMT_DFU_CHUNK			= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 0),
169 
170 	/** Callback when a DFU operation is stopped. */
171 	MGMT_EVT_OP_IMG_MGMT_DFU_STOPPED		= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 1),
172 
173 	/** Callback when a DFU operation is started. */
174 	MGMT_EVT_OP_IMG_MGMT_DFU_STARTED		= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 2),
175 
176 	/** Callback when a DFU operation has finished being transferred. */
177 	MGMT_EVT_OP_IMG_MGMT_DFU_PENDING		= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 3),
178 
179 	/** Callback when an image has been confirmed. data is img_mgmt_image_confirmed(). */
180 	MGMT_EVT_OP_IMG_MGMT_DFU_CONFIRMED		= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 4),
181 
182 	/** Callback when an image write command has finished writing to flash. */
183 	MGMT_EVT_OP_IMG_MGMT_DFU_CHUNK_WRITE_COMPLETE	= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 5),
184 
185 	/**
186 	 * Callback when an image slot's state is encoded for a response, data is
187 	 * img_mgmt_state_slot_encode().
188 	 */
189 	MGMT_EVT_OP_IMG_MGMT_IMAGE_SLOT_STATE		= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 6),
190 
191 	/**
192 	 * Callback when a slot list command outputs fields for an image, data is
193 	 * img_mgmt_slot_info_image().
194 	 */
195 	MGMT_EVT_OP_IMG_MGMT_SLOT_INFO_IMAGE		= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 7),
196 
197 	/**
198 	 * Callback when a slot list command outputs fields for a slot of an image, data is
199 	 * img_mgmt_slot_info_slot().
200 	 */
201 	MGMT_EVT_OP_IMG_MGMT_SLOT_INFO_SLOT		= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 8),
202 
203 	/** Used to enable all img_mgmt_group events. */
204 	MGMT_EVT_OP_IMG_MGMT_ALL			= MGMT_DEF_EVT_OP_ALL(MGMT_EVT_GRP_IMG),
205 };
206 
207 /**
208  * MGMT event opcodes for operating system management group.
209  */
210 enum os_mgmt_group_events {
211 	/** Callback when a reset command has been received, data is os_mgmt_reset_data(). */
212 	MGMT_EVT_OP_OS_MGMT_RESET		= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_OS, 0),
213 
214 	/** Callback when an info command is processed, data is os_mgmt_info_check(). */
215 	MGMT_EVT_OP_OS_MGMT_INFO_CHECK		= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_OS, 1),
216 
217 	/** Callback when an info command needs to output data, data is os_mgmt_info_append(). */
218 	MGMT_EVT_OP_OS_MGMT_INFO_APPEND		= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_OS, 2),
219 
220 	/** Callback when a datetime get command has been received. */
221 	MGMT_EVT_OP_OS_MGMT_DATETIME_GET	= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_OS, 3),
222 
223 	/** Callback when a datetime set command has been received, data is struct rtc_time(). */
224 	MGMT_EVT_OP_OS_MGMT_DATETIME_SET	= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_OS, 4),
225 
226 	/**
227 	 * Callback when a bootloader info command has been received, data is
228 	 * os_mgmt_bootloader_info_data().
229 	 */
230 	MGMT_EVT_OP_OS_MGMT_BOOTLOADER_INFO	= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_OS, 5),
231 
232 	/** Used to enable all os_mgmt_group events. */
233 	MGMT_EVT_OP_OS_MGMT_ALL			= MGMT_DEF_EVT_OP_ALL(MGMT_EVT_GRP_OS),
234 };
235 
236 /**
237  * MGMT event opcodes for settings management group.
238  */
239 enum settings_mgmt_group_events {
240 	/** Callback when a setting is read/written/deleted. */
241 	MGMT_EVT_OP_SETTINGS_MGMT_ACCESS	= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_SETTINGS, 0),
242 
243 	/** Used to enable all settings_mgmt_group events. */
244 	MGMT_EVT_OP_SETTINGS_MGMT_ALL		= MGMT_DEF_EVT_OP_ALL(MGMT_EVT_GRP_SETTINGS),
245 };
246 
247 /**
248  * MGMT event opcodes for enumeration management group.
249  */
250 enum enum_mgmt_group_events {
251 	/** Callback when fetching details on supported command groups. */
252 	MGMT_EVT_OP_ENUM_MGMT_DETAILS		= MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_ENUM, 0),
253 
254 	/** Used to enable all enum_mgmt_group events. */
255 	MGMT_EVT_OP_ENUM_MGMT_ALL		= MGMT_DEF_EVT_OP_ALL(MGMT_EVT_GRP_ENUM),
256 };
257 
258 /**
259  * MGMT callback struct
260  */
261 struct mgmt_callback {
262 	/** Entry list node. */
263 	sys_snode_t node;
264 
265 	/** Callback that will be called. */
266 	mgmt_cb callback;
267 
268 	/**
269 	 * MGMT_EVT_[...] Event ID for handler to be called on. This has special meaning if
270 	 * #MGMT_EVT_OP_ALL is used (which will cover all events for all groups), or
271 	 * MGMT_EVT_OP_*_MGMT_ALL (which will cover all events for a single group). For events
272 	 * that are part of a single group, they can be or'd together for this to have one
273 	 * registration trigger on multiple events, please note that this will only work for
274 	 * a single group, to register for events in different groups, they must be registered
275 	 * separately.
276 	 */
277 	uint32_t event_id;
278 };
279 
280 /**
281  * Arguments for #MGMT_EVT_OP_CMD_RECV, #MGMT_EVT_OP_CMD_STATUS and #MGMT_EVT_OP_CMD_DONE
282  */
283 struct mgmt_evt_op_cmd_arg {
284 	/** #mcumgr_group_t */
285 	uint16_t group;
286 
287 	/** Message ID within group */
288 	uint8_t id;
289 
290 	union {
291 		/** #mcumgr_op_t used in #MGMT_EVT_OP_CMD_RECV */
292 		uint8_t op;
293 
294 		/** #mcumgr_err_t, used in #MGMT_EVT_OP_CMD_DONE */
295 		int err;
296 
297 		/** #img_mgmt_id_upload_t, used in #MGMT_EVT_OP_CMD_STATUS */
298 		int status;
299 	};
300 };
301 
302 /**
303  * @brief Get event ID index from event.
304  *
305  * @param event		Event to get ID index from.
306  *
307  * @return		Event index.
308  */
309 uint8_t mgmt_evt_get_index(uint32_t event);
310 
311 /**
312  * @brief This function is called to notify registered callbacks about mcumgr notifications/events.
313  *
314  * @param event		#mcumgr_op_t.
315  * @param data		Optional event argument.
316  * @param data_size	Size of optional event argument (0 if none).
317  * @param err_rc	Pointer to rc value.
318  * @param err_group	Pointer to group value.
319  *
320  * @return		#mgmt_cb_return either #MGMT_CB_OK if all handlers returned it, or
321  *			#MGMT_CB_ERROR_RC if the first failed handler returned an SMP error (in
322  *			which case ``err_rc`` will be updated with the SMP error) or
323  *			#MGMT_CB_ERROR_ERR if the first failed handler returned a ret group and
324  *			error (in which case ``err_group`` will be updated with the failed group
325  *			ID and ``err_rc`` will be updated with the group-specific error code).
326  */
327 enum mgmt_cb_return mgmt_callback_notify(uint32_t event, void *data, size_t data_size,
328 					 int32_t *err_rc, uint16_t *err_group);
329 
330 /**
331  * @brief Register event callback function.
332  *
333  * @param callback Callback struct.
334  */
335 void mgmt_callback_register(struct mgmt_callback *callback);
336 
337 /**
338  * @brief Unregister event callback function.
339  *
340  * @param callback Callback struct.
341  */
342 void mgmt_callback_unregister(struct mgmt_callback *callback);
343 
344 /**
345  * @}
346  */
347 
348 #ifdef __cplusplus
349 }
350 #endif
351 
352 #endif /* H_MCUMGR_CALLBACKS_ */
353