waverave_hackrf/
error.rs

1use std::ops::Range;
2
3use crate::HackRf;
4
5/// An error from operating the HackRF.
6///
7/// Some errors are recoverable:
8///
9/// - `Io` & `Transfer` may just be a failed packet operation on the USB cable,
10///   and can potentially be recovered from without giving up on the HackRF.
11/// - `AddressRange`, `ValueRange`, `TuningRange`, and `InvalidParameter` all
12///   mean the arguments to a function were out of range, and may even provide a
13///   hint of how to fix them.
14/// - `ReturnData` means the HackRF replied to a USB transaction with something
15///   unintelligible. If this is for a bulk transfer during Sweep mode, it
16///   *might* be possible to recover by stopping and re-entering sweep mode, but
17///   most of the time this means something is seriously wrong and
18///   nonrecoverable.
19/// - `ApiVersion` indicates the firmware on the HackRF is too old to support
20///   this function. Bail out, and advise the user to update their HackRF's
21///   firmware.
22#[derive(Debug, thiserror::Error)]
23#[non_exhaustive]
24pub enum Error {
25    /// Underlying OS I/O error.
26    #[error("I/O error")]
27    Io(#[from] std::io::Error),
28
29    /// Transfer error from `nusb`.
30    #[error("USB transfer error")]
31    Transfer(#[from] nusb::transfer::TransferError),
32
33    /// The provided address (usually for register I/O) is out of range.
34    #[error("Address (0x{addr:x}) out of range (0x{}..0x{})", .range.start, .range.end)]
35    #[allow(missing_docs)]
36    AddressRange { range: Range<u32>, addr: u32 },
37
38    /// The provided argument value is out of range.
39    #[error("Value (0x{val:x}) out of range (0x{}..0x{})", .range.start, .range.end)]
40    #[allow(missing_docs)]
41    ValueRange { range: Range<u32>, val: u32 },
42
43    /// The provided tuning frequency is out of range.
44    #[error("Tuning Value ({val:x} Hz) out of range ({}..{} Hz)", .range.start, .range.end)]
45    #[allow(missing_docs)]
46    TuningRange { range: Range<u64>, val: u64 },
47
48    /// Some argument to a function is invalid in a way not easily expressed as
49    /// a range.
50    #[error("Invalid Parameter: {0}")]
51    InvalidParameter(&'static str),
52
53    /// The API version of the opened HackRF is too old for this function.
54    #[error(
55        "Requires API >= 0x{:x}, but device has API 0x{:x}. Consider updating the firmware",
56        needed,
57        actual
58    )]
59    #[allow(missing_docs)]
60    ApiVersion { needed: u16, actual: u16 },
61
62    /// Returned data from a HackRF didn't make any sense.
63    #[error("Invalid return data")]
64    ReturnData,
65}
66
67/// An error from trying to change HackRF states and failing.
68///
69/// Always contains the HackRF instance, but in an unknown state. To try and
70/// return to a known state, try calling [`HackRf::turn_off`].
71pub struct StateChangeError {
72    /// The error that occurred while trying to change state.
73    pub err: Error,
74    /// The HackRF instance.
75    pub rf: HackRf,
76}
77
78impl core::error::Error for StateChangeError {
79    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
80        Some(&self.err)
81    }
82}
83
84impl core::fmt::Display for StateChangeError {
85    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86        f.write_str("Failed to change state")
87    }
88}
89
90impl core::fmt::Debug for StateChangeError {
91    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
92        f.debug_struct("StateChangeError")
93            .field("err", &self.err)
94            .finish_non_exhaustive()
95    }
96}