bt_hci/param/
status.rs

1use core::num::NonZeroU8;
2
3use crate::{ByteAlignedValue, FixedSizeValue, FromHciBytes};
4
5/// A HCI status value.
6#[repr(transparent)]
7#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
8pub struct Status(u8);
9
10impl Status {
11    /// Get the underlying representation.
12    pub fn into_inner(self) -> u8 {
13        self.0
14    }
15}
16
17unsafe impl FixedSizeValue for Status {
18    #[inline(always)]
19    fn is_valid(_data: &[u8]) -> bool {
20        true
21    }
22}
23
24unsafe impl ByteAlignedValue for Status {}
25
26impl<'de> FromHciBytes<'de> for &'de Status {
27    #[inline(always)]
28    fn from_hci_bytes(data: &'de [u8]) -> Result<(Self, &'de [u8]), crate::FromHciBytesError> {
29        <Status as crate::ByteAlignedValue>::ref_from_hci_bytes(data)
30    }
31}
32
33impl Status {
34    /// Status for successful operation.
35    pub const SUCCESS: Status = Status(0);
36
37    /// Create a new instance.
38    pub const fn new(n: u8) -> Self {
39        Status(n)
40    }
41
42    /// Get a result representation of status which will provide an error
43    /// if not a success.
44    pub const fn to_result(self) -> Result<(), Error> {
45        if let Some(err) = NonZeroU8::new(self.0) {
46            Err(Error(err))
47        } else {
48            Ok(())
49        }
50    }
51}
52
53#[cfg(feature = "defmt")]
54impl defmt::Format for Status {
55    fn format(&self, fmt: defmt::Formatter) {
56        if let Some(err) = NonZeroU8::new(self.0) {
57            defmt::write!(fmt, "{}", Error(err))
58        } else {
59            defmt::write!(fmt, "Success")
60        }
61    }
62}
63
64impl core::fmt::Debug for Status {
65    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
66        if let Some(err) = NonZeroU8::new(self.0) {
67            core::fmt::Debug::fmt(&Error(err), f)
68        } else {
69            f.write_str("Success")
70        }
71    }
72}
73
74impl From<u8> for Status {
75    fn from(value: u8) -> Self {
76        Status(value)
77    }
78}
79
80impl From<Status> for u8 {
81    fn from(value: Status) -> Self {
82        value.0
83    }
84}
85
86/// An error representation for HCI errors.
87#[repr(transparent)]
88#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
89pub struct Error(NonZeroU8);
90
91impl Error {
92    /// Create from the byte value
93    ///
94    /// # Safety
95    /// Must be a valid HCI error code.
96    const unsafe fn from_u8(err: u8) -> Error {
97        Error(NonZeroU8::new_unchecked(err))
98    }
99
100    /// Get the status representation.
101    pub const fn to_status(self) -> Status {
102        Status(self.0.get())
103    }
104}
105
106impl core::fmt::Display for Error {
107    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
108        core::fmt::Debug::fmt(self, f)
109    }
110}
111
112impl From<Error> for u8 {
113    fn from(value: Error) -> Self {
114        value.0.get()
115    }
116}
117
118macro_rules! errnos {
119        (
120            $(
121                ($val:expr, $konst:ident, $desc:expr);
122            )+
123        ) => {
124            impl Error {
125            $(
126                #[doc = $desc]
127                pub const $konst: Error = unsafe { Error::from_u8($val) };
128            )+
129            }
130
131            impl Status {
132            $(
133                #[doc = $desc]
134                pub const $konst: Status = Error::$konst.to_status();
135            )+
136            }
137
138            #[cfg(feature = "defmt")]
139            impl defmt::Format for Error {
140                fn format(&self, fmt: defmt::Formatter) {
141                    match *self {
142                        $(
143                        Self::$konst => defmt::write!(fmt, $desc),
144                        )+
145                        _ => defmt::write!(fmt, "Unknown error: {}", self.0),
146                    }
147                }
148            }
149
150            impl core::fmt::Debug for Error {
151                fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
152                    match *self {
153                        $(
154                        Self::$konst => core::write!(fmt, $desc),
155                        )+
156                        _ => core::write!(fmt, "Unknown errno: {}", self.0),
157                    }
158                }
159            }
160        }
161    }
162
163errnos! {
164    (0x01, UNKNOWN_CMD, "Unknown HCI Command");
165    (0x02, UNKNOWN_CONN_IDENTIFIER, "Unknown Connection Identifier");
166    (0x03, HARDWARE_FAILURE, "Hardware Failure");
167    (0x04, PAGE_TIMEOUT, "Page Timeout");
168    (0x05, AUTHENTICATION_FAILURE, "Authentication Failure");
169    (0x06, PIN_OR_KEY_MISSING, "PIN or Key Missing");
170    (0x07, MEMORY_CAPACITY_EXCEEDED, "Memory Capacity Exceeded");
171    (0x08, CONN_TIMEOUT, "Connection Timeout");
172    (0x09, CONN_LIMIT_EXCEEDED, "Connection Limit Exceeded");
173    (0x0A, SYNCHRONOUS_CONN_LIMIT_EXCEEDED, "Synchronous Connection Limit To A Device Exceeded");
174    (0x0B, CONN_ALREADY_EXISTS, "Connection Already Exists");
175    (0x0C, CMD_DISALLOWED, "Command Disallowed");
176    (0x0D, CONN_REJECTED_LIMITED_RESOURCES, "Connection Rejected due to Limited Resources");
177    (0x0E, CONN_REJECTED_SECURITY_REASONS, "Connection Rejected Due To Security Reasons");
178    (0x0F, CONN_REJECTED_UNACCEPTABLE_BD_ADDR, "Connection Rejected due to Unacceptable BD_ADDR");
179    (0x10, CONN_ACCEPT_TIMEOUT_EXCEEDED, "Connection Accept Timeout Exceeded");
180    (0x11, UNSUPPORTED, "Unsupported Feature or Parameter Value");
181    (0x12, INVALID_HCI_PARAMETERS, "Invalid HCI Command Parameters");
182    (0x13, REMOTE_USER_TERMINATED_CONN, "Remote User Terminated Connection");
183    (0x14, REMOTE_DEVICE_TERMINATED_CONN_LOW_RESOURCES, "Remote Device Terminated Connection due to Low Resources");
184    (0x15, REMOTE_DEVICE_TERMINATED_CONN_POWER_OFF, "Remote Device Terminated Connection due to Power Off");
185    (0x16, CONN_TERMINATED_BY_LOCAL_HOST, "Connection Terminated By Local Host");
186    (0x17, REPEATED_ATTEMPTS, "Repeated Attempts");
187    (0x18, PAIRING_NOT_ALLOWED, "Pairing Not Allowed");
188    (0x19, UNKNOWN_LMP_PDU, "Unknown LMP PDU");
189    (0x1A, UNSUPPORTED_REMOTE_FEATURE, "Unsupported Remote Feature");
190    (0x1B, SCO_OFFSET_REJECTED, "SCO Offset Rejected");
191    (0x1C, SCO_INTERVAL_REJECTED, "SCO Interval Rejected");
192    (0x1D, SCO_AIR_MODE_REJECTED, "SCO Air Mode Rejected");
193    (0x1E, INVALID_LMP_LL_PARAMETERS, "Invalid LMP Parameters / Invalid LL Parameters");
194    (0x1F, UNSPECIFIED, "Unspecified Error");
195    (0x20, UNSUPPORTED_LMP_LL_PARAMETER_VALUE, "Unsupported LMP Parameter Value / Unsupported LL Parameter Value");
196    (0x21, ROLE_CHANGE_NOT_ALLOWED, "Role Change Not Allowed");
197    (0x22, LMP_LL_RESPONSE_TIMEOUT, "LMP Response Timeout / LL Response Timeout");
198    (0x23, LMP_LL_COLLISION, "LMP Error Transaction Collision / LL Procedure Collision");
199    (0x24, LMP_PDU_NOT_ALLOWED, "LMP PDU Not Allowed");
200    (0x25, ENCRYPTION_MODE_NOT_ACCEPTABLE, "Encryption Mode Not Acceptable");
201    (0x26, LINK_KEY_CANNOT_BE_CHANGED, "Link Key cannot be Changed");
202    (0x27, REQUESTED_QOS_NOT_SUPPORTED, "Requested QoS Not Supported");
203    (0x28, INSTANT_PASSED, "Instant Passed");
204    (0x29, PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED, "Pairing With Unit Key Not Supported");
205    (0x2A, DIFFERENT_TRANSACTION_COLLISION, "Different Transaction Collision");
206    (0x2C, QOS_UNACCEPTABLE_PARAMETER, "QoS Unacceptable Parameter");
207    (0x2D, QOS_REJECTED, "QoS Rejected");
208    (0x2E, CHANNEL_CLASSIFICATION_NOT_SUPPORTED, "Channel Classification Not Supported");
209    (0x2F, INSUFFICIENT_SECURITY, "Insufficient Security");
210    (0x30, PARAMETER_OUT_OF_RANGE, "Parameter Out Of Mandatory Range");
211    (0x32, ROLE_SWITCH_PENDING, "Role Switch Pending");
212    (0x34, RESERVED_SLOT_VIOLATION, "Reserved Slot Violation");
213    (0x35, ROLE_SWITCH_FAILED, "Role Switch Failed");
214    (0x36, EXT_INQUIRY_RESPONSE_TOO_LARGE, "Extended Inquiry Response Too Large");
215    (0x37, SECURE_SIMPLE_PAIRING_NOT_SUPPORTED_BY_HOST, "Secure Simple Pairing Not Supported By Host");
216    (0x38, HOST_BUSY_PAIRING, "Host Busy - Pairing");
217    (0x39, CONN_REJECTED_NO_SUITABLE_CHANNEL_FOUND, "Connection Rejected due to No Suitable Channel Found");
218    (0x3A, CONTROLLER_BUSY, "Controller Busy");
219    (0x3B, UNACCEPTABLE_CONN_PARAMETERS, "Unacceptable Connection Parameters");
220    (0x3C, ADV_TIMEOUT, "Advertising Timeout");
221    (0x3D, CONN_TERMINATED_DUE_TO_MIC_FAILURE, "Connection Terminated due to MIC Failure");
222    (0x3E, CONN_FAILED_SYNCHRONIZATION_TIMEOUT, "Connection Failed to be Established / Synchronization Timeout");
223    (0x40, COARSE_CLOCK_ADJUSTMENT_REJECTED, "Coarse Clock Adjustment Rejected but Will Try to Adjust Using Clock Dragging");
224    (0x41, TYPE0_SUBMAP_NOT_DEFINED, "Type0 Submap Not Defined");
225    (0x42, UNKNOWN_ADV_IDENTIFIER, "Unknown Advertising Identifier");
226    (0x43, LIMIT_REACHED, "Limit Reached");
227    (0x44, OPERATION_CANCELLED_BY_HOST, "Operation Cancelled by Host");
228    (0x45, PACKET_TOO_LONG, "Packet Too Long");
229}