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