1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #ifndef H_MGMT_MGMT_
21 #define H_MGMT_MGMT_
22 
23 #include <inttypes.h>
24 #include "tinycbor/cbor.h"
25 
26 #ifdef __cplusplus
27 extern "C" {
28 #endif
29 
30 /* MTU for newtmgr responses */
31 #define MGMT_MAX_MTU            1024
32 
33 /** Opcodes; encoded in first byte of header. */
34 #define MGMT_OP_READ            0
35 #define MGMT_OP_READ_RSP        1
36 #define MGMT_OP_WRITE           2
37 #define MGMT_OP_WRITE_RSP       3
38 
39 /**
40  * The first 64 groups are reserved for system level mcumgr commands.
41  * Per-user commands are then defined after group 64.
42  */
43 #define MGMT_GROUP_ID_OS        0
44 #define MGMT_GROUP_ID_IMAGE     1
45 #define MGMT_GROUP_ID_STAT      2
46 #define MGMT_GROUP_ID_CONFIG    3
47 #define MGMT_GROUP_ID_LOG       4
48 #define MGMT_GROUP_ID_CRASH     5
49 #define MGMT_GROUP_ID_SPLIT     6
50 #define MGMT_GROUP_ID_RUN       7
51 #define MGMT_GROUP_ID_FS        8
52 #define MGMT_GROUP_ID_SHELL     9
53 #define MGMT_GROUP_ID_PERUSER   64
54 
55 /**
56  * mcumgr error codes.
57  */
58 #define MGMT_ERR_EOK            0
59 #define MGMT_ERR_EUNKNOWN       1
60 #define MGMT_ERR_ENOMEM         2
61 #define MGMT_ERR_EINVAL         3
62 #define MGMT_ERR_ETIMEOUT       4
63 #define MGMT_ERR_ENOENT         5
64 #define MGMT_ERR_EBADSTATE      6       /* Current state disallows command. */
65 #define MGMT_ERR_EMSGSIZE       7       /* Response too large. */
66 #define MGMT_ERR_ENOTSUP        8       /* Command not supported. */
67 #define MGMT_ERR_ECORRUPT       9       /* Corrupt */
68 #define MGMT_ERR_EPERUSER       256
69 
70 #define MGMT_HDR_SIZE           8
71 
72 /*
73  * MGMT event opcodes.
74  */
75 #define MGMT_EVT_OP_CMD_RECV            0x01
76 #define MGMT_EVT_OP_CMD_STATUS          0x02
77 #define MGMT_EVT_OP_CMD_DONE            0x03
78 
79 struct mgmt_hdr {
80 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
81     uint8_t  nh_op:3;           /* MGMT_OP_[...] */
82     uint8_t  _res1:5;
83 #endif
84 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
85     uint8_t  _res1:5;
86     uint8_t  nh_op:3;           /* MGMT_OP_[...] */
87 #endif
88     uint8_t  nh_flags;          /* Reserved for future flags */
89     uint16_t nh_len;            /* Length of the payload */
90     uint16_t nh_group;          /* MGMT_GROUP_ID_[...] */
91     uint8_t  nh_seq;            /* Sequence number */
92     uint8_t  nh_id;             /* Message ID within group */
93 };
94 
95 #define nmgr_hdr mgmt_hdr
96 
97 /*
98  * MGMT_EVT_OP_CMD_STATUS argument
99  */
100 struct mgmt_evt_op_cmd_status_arg {
101     int status;
102 };
103 
104 /*
105  * MGMT_EVT_OP_CMD_DONE argument
106  */
107 struct mgmt_evt_op_cmd_done_arg {
108     int err;                    /* MGMT_ERR_[...] */
109 };
110 
111 /** @typedef mgmt_on_evt_cb
112  * @brief Function to be called on MGMT event.
113  *
114  * This callback function is used to notify application about mgmt event.
115  *
116  * @param opcode                MGMT_EVT_OP_[...].
117  * @param group                 MGMT_GROUP_ID_[...].
118  * @param id                    Message ID within group.
119  * @param arg                   Optional event argument.
120  */
121 typedef void mgmt_on_evt_cb(uint8_t opcode, uint16_t group, uint8_t id,
122                             void *arg);
123 
124 /** @typedef mgmt_alloc_rsp_fn
125  * @brief Allocates a buffer suitable for holding a response.
126  *
127  * If a source buf is provided, its user data is copied into the new buffer.
128  *
129  * @param src_buf               An optional source buffer to copy user data
130  *                                  from.
131  * @param arg                   Optional streamer argument.
132  *
133  * @return                      Newly-allocated buffer on success
134  *                              NULL on failure.
135  */
136 typedef void *mgmt_alloc_rsp_fn(const void *src_buf, void *arg);
137 
138 /** @typedef mgmt_trim_front_fn
139  * @brief Trims data from the front of a buffer.
140  *
141  * If the amount to trim exceeds the size of the buffer, the buffer is
142  * truncated to a length of 0.
143  *
144  * @param buf                   The buffer to trim.
145  * @param len                   The number of bytes to remove.
146  * @param arg                   Optional streamer argument.
147  */
148 typedef void mgmt_trim_front_fn(void *buf, size_t len, void *arg);
149 
150 /** @typedef mgmt_reset_buf_fn
151  * @brief Resets a buffer to a length of 0.
152  *
153  * The buffer's user data remains, but its payload is cleared.
154  *
155  * @param buf                   The buffer to reset.
156  * @param arg                   Optional streamer argument.
157  */
158 typedef void mgmt_reset_buf_fn(void *buf, void *arg);
159 
160 /** @typedef mgmt_write_at_fn
161  * @brief Writes data to a CBOR encoder.
162  *
163  * Any existing data at the specified offset is overwritten by the new data.
164  * Any new data that extends past the buffer's current length is appended.
165  *
166  * @param writer                The encoder to write to.
167  * @param offset                The byte offset to write to,
168  * @param data                  The data to write.
169  * @param len                   The number of bytes to write.
170  * @param arg                   Optional streamer argument.
171  *
172  * @return                      0 on success, MGMT_ERR_[...] code on failure.
173  */
174 typedef int mgmt_write_at_fn(struct cbor_encoder_writer *writer, size_t offset,
175                              const void *data, size_t len, void *arg);
176 
177 /** @typedef mgmt_init_reader_fn
178  * @brief Initializes a CBOR reader with the specified buffer.
179  *
180  * @param reader                The reader to initialize.
181  * @param buf                   The buffer to configure the reader with.
182  * @param arg                   Optional streamer argument.
183  *
184  * @return                      0 on success, MGMT_ERR_[...] code on failure.
185  */
186 typedef int mgmt_init_reader_fn(struct cbor_decoder_reader *reader, void *buf,
187                                 void *arg);
188 
189 /** @typedef mgmt_init_writer_fn
190  * @brief Initializes a CBOR writer with the specified buffer.
191  *
192  * @param writer                The writer to initialize.
193  * @param buf                   The buffer to configure the writer with.
194  * @param arg                   Optional streamer argument.
195  *
196  * @return                      0 on success, MGMT_ERR_[...] code on failure.
197  */
198 typedef int mgmt_init_writer_fn(struct cbor_encoder_writer *writer, void *buf,
199                                 void *arg);
200 
201 /** @typedef mgmt_init_writer_fn
202  * @brief Frees the specified buffer.
203  *
204  * @param buf                   The buffer to free.
205  * @param arg                   Optional streamer argument.
206  */
207 typedef void mgmt_free_buf_fn(void *buf, void *arg);
208 
209 /**
210  * @brief Configuration for constructing a mgmt_streamer object.
211  */
212 struct mgmt_streamer_cfg {
213     mgmt_alloc_rsp_fn *alloc_rsp;
214     mgmt_trim_front_fn *trim_front;
215     mgmt_reset_buf_fn *reset_buf;
216     mgmt_write_at_fn *write_at;
217     mgmt_init_reader_fn *init_reader;
218     mgmt_init_writer_fn *init_writer;
219     mgmt_free_buf_fn *free_buf;
220 };
221 
222 /**
223  * @brief Decodes requests and encodes responses for any mcumgr protocol.
224  */
225 struct mgmt_streamer {
226     const struct mgmt_streamer_cfg *cfg;
227     void *cb_arg;
228     struct cbor_decoder_reader *reader;
229     struct cbor_encoder_writer *writer;
230 };
231 
232 /**
233  * @brief Context required by command handlers for parsing requests and writing
234  *        responses.
235  */
236 struct mgmt_ctxt {
237     struct CborEncoder encoder;
238     struct CborParser parser;
239     struct CborValue it;
240 };
241 
242 /** @typedef mgmt_handler_fn
243  * @brief Processes a request and writes the corresponding response.
244  *
245  * A separate handler is required for each supported op-ID pair.
246  *
247  * @param ctxt                  The mcumgr context to use.
248  *
249  * @return                      0 if a response was successfully encoded,
250  *                                  MGMT_ERR_[...] code on failure.
251  */
252 typedef int mgmt_handler_fn(struct mgmt_ctxt *ctxt);
253 
254 /**
255  * @brief Read handler and write handler for a single command ID.
256  */
257 struct mgmt_handler {
258     mgmt_handler_fn *mh_read;
259     mgmt_handler_fn *mh_write;
260 };
261 
262 /**
263  * @brief A collection of handlers for an entire command group.
264  */
265 struct mgmt_group {
266     /** Points to the next group in the list. */
267     struct mgmt_group *mg_next;
268 
269     /** Array of handlers; one entry per command ID. */
270     const struct mgmt_handler *mg_handlers;
271     uint16_t mg_handlers_count;
272 
273     /* The numeric ID of this group. */
274     uint16_t mg_group_id;
275 };
276 
277 /**
278  * @brief Uses the specified streamer to allocates a response buffer.
279  *
280  * If a source buf is provided, its user data is copied into the new buffer.
281  *
282  * @param streamer              The streamer providing the callback.
283  * @param src_buf               An optional source buffer to copy user data
284  *                                  from.
285  *
286  * @return                      Newly-allocated buffer on success
287  *                              NULL on failure.
288  */
289 void *mgmt_streamer_alloc_rsp(struct mgmt_streamer *streamer,
290                               const void *src_buf);
291 
292 /**
293  * @brief Uses the specified streamer to trim data from the front of a buffer.
294  *
295  * If the amount to trim exceeds the size of the buffer, the buffer is
296  * truncated to a length of 0.
297  *
298  * @param streamer              The streamer providing the callback.
299  * @param buf                   The buffer to trim.
300  * @param len                   The number of bytes to remove.
301  */
302 void mgmt_streamer_trim_front(struct mgmt_streamer *streamer, void *buf,
303                               size_t len);
304 
305 /**
306  * @brief Uses the specified streamer to reset a buffer to a length of 0.
307  *
308  * The buffer's user data remains, but its payload is cleared.
309  *
310  * @param streamer              The streamer providing the callback.
311  * @param buf                   The buffer to reset.
312  */
313 void mgmt_streamer_reset_buf(struct mgmt_streamer *streamer, void *buf);
314 
315 /**
316  * @brief Uses the specified streamer to write data to a CBOR encoder.
317  *
318  * Any existing data at the specified offset is overwritten by the new data.
319  * Any new data that extends past the buffer's current length is appended.
320  *
321  * @param streamer              The streamer providing the callback.
322  * @param writer                The encoder to write to.
323  * @param offset                The byte offset to write to,
324  * @param data                  The data to write.
325  * @param len                   The number of bytes to write.
326  *
327  * @return                      0 on success, MGMT_ERR_[...] code on failure.
328  */
329 int mgmt_streamer_write_at(struct mgmt_streamer *streamer, size_t offset,
330                            const void *data, int len);
331 
332 /**
333  * @brief Uses the specified streamer to initialize a CBOR reader.
334  *
335  * @param streamer              The streamer providing the callback.
336  * @param reader                The reader to initialize.
337  * @param buf                   The buffer to configure the reader with.
338  *
339  * @return                      0 on success, MGMT_ERR_[...] code on failure.
340  */
341 int mgmt_streamer_init_reader(struct mgmt_streamer *streamer, void *buf);
342 
343 /**
344  * @brief Uses the specified streamer to initializes a CBOR writer.
345  *
346  * @param streamer              The streamer providing the callback.
347  * @param writer                The writer to initialize.
348  * @param buf                   The buffer to configure the writer with.
349  *
350  * @return                      0 on success, MGMT_ERR_[...] code on failure.
351  */
352 int mgmt_streamer_init_writer(struct mgmt_streamer *streamer, void *buf);
353 
354 /**
355  * @brief Uses the specified streamer to free a buffer.
356  *
357  * @param streamer              The streamer providing the callback.
358  * @param buf                   The buffer to free.
359  */
360 void mgmt_streamer_free_buf(struct mgmt_streamer *streamer, void *buf);
361 
362 /**
363  * @brief Registers a full command group.
364  *
365  * @param group                 The group to register.
366  */
367 void mgmt_register_group(struct mgmt_group *group);
368 
369 /**
370  * @brief Unregisters a full command group.
371  *
372  * @param group                 The group to register.
373  */
374 void
375 mgmt_unregister_group(struct mgmt_group *group);
376 
377 /**
378  * @brief Finds a registered command handler.
379  *
380  * @param group_id              The group of the command to find.
381  * @param command_id            The ID of the command to find.
382  *
383  * @return                      The requested command handler on success;
384  *                              NULL on failure.
385  */
386 const struct mgmt_handler *mgmt_find_handler(uint16_t group_id,
387                                              uint16_t command_id);
388 
389 /**
390  * @brief Encodes a response status into the specified management context.
391  *
392  * @param ctxt                  The management context to encode into.
393  * @param status                The response status to write.
394  *
395  * @return                      0 on success, MGMT_ERR_[...] code on failure.
396  */
397 int mgmt_write_rsp_status(struct mgmt_ctxt *ctxt, int status);
398 
399 /**
400  * @brief Initializes a management context object with the specified streamer.
401  *
402  * @param ctxt                  The context object to initialize.
403  * @param streamer              The streamer that will be used with the
404  *                                  context.
405  *
406  * @return                      0 on success, MGMT_ERR_[...] code on failure.
407  */
408 int mgmt_ctxt_init(struct mgmt_ctxt *ctxt, struct mgmt_streamer *streamer);
409 
410 /**
411  * @brief Converts a CBOR status code to a MGMT_ERR_[...] code.
412  *
413  * @param cbor_status           The CBOR status code to convert.
414  *
415  * @return                      The corresponding MGMT_ERR_[,,,] code.
416  */
417 int mgmt_err_from_cbor(int cbor_status);
418 
419 /**
420  * @brief Byte-swaps an mcumgr header from network to host byte order.
421  *
422  * @param hdr                   The mcumgr header to byte-swap.
423  */
424 void mgmt_ntoh_hdr(struct mgmt_hdr *hdr);
425 
426 /**
427  * @brief Byte-swaps an mcumgr header from host to network byte order.
428  *
429  * @param hdr                   The mcumgr header to byte-swap.
430  */
431 void mgmt_hton_hdr(struct mgmt_hdr *hdr);
432 
433 /**
434  * @brief Register event callback function.
435  *
436  * @param cb                    Callback function.
437  */
438 void mgmt_register_evt_cb(mgmt_on_evt_cb *cb);
439 
440 /**
441  * @brief This function is called to notify about mgmt event.
442  *
443  * @param opcode                MGMT_EVT_OP_[...].
444  * @param group                 MGMT_GROUP_ID_[...].
445  * @param id                    Message ID within group.
446  * @param arg                   Optional event argument.
447  */
448 void mgmt_evt(uint8_t opcode, uint16_t group, uint8_t id, void *arg);
449 
450 #ifdef __cplusplus
451 }
452 #endif
453 
454 #endif /* MGMT_MGMT_H_ */
455