firefly_hal/
errors.rs

1use core::fmt;
2
3pub enum FSError {
4    /// The underlying block device threw an error.
5    DeviceError(alloc::string::String),
6    /// The filesystem is badly formatted (or this code is buggy).
7    FormatError(&'static str),
8    /// The given `VolumeIdx` was bad,
9    NoSuchVolume,
10    /// The given filename was bad
11    #[cfg(target_os = "none")]
12    FilenameError(embedded_sdmmc::FilenameError),
13    /// Out of memory opening volumes
14    TooManyOpenVolumes,
15    /// Out of memory opening directories
16    TooManyOpenDirs,
17    /// Out of memory opening files
18    TooManyOpenFiles,
19    /// Bad handle given
20    BadHandle,
21    /// That file or directory doesn't exist
22    NotFound,
23    /// You can't open a file twice or delete an open file
24    FileAlreadyOpen,
25    /// You can't open a directory twice
26    DirAlreadyOpen,
27    /// You can't open a directory as a file
28    OpenedDirAsFile,
29    /// You can't open a file as a directory
30    OpenedFileAsDir,
31    /// You can't delete a directory as a file
32    DeleteDirAsFile,
33    /// You can't close a volume with open files or directories
34    VolumeStillInUse,
35    /// You can't open a volume twice
36    VolumeAlreadyOpen,
37    /// We can't do that yet
38    Unsupported,
39    /// Tried to read beyond end of file
40    EndOfFile,
41    /// Found a bad cluster
42    BadCluster,
43    /// Error while converting types
44    ConversionError,
45    /// The device does not have enough space for the operation
46    NotEnoughSpace,
47    /// Cluster was not properly allocated by the library
48    AllocationError,
49    /// Jumped to free space during FAT traversing
50    UnterminatedFatChain,
51    /// Tried to open Read-Only file with write mode
52    ReadOnly,
53    /// Tried to create an existing file
54    FileAlreadyExists,
55    /// Bad block size - only 512 byte blocks supported
56    BadBlockSize(u16),
57    /// Bad offset given when seeking
58    InvalidOffset,
59    /// Disk is full
60    DiskFull,
61    /// A directory with that name already exists
62    DirAlreadyExists,
63    // The filesystem tried to gain a lock whilst already locked.
64    Deadlock,
65
66    /// The operation lacked the necessary privileges to complete.
67    PermissionDenied,
68    /// The connection was refused by the remote server.
69    ConnectionRefused,
70    /// The connection was reset by the remote server.
71    ConnectionReset,
72    /// The connection was aborted (terminated) by the remote server.
73    ConnectionAborted,
74    /// The network operation failed because it was not connected yet.
75    NotConnected,
76    /// A socket address could not be bound because the address is already in
77    /// use elsewhere.
78    AddrInUse,
79    /// A nonexistent interface was requested or the requested address was not
80    /// local.
81    AddrNotAvailable,
82    /// The operation failed because a pipe was closed.
83    BrokenPipe,
84    /// A parameter was incorrect.
85    InvalidInput,
86    /// Data not valid for the operation were encountered.
87    ///
88    /// Unlike [`InvalidInput`], this typically means that the operation
89    /// parameters were valid, however the error was caused by malformed
90    /// input data.
91    ///
92    /// For example, a function that reads a file into a string will error with
93    /// `InvalidData` if the file's contents are not valid UTF-8.
94    ///
95    /// [`InvalidInput`]: ErrorKind::InvalidInput
96    InvalidData,
97    /// The I/O operation's timeout expired, causing it to be canceled.
98    TimedOut,
99    /// This operation was interrupted.
100    ///
101    /// Interrupted operations can typically be retried.
102    Interrupted,
103    /// An attempted write could not write any data.
104    WriteZero,
105
106    /// Something else.
107    Other,
108}
109
110#[cfg(target_os = "none")]
111impl<T: fmt::Debug> From<embedded_sdmmc::Error<T>> for FSError {
112    fn from(value: embedded_sdmmc::Error<T>) -> Self {
113        use embedded_sdmmc::Error::*;
114        match value {
115            DeviceError(e) => Self::DeviceError(alloc::format!("{e:?}")),
116            FormatError(e) => Self::FormatError(e),
117            NoSuchVolume => Self::NoSuchVolume,
118            FilenameError(e) => Self::FilenameError(e),
119            TooManyOpenVolumes => Self::TooManyOpenVolumes,
120            TooManyOpenDirs => Self::TooManyOpenDirs,
121            TooManyOpenFiles => Self::TooManyOpenFiles,
122            BadHandle => Self::BadHandle,
123            NotFound => Self::NotFound,
124            FileAlreadyOpen => Self::FileAlreadyOpen,
125            DirAlreadyOpen => Self::DirAlreadyOpen,
126            OpenedDirAsFile => Self::OpenedDirAsFile,
127            OpenedFileAsDir => Self::OpenedFileAsDir,
128            DeleteDirAsFile => Self::DeleteDirAsFile,
129            VolumeStillInUse => Self::VolumeStillInUse,
130            VolumeAlreadyOpen => Self::VolumeAlreadyOpen,
131            Unsupported => Self::Unsupported,
132            EndOfFile => Self::EndOfFile,
133            BadCluster => Self::BadCluster,
134            ConversionError => Self::ConversionError,
135            NotEnoughSpace => Self::NotEnoughSpace,
136            AllocationError => Self::AllocationError,
137            UnterminatedFatChain => Self::UnterminatedFatChain,
138            ReadOnly => Self::ReadOnly,
139            FileAlreadyExists => Self::FileAlreadyExists,
140            BadBlockSize(size) => Self::BadBlockSize(size),
141            InvalidOffset => Self::InvalidOffset,
142            DiskFull => Self::DiskFull,
143            DirAlreadyExists => Self::DirAlreadyExists,
144            LockError => Self::Deadlock,
145        }
146    }
147}
148
149#[cfg(not(target_os = "none"))]
150impl From<std::io::Error> for FSError {
151    fn from(value: std::io::Error) -> Self {
152        value.kind().into()
153    }
154}
155
156#[cfg(not(target_os = "none"))]
157impl From<std::io::ErrorKind> for FSError {
158    fn from(value: std::io::ErrorKind) -> Self {
159        use std::io::ErrorKind::*;
160        match value {
161            NotFound => Self::NotFound,
162            PermissionDenied => Self::PermissionDenied,
163            ConnectionRefused => Self::ConnectionRefused,
164            ConnectionReset => Self::ConnectionReset,
165            ConnectionAborted => Self::ConnectionAborted,
166            NotConnected => Self::NotConnected,
167            AddrInUse => Self::AddrInUse,
168            AddrNotAvailable => Self::AddrNotAvailable,
169            BrokenPipe => Self::BrokenPipe,
170            AlreadyExists => Self::FileAlreadyExists,
171            WouldBlock => Self::Other,
172            InvalidInput => Self::InvalidInput,
173            InvalidData => Self::InvalidData,
174            TimedOut => Self::TimedOut,
175            WriteZero => Self::WriteZero,
176            Interrupted => Self::Interrupted,
177            Unsupported => Self::Unsupported,
178            UnexpectedEof => Self::EndOfFile,
179            OutOfMemory => Self::DiskFull,
180            Other => Self::Other,
181            _ => Self::Other,
182        }
183    }
184}
185
186impl From<embedded_io::ErrorKind> for FSError {
187    fn from(value: embedded_io::ErrorKind) -> Self {
188        use embedded_io::ErrorKind::*;
189        match value {
190            Other => Self::Other,
191            NotFound => Self::NotFound,
192            PermissionDenied => Self::PermissionDenied,
193            ConnectionRefused => Self::ConnectionRefused,
194            ConnectionReset => Self::ConnectionReset,
195            ConnectionAborted => Self::ConnectionAborted,
196            NotConnected => Self::NotConnected,
197            AddrInUse => Self::AddrInUse,
198            AddrNotAvailable => Self::AddrNotAvailable,
199            BrokenPipe => Self::BrokenPipe,
200            AlreadyExists => Self::FileAlreadyExists,
201            InvalidInput => Self::InvalidInput,
202            InvalidData => Self::InvalidData,
203            TimedOut => Self::TimedOut,
204            Interrupted => Self::Interrupted,
205            Unsupported => Self::Unsupported,
206            OutOfMemory => Self::DiskFull,
207            WriteZero => Self::WriteZero,
208            _ => Self::Other,
209        }
210    }
211}
212
213impl fmt::Display for FSError {
214    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
215        use FSError::*;
216        match self {
217            DeviceError(e) => write!(f, "device error: {e}"),
218            FormatError(e) => write!(f, "format error: {e}"),
219            NoSuchVolume => write!(f, "no such volume"),
220            #[cfg(target_os = "none")]
221            FilenameError(e) => write!(f, "filename error: {e:?}"),
222            TooManyOpenVolumes => write!(f, "too many open volumes"),
223            TooManyOpenDirs => write!(f, "too many open dirs"),
224            TooManyOpenFiles => write!(f, "too many open files"),
225            BadHandle => write!(f, "bad handle"),
226            NotFound => write!(f, "not found"),
227            FileAlreadyOpen => write!(f, "file already open"),
228            DirAlreadyOpen => write!(f, "dir already open"),
229            OpenedDirAsFile => write!(f, "opened dir as file"),
230            OpenedFileAsDir => write!(f, "opened file as dir"),
231            DeleteDirAsFile => write!(f, "delete dir as file"),
232            VolumeStillInUse => write!(f, "volume still in use"),
233            VolumeAlreadyOpen => write!(f, "volume already open"),
234            Unsupported => write!(f, "unsupported"),
235            EndOfFile => write!(f, "end of file"),
236            BadCluster => write!(f, "bad cluster"),
237            ConversionError => write!(f, "conversion error"),
238            NotEnoughSpace => write!(f, "not enough space"),
239            AllocationError => write!(f, "allocation error"),
240            UnterminatedFatChain => write!(f, "unterminated fat chain"),
241            ReadOnly => write!(f, "read only"),
242            FileAlreadyExists => write!(f, "file already exists"),
243            BadBlockSize(_) => write!(f, "bad block size"),
244            InvalidOffset => write!(f, "invalid offset"),
245            DiskFull => write!(f, "disk full"),
246            DirAlreadyExists => write!(f, "dir already exists"),
247            PermissionDenied => write!(f, "permission denied"),
248            ConnectionRefused => write!(f, "connection refused"),
249            ConnectionReset => write!(f, "connection reset"),
250            ConnectionAborted => write!(f, "connection aborted"),
251            NotConnected => write!(f, "not connected"),
252            AddrInUse => write!(f, "addr in use"),
253            AddrNotAvailable => write!(f, "addr not available"),
254            BrokenPipe => write!(f, "broken pipe"),
255            InvalidInput => write!(f, "invalid input"),
256            InvalidData => write!(f, "invalid data"),
257            TimedOut => write!(f, "timed out"),
258            Interrupted => write!(f, "interrupted"),
259            WriteZero => write!(f, "write zero"),
260            Deadlock => write!(f, "deadlock"),
261            Other => write!(f, "other"),
262        }
263    }
264}
265
266pub enum NetworkError {
267    NotInitialized,
268    AlreadyInitialized,
269    UnknownPeer,
270    CannotBind,
271    PeerListFull,
272    RecvError,
273    SendError,
274    NetThreadDeallocated,
275    OutMessageTooBig,
276    UnexpectedResp,
277    Decode(postcard::Error),
278    Uart(&'static str),
279    Error(&'static str),
280    OwnedError(alloc::string::String),
281    Other(u32),
282}
283
284impl From<postcard::Error> for NetworkError {
285    fn from(v: postcard::Error) -> Self {
286        Self::Decode(v)
287    }
288}
289
290// #[cfg(target_os = "none")]
291// impl From<embedded_hal_bus::spi::DeviceError<esp_hal::spi::Error, core::convert::Infallible>>
292//     for NetworkError
293// {
294//     fn from(
295//         value: embedded_hal_bus::spi::DeviceError<esp_hal::spi::Error, core::convert::Infallible>,
296//     ) -> Self {
297//         match value {
298//             embedded_hal_bus::spi::DeviceError::Spi(err) => Self::Spi(err),
299//             embedded_hal_bus::spi::DeviceError::Cs(_) => Self::Error("CS error"),
300//         }
301//     }
302// }
303
304#[cfg(target_os = "none")]
305impl From<esp_hal::uart::RxError> for NetworkError {
306    fn from(value: esp_hal::uart::RxError) -> Self {
307        let msg = match value {
308            esp_hal::uart::RxError::FifoOverflowed => "RX FIFO overflowed",
309            esp_hal::uart::RxError::GlitchOccurred => "glitch on RX line",
310            esp_hal::uart::RxError::FrameFormatViolated => "framing error on RX line",
311            esp_hal::uart::RxError::ParityMismatch => "parity error on RX line",
312            _ => "unknown RX error",
313        };
314        Self::Uart(msg)
315    }
316}
317
318#[cfg(target_os = "none")]
319impl From<esp_hal::uart::TxError> for NetworkError {
320    fn from(_: esp_hal::uart::TxError) -> Self {
321        Self::Uart("unknown TX error")
322    }
323}
324
325#[cfg(target_os = "none")]
326impl From<esp_hal::uart::IoError> for NetworkError {
327    fn from(err: esp_hal::uart::IoError) -> Self {
328        match err {
329            esp_hal::uart::IoError::Tx(err) => err.into(),
330            esp_hal::uart::IoError::Rx(err) => err.into(),
331            _ => Self::Uart("unknown IO error"),
332        }
333    }
334}
335
336#[cfg(target_os = "none")]
337impl From<embedded_io::ReadExactError<esp_hal::uart::IoError>> for NetworkError {
338    fn from(err: embedded_io::ReadExactError<esp_hal::uart::IoError>) -> Self {
339        match err {
340            embedded_io::ReadExactError::UnexpectedEof => Self::Uart("unexpected EoF"),
341            embedded_io::ReadExactError::Other(err) => err.into(),
342        }
343    }
344}
345
346impl fmt::Display for NetworkError {
347    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
348        use NetworkError::*;
349        match self {
350            NotInitialized => write!(f, "cannot send messages with Wi-Fi turned off"),
351            AlreadyInitialized => write!(f, "tried to initialize networking twice"),
352            UnknownPeer => write!(f, "cannot send messages to disconnected device"),
353            CannotBind => write!(f, "cannot find free address for networking"),
354            PeerListFull => write!(f, "cannot connect more devices"),
355            RecvError => write!(f, "cannot fetch network message"),
356            SendError => write!(f, "cannot send network message"),
357            NetThreadDeallocated => write!(f, "thread handling networking is already deallocated"),
358            OutMessageTooBig => write!(f, "outgoing message is too big"),
359            UnexpectedResp => write!(f, "unexpected response"),
360            Decode(err) => write!(f, "decode message: {err}"),
361            Uart(err) => write!(f, "SPI error: {err}"),
362            Error(err) => write!(f, "network error: {err}"),
363            OwnedError(err) => write!(f, "network error: {err}"),
364            Other(n) => write!(f, "network error #{n}"),
365        }
366    }
367}