Skip to main content

mcumgr_toolkit/
smp_errors.rs

1use strum::{Display, FromRepr};
2
3use crate::MCUmgrGroup;
4
5/// Errors the device can respond with when trying to execute an SMP command.
6///
7/// More information can be found [here](https://docs.zephyrproject.org/latest/services/device_mgmt/smp_protocol.html#minimal-response-smp-data).
8#[derive(Debug, Clone, Eq, PartialEq)]
9pub enum DeviceError {
10    /// MCUmgr SMP v1 error codes
11    V1 {
12        /// Error code
13        rc: i32,
14        /// Optional string that clarifies reason for an error
15        rsn: Option<String>,
16    },
17    /// MCUmgr SMP v2 error codes
18    V2 {
19        /// Group id
20        group: u16,
21        /// Group based error code
22        rc: i32,
23    },
24}
25
26fn v2_err_to_string(group: u16, rc: i32) -> Option<String> {
27    match MCUmgrGroup::from_repr(group)? {
28        MCUmgrGroup::MGMT_GROUP_ID_ENUM => EnumMgmtErrCode::from_repr(rc).map(|x| x.to_string()),
29        MCUmgrGroup::MGMT_GROUP_ID_FS => FsMgmtErrCode::from_repr(rc).map(|x| x.to_string()),
30        MCUmgrGroup::MGMT_GROUP_ID_IMAGE => ImgMgmtErrCode::from_repr(rc).map(|x| x.to_string()),
31        MCUmgrGroup::MGMT_GROUP_ID_OS => OsMgmtErrCode::from_repr(rc).map(|x| x.to_string()),
32        MCUmgrGroup::MGMT_GROUP_ID_SETTINGS => {
33            SettingsMgmtRetCode::from_repr(rc).map(|x| x.to_string())
34        }
35        MCUmgrGroup::MGMT_GROUP_ID_SHELL => ShellMgmtErrCode::from_repr(rc).map(|x| x.to_string()),
36        MCUmgrGroup::MGMT_GROUP_ID_STAT => StatMgmtErrCode::from_repr(rc).map(|x| x.to_string()),
37        MCUmgrGroup::ZEPHYR_MGMT_GRP_BASIC => {
38            ZephyrBasicGroupErrCode::from_repr(rc).map(|x| x.to_string())
39        }
40        _ => None,
41    }
42}
43
44impl std::fmt::Display for DeviceError {
45    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46        match self {
47            DeviceError::V1 { rc, rsn } => {
48                if let Some(rsn) = rsn {
49                    write!(f, "{}: {}", MCUmgrErr::err_to_string(*rc), rsn)
50                } else {
51                    write!(f, "{}", MCUmgrErr::err_to_string(*rc))
52                }
53            }
54            DeviceError::V2 { group, rc } => match v2_err_to_string(*group, *rc) {
55                Some(msg) => f.write_str(&msg),
56                None => write!(f, "group={group},rc={rc}"),
57            },
58        }
59    }
60}
61
62/// See [`enum mcumgr_err_t`](https://docs.zephyrproject.org/latest/doxygen/html/mgmt__defines_8h.html).
63#[derive(FromRepr, Display, Debug, Copy, Clone, PartialEq, Eq)]
64#[repr(i32)]
65#[allow(non_camel_case_types)]
66pub enum MCUmgrErr {
67    /** No error (success). */
68    MGMT_ERR_EOK = 0,
69
70    /** Unknown error. */
71    MGMT_ERR_EUNKNOWN,
72
73    /** Insufficient memory (likely not enough space for CBOR object). */
74    MGMT_ERR_ENOMEM,
75
76    /** Error in input value. */
77    MGMT_ERR_EINVAL,
78
79    /** Operation timed out. */
80    MGMT_ERR_ETIMEOUT,
81
82    /** No such file/entry. */
83    MGMT_ERR_ENOENT,
84
85    /** Current state disallows command. */
86    MGMT_ERR_EBADSTATE,
87
88    /** Response too large. */
89    MGMT_ERR_EMSGSIZE,
90
91    /** Command not supported. */
92    MGMT_ERR_ENOTSUP,
93
94    /** Corrupt */
95    MGMT_ERR_ECORRUPT,
96
97    /** Command blocked by processing of other command */
98    MGMT_ERR_EBUSY,
99
100    /** Access to specific function, command or resource denied */
101    MGMT_ERR_EACCESSDENIED,
102
103    /** Requested SMP MCUmgr protocol version is not supported (too old) */
104    MGMT_ERR_UNSUPPORTED_TOO_OLD,
105
106    /** Requested SMP MCUmgr protocol version is not supported (too new) */
107    MGMT_ERR_UNSUPPORTED_TOO_NEW,
108
109    /** User errors defined from 256 onwards */
110    MGMT_ERR_EPERUSER = 256,
111}
112impl MCUmgrErr {
113    /// Converts a raw error code to a string
114    pub fn err_to_string(err: i32) -> String {
115        const PERUSER: MCUmgrErr = MCUmgrErr::MGMT_ERR_EPERUSER;
116        if err < PERUSER as i32 {
117            if let Some(err_enum) = Self::from_repr(err) {
118                format!("{err_enum}")
119            } else {
120                format!("MGMT_ERR_UNKNOWN({err})")
121            }
122        } else {
123            format!("{PERUSER}({err})")
124        }
125    }
126}
127
128/// See `enum settings_mgmt_ret_code_t`.
129#[derive(FromRepr, Display, Debug, Copy, Clone, PartialEq, Eq)]
130#[repr(i32)]
131#[allow(non_camel_case_types)]
132pub enum SettingsMgmtRetCode {
133    /** No error, this is implied if there is no ret value in the response. */
134    SETTINGS_MGMT_ERR_OK = 0,
135
136    /** Unknown error occurred. */
137    SETTINGS_MGMT_ERR_UNKNOWN,
138
139    /** The provided key name is too long to be used. */
140    SETTINGS_MGMT_ERR_KEY_TOO_LONG,
141
142    /** The provided key name does not exist. */
143    SETTINGS_MGMT_ERR_KEY_NOT_FOUND,
144
145    /** The provided key name does not support being read. */
146    SETTINGS_MGMT_ERR_READ_NOT_SUPPORTED,
147
148    /** The provided root key name does not exist. */
149    SETTINGS_MGMT_ERR_ROOT_KEY_NOT_FOUND,
150
151    /** The provided key name does not support being written. */
152    SETTINGS_MGMT_ERR_WRITE_NOT_SUPPORTED,
153
154    /** The provided key name does not support being deleted. */
155    SETTINGS_MGMT_ERR_DELETE_NOT_SUPPORTED,
156
157    /** The provided key name does not support being saved. */
158    SETTINGS_MGMT_ERR_SAVE_NOT_SUPPORTED,
159}
160
161/// See `enum fs_mgmt_err_code_t`.
162#[derive(FromRepr, Display, Debug, Copy, Clone, PartialEq, Eq)]
163#[repr(i32)]
164#[allow(non_camel_case_types)]
165pub enum FsMgmtErrCode {
166    /** No error (success). */
167    FS_MGMT_ERR_OK = 0,
168
169    /** Unknown error occurred. */
170    FS_MGMT_ERR_UNKNOWN,
171
172    /** The specified file name is not valid. */
173    FS_MGMT_ERR_FILE_INVALID_NAME,
174
175    /** The specified file does not exist. */
176    FS_MGMT_ERR_FILE_NOT_FOUND,
177
178    /** The specified file is a directory, not a file. */
179    FS_MGMT_ERR_FILE_IS_DIRECTORY,
180
181    /** Error occurred whilst attempting to open a file. */
182    FS_MGMT_ERR_FILE_OPEN_FAILED,
183
184    /** Error occurred whilst attempting to seek to an offset in a file. */
185    FS_MGMT_ERR_FILE_SEEK_FAILED,
186
187    /** Error occurred whilst attempting to read data from a file. */
188    FS_MGMT_ERR_FILE_READ_FAILED,
189
190    /** Error occurred whilst trying to truncate file. */
191    FS_MGMT_ERR_FILE_TRUNCATE_FAILED,
192
193    /** Error occurred whilst trying to delete file. */
194    FS_MGMT_ERR_FILE_DELETE_FAILED,
195
196    /** Error occurred whilst attempting to write data to a file. */
197    FS_MGMT_ERR_FILE_WRITE_FAILED,
198
199    /**
200     * The specified data offset is not valid, this could indicate that the file on the device
201     * has changed since the previous command. The length of the current file on the device is
202     * returned as "len", the user application needs to decide how to handle this (e.g. the
203     * hash of the file could be requested and compared with the hash of the length of the
204     * file being uploaded to see if they match or not).
205     */
206    FS_MGMT_ERR_FILE_OFFSET_NOT_VALID,
207
208    /** The requested offset is larger than the size of the file on the device. */
209    FS_MGMT_ERR_FILE_OFFSET_LARGER_THAN_FILE,
210
211    /** The requested checksum or hash type was not found or is not supported by this build. */
212    FS_MGMT_ERR_CHECKSUM_HASH_NOT_FOUND,
213
214    /** The specified mount point was not found or is not mounted. */
215    FS_MGMT_ERR_MOUNT_POINT_NOT_FOUND,
216
217    /** The specified mount point is that of a read-only filesystem. */
218    FS_MGMT_ERR_READ_ONLY_FILESYSTEM,
219
220    /** The operation cannot be performed because the file is empty with no contents. */
221    FS_MGMT_ERR_FILE_EMPTY,
222}
223
224/// See `enum img_mgmt_err_code_t`.
225#[derive(FromRepr, Display, Debug, Copy, Clone, PartialEq, Eq)]
226#[repr(i32)]
227#[allow(non_camel_case_types)]
228pub enum ImgMgmtErrCode {
229    /** No error, this is implied if there is no ret value in the response */
230    IMG_MGMT_ERR_OK = 0,
231
232    /** Unknown error occurred. */
233    IMG_MGMT_ERR_UNKNOWN,
234
235    /** Failed to query flash area configuration. */
236    IMG_MGMT_ERR_FLASH_CONFIG_QUERY_FAIL,
237
238    /** There is no image in the slot. */
239    IMG_MGMT_ERR_NO_IMAGE,
240
241    /** The image in the slot has no TLVs (tag, length, value). */
242    IMG_MGMT_ERR_NO_TLVS,
243
244    /** The image in the slot has an invalid TLV type and/or length. */
245    IMG_MGMT_ERR_INVALID_TLV,
246
247    /** The image in the slot has multiple hash TLVs, which is invalid. */
248    IMG_MGMT_ERR_TLV_MULTIPLE_HASHES_FOUND,
249
250    /** The image in the slot has an invalid TLV size. */
251    IMG_MGMT_ERR_TLV_INVALID_SIZE,
252
253    /** The image in the slot does not have a hash TLV, which is required.  */
254    IMG_MGMT_ERR_HASH_NOT_FOUND,
255
256    /** There is no free slot to place the image. */
257    IMG_MGMT_ERR_NO_FREE_SLOT,
258
259    /** Flash area opening failed. */
260    IMG_MGMT_ERR_FLASH_OPEN_FAILED,
261
262    /** Flash area reading failed. */
263    IMG_MGMT_ERR_FLASH_READ_FAILED,
264
265    /** Flash area writing failed. */
266    IMG_MGMT_ERR_FLASH_WRITE_FAILED,
267
268    /** Flash area erase failed. */
269    IMG_MGMT_ERR_FLASH_ERASE_FAILED,
270
271    /** The provided slot is not valid. */
272    IMG_MGMT_ERR_INVALID_SLOT,
273
274    /** Insufficient heap memory (malloc failed). */
275    IMG_MGMT_ERR_NO_FREE_MEMORY,
276
277    /** The flash context is already set. */
278    IMG_MGMT_ERR_FLASH_CONTEXT_ALREADY_SET,
279
280    /** The flash context is not set. */
281    IMG_MGMT_ERR_FLASH_CONTEXT_NOT_SET,
282
283    /** The device for the flash area is NULL. */
284    IMG_MGMT_ERR_FLASH_AREA_DEVICE_NULL,
285
286    /** The offset for a page number is invalid. */
287    IMG_MGMT_ERR_INVALID_PAGE_OFFSET,
288
289    /** The offset parameter was not provided and is required. */
290    IMG_MGMT_ERR_INVALID_OFFSET,
291
292    /** The length parameter was not provided and is required. */
293    IMG_MGMT_ERR_INVALID_LENGTH,
294
295    /** The image length is smaller than the size of an image header. */
296    IMG_MGMT_ERR_INVALID_IMAGE_HEADER,
297
298    /** The image header magic value does not match the expected value. */
299    IMG_MGMT_ERR_INVALID_IMAGE_HEADER_MAGIC,
300
301    /** The hash parameter provided is not valid. */
302    IMG_MGMT_ERR_INVALID_HASH,
303
304    /** The image load address does not match the address of the flash area. */
305    IMG_MGMT_ERR_INVALID_FLASH_ADDRESS,
306
307    /** Failed to get version of currently running application. */
308    IMG_MGMT_ERR_VERSION_GET_FAILED,
309
310    /** The currently running application is newer than the version being uploaded. */
311    IMG_MGMT_ERR_CURRENT_VERSION_IS_NEWER,
312
313    /** There is already an image operating pending. */
314    IMG_MGMT_ERR_IMAGE_ALREADY_PENDING,
315
316    /** The image vector table is invalid. */
317    IMG_MGMT_ERR_INVALID_IMAGE_VECTOR_TABLE,
318
319    /** The image it too large to fit. */
320    IMG_MGMT_ERR_INVALID_IMAGE_TOO_LARGE,
321
322    /** The amount of data sent is larger than the provided image size. */
323    IMG_MGMT_ERR_INVALID_IMAGE_DATA_OVERRUN,
324
325    /** Confirmation of image has been denied */
326    IMG_MGMT_ERR_IMAGE_CONFIRMATION_DENIED,
327
328    /** Setting test to active slot is not allowed */
329    IMG_MGMT_ERR_IMAGE_SETTING_TEST_TO_ACTIVE_DENIED,
330
331    /** Current active slot for image cannot be determined */
332    IMG_MGMT_ERR_ACTIVE_SLOT_NOT_KNOWN,
333}
334
335/// See `enum os_mgmt_err_code_t`.
336#[derive(FromRepr, Display, Debug, Copy, Clone, PartialEq, Eq)]
337#[repr(i32)]
338#[allow(non_camel_case_types)]
339pub enum OsMgmtErrCode {
340    /** No error, this is implied if there is no ret value in the response */
341    OS_MGMT_ERR_OK = 0,
342
343    /** Unknown error occurred. */
344    OS_MGMT_ERR_UNKNOWN,
345
346    /** The provided format value is not valid. */
347    OS_MGMT_ERR_INVALID_FORMAT,
348
349    /** Query was not recognized. */
350    OS_MGMT_ERR_QUERY_YIELDS_NO_ANSWER,
351
352    /** RTC is not set */
353    OS_MGMT_ERR_RTC_NOT_SET,
354
355    /** RTC command failed */
356    OS_MGMT_ERR_RTC_COMMAND_FAILED,
357
358    /** Query was recognized but there is no valid value for the response. */
359    OS_MGMT_ERR_QUERY_RESPONSE_VALUE_NOT_VALID,
360}
361
362/// See `enum shell_mgmt_err_code_t`.
363#[derive(FromRepr, Display, Debug, Copy, Clone, PartialEq, Eq)]
364#[repr(i32)]
365#[allow(non_camel_case_types)]
366pub enum ShellMgmtErrCode {
367    /** No error, this is implied if there is no ret value in the response */
368    SHELL_MGMT_ERR_OK = 0,
369
370    /** Unknown error occurred. */
371    SHELL_MGMT_ERR_UNKNOWN,
372
373    /** The provided command to execute is too long. */
374    SHELL_MGMT_ERR_COMMAND_TOO_LONG,
375
376    /** No command to execute was provided. */
377    SHELL_MGMT_ERR_EMPTY_COMMAND,
378}
379
380/// See `enum stat_mgmt_err_code_t`.
381#[derive(FromRepr, Display, Debug, Copy, Clone, PartialEq, Eq)]
382#[repr(i32)]
383#[allow(non_camel_case_types)]
384pub enum StatMgmtErrCode {
385    /** No error, this is implied if there is no ret value in the response */
386    STAT_MGMT_ERR_OK = 0,
387
388    /** Unknown error occurred. */
389    STAT_MGMT_ERR_UNKNOWN,
390
391    /** The provided statistic group name was not found. */
392    STAT_MGMT_ERR_INVALID_GROUP,
393
394    /** The provided statistic name was not found. */
395    STAT_MGMT_ERR_INVALID_STAT_NAME,
396
397    /** The size of the statistic cannot be handled. */
398    STAT_MGMT_ERR_INVALID_STAT_SIZE,
399
400    /** Walk through of statistics was aborted. */
401    STAT_MGMT_ERR_WALK_ABORTED,
402}
403
404/// See `enum enum_mgmt_err_code_t`.
405#[derive(FromRepr, Display, Debug, Copy, Clone, PartialEq, Eq)]
406#[repr(i32)]
407#[allow(non_camel_case_types)]
408pub enum EnumMgmtErrCode {
409    /** No error, this is implied if there is no ret value in the response */
410    ENUM_MGMT_ERR_OK = 0,
411
412    /** Unknown error occurred. */
413    ENUM_MGMT_ERR_UNKNOWN,
414
415    /** Too many entries were provided. */
416    ENUM_MGMT_ERR_TOO_MANY_GROUP_ENTRIES,
417
418    /** Insufficient heap memory to store entry data. */
419    ENUM_MGMT_ERR_INSUFFICIENT_HEAP_FOR_ENTRIES,
420
421    /** Provided index is larger than the number of supported grouped. */
422    ENUM_MGMT_ERR_INDEX_TOO_LARGE,
423}
424
425/// See `enum zephyr_basic_group_err_code_t`.
426#[derive(FromRepr, Display, Debug, Copy, Clone, PartialEq, Eq)]
427#[repr(i32)]
428#[allow(non_camel_case_types)]
429pub enum ZephyrBasicGroupErrCode {
430    /** No error, this is implied if there is no ret value in the response */
431    ZEPHYRBASIC_MGMT_ERR_OK = 0,
432
433    /** Unknown error occurred. */
434    ZEPHYRBASIC_MGMT_ERR_UNKNOWN,
435
436    /** Opening of the flash area has failed. */
437    ZEPHYRBASIC_MGMT_ERR_FLASH_OPEN_FAILED,
438
439    /** Querying the flash area parameters has failed. */
440    ZEPHYRBASIC_MGMT_ERR_FLASH_CONFIG_QUERY_FAIL,
441
442    /** Erasing the flash area has failed. */
443    ZEPHYRBASIC_MGMT_ERR_FLASH_ERASE_FAILED,
444}