Skip to main content

firefly_hal/
errors.rs

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