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