Skip to main content

nrf_modem/
error.rs

1use core::{fmt::Display, str::Utf8Error};
2
3use at_commands::parser::ParseError;
4
5use crate::socket::SocketOptionError;
6
7#[derive(Debug, Clone)]
8#[cfg_attr(feature = "defmt", derive(defmt::Format))]
9#[non_exhaustive]
10/// The global error type of this crate
11pub enum Error {
12    /// An operation was tried for which the modem needs to be initialized, but the modem is not yet initialized
13    ModemNotInitialized,
14    /// There can only be one Gnss instance, yet a second was requested
15    GnssAlreadyTaken,
16    /// An unkown error occured. Check [nrf_errno.h](https://github.com/nrfconnect/sdk-nrfxlib/blob/main/nrf_modem/include/nrf_errno.h) to see what it means.
17    ///
18    /// Sometimes the sign is flipped, but ignore that and just look at the number.
19    NrfError(isize),
20    BufferTooSmall(Option<usize>),
21    OutOfMemory,
22    AtParseError(ParseError),
23    InvalidSystemModeConfig,
24    StringNotNulTerminated,
25    Utf8Error,
26    LteRegistrationDenied,
27    SimFailure,
28    UnexpectedAtResponse,
29    HostnameNotAscii,
30    HostnameTooLong,
31    AddressNotFound,
32    SocketOptionError(SocketOptionError),
33    /// The ongoing operation has been cancelled by the user
34    OperationCancelled,
35    SmsNumberNotAscii,
36    Disconnected,
37    TooManyLteLinks,
38    TooManyUiccLinks,
39    InternalRuntimeMutexLocked,
40    /// The given memory layout falls outside of the acceptable range
41    BadMemoryLayout,
42    ModemAlreadyInitialized,
43    /// The modem has a maximum packet size of 2kb when receiving TLS packets
44    TlsPacketTooBig,
45    /// tcp and udp TLS connections require at least one security tag to identify the server certificate
46    NoSecurityTag,
47    #[cfg(feature = "dns-async")]
48    DomainNameTooLong,
49    #[cfg(feature = "dns-async")]
50    DnsCacheOverflow,
51    #[cfg(feature = "dns-async")]
52    DnsHeaderBufferOverflow,
53    #[cfg(feature = "dns-async")]
54    DnsQuestionBufferOverflow,
55    #[cfg(feature = "dns-async")]
56    DnsSocketTimeout,
57    #[cfg(feature = "dns-async")]
58    DnsSocketError,
59    #[cfg(feature = "dns-async")]
60    DnsParseFailed,
61    #[cfg(feature = "embedded-nal-async")]
62    ReverseDnsLookupNotSupported,
63    /// The address returned by the modem couldn't be parsed
64    #[cfg(feature = "embassy-net")]
65    AddrParseError,
66}
67
68impl Display for Error {
69    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
70        write!(f, "{self:?}")
71    }
72}
73
74impl core::error::Error for Error {}
75
76impl embedded_io_async::Error for Error {
77    fn kind(&self) -> embedded_io_async::ErrorKind {
78        match self {
79            Error::ModemNotInitialized => embedded_io_async::ErrorKind::Other,
80            Error::GnssAlreadyTaken => embedded_io_async::ErrorKind::Other,
81            Error::NrfError(_) => embedded_io_async::ErrorKind::Other,
82            Error::BufferTooSmall(_) => embedded_io_async::ErrorKind::OutOfMemory,
83            Error::OutOfMemory => embedded_io_async::ErrorKind::OutOfMemory,
84            Error::AtParseError(_) => embedded_io_async::ErrorKind::Other,
85            Error::InvalidSystemModeConfig => embedded_io_async::ErrorKind::Other,
86            Error::StringNotNulTerminated => embedded_io_async::ErrorKind::InvalidInput,
87            Error::Utf8Error => embedded_io_async::ErrorKind::InvalidInput,
88            Error::LteRegistrationDenied => embedded_io_async::ErrorKind::Other,
89            Error::SimFailure => embedded_io_async::ErrorKind::Other,
90            Error::UnexpectedAtResponse => embedded_io_async::ErrorKind::Other,
91            Error::HostnameNotAscii => embedded_io_async::ErrorKind::InvalidInput,
92            Error::HostnameTooLong => embedded_io_async::ErrorKind::InvalidInput,
93            Error::AddressNotFound => embedded_io_async::ErrorKind::Other,
94            Error::SocketOptionError(_) => embedded_io_async::ErrorKind::Other,
95            Error::OperationCancelled => embedded_io_async::ErrorKind::Other,
96            Error::SmsNumberNotAscii => embedded_io_async::ErrorKind::Other,
97            Error::Disconnected => embedded_io_async::ErrorKind::ConnectionReset,
98            Error::TooManyLteLinks => embedded_io_async::ErrorKind::Other,
99            Error::TooManyUiccLinks => embedded_io_async::ErrorKind::Other,
100            Error::InternalRuntimeMutexLocked => embedded_io_async::ErrorKind::Other,
101            Error::BadMemoryLayout => embedded_io_async::ErrorKind::Other,
102            Error::ModemAlreadyInitialized => embedded_io_async::ErrorKind::Other,
103            Error::TlsPacketTooBig => embedded_io_async::ErrorKind::Other,
104            Error::NoSecurityTag => embedded_io_async::ErrorKind::Other,
105            #[cfg(feature = "dns-async")]
106            Error::DomainNameTooLong => embedded_io_async::ErrorKind::InvalidInput,
107            #[cfg(feature = "dns-async")]
108            Error::DnsCacheOverflow => embedded_io_async::ErrorKind::Other,
109            #[cfg(feature = "dns-async")]
110            Error::DnsHeaderBufferOverflow => embedded_io_async::ErrorKind::Other,
111            #[cfg(feature = "dns-async")]
112            Error::DnsQuestionBufferOverflow => embedded_io_async::ErrorKind::Other,
113            #[cfg(feature = "dns-async")]
114            Error::DnsSocketTimeout => embedded_io_async::ErrorKind::TimedOut,
115            #[cfg(feature = "dns-async")]
116            Error::DnsSocketError => embedded_io_async::ErrorKind::Other,
117            #[cfg(feature = "dns-async")]
118            Error::DnsParseFailed => embedded_io_async::ErrorKind::Other,
119            #[cfg(feature = "embedded-nal-async")]
120            Error::ReverseDnsLookupNotSupported => embedded_io_async::ErrorKind::Unsupported,
121            #[cfg(feature = "embassy-net")]
122            Error::AddrParseError => embedded_io_async::ErrorKind::InvalidInput,
123        }
124    }
125}
126
127/// Helper to convert [`nrfxlib_sys`] numeric errors into idiomatic results.
128pub trait ErrorSource {
129    /// Turns a value of 0 into an [`Ok(())`][Result::Ok], whereas any other value gets turned into
130    /// [`Error::NrfError`].
131    fn into_result(self) -> Result<(), Error>;
132}
133
134impl ErrorSource for isize {
135    fn into_result(self) -> Result<(), Error> {
136        if self == 0 {
137            return Ok(());
138        }
139
140        Err(Error::NrfError(self))
141    }
142}
143impl ErrorSource for i32 {
144    fn into_result(self) -> Result<(), Error> {
145        if self == 0 {
146            return Ok(());
147        }
148
149        Err(Error::NrfError(self as isize))
150    }
151}
152
153impl From<ParseError> for Error {
154    fn from(e: ParseError) -> Self {
155        Error::AtParseError(e)
156    }
157}
158
159impl From<Utf8Error> for Error {
160    fn from(_: Utf8Error) -> Self {
161        Self::Utf8Error
162    }
163}
164
165impl From<SocketOptionError> for Error {
166    fn from(e: SocketOptionError) -> Self {
167        Self::SocketOptionError(e)
168    }
169}