1use core::num::NonZeroU8;
2
3use crate::{ByteAlignedValue, FixedSizeValue, FromHciBytes};
4
5#[repr(transparent)]
7#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
8pub struct Status(u8);
9
10impl Status {
11 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 pub const SUCCESS: Status = Status(0);
36
37 pub const fn new(n: u8) -> Self {
39 Status(n)
40 }
41
42 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#[repr(transparent)]
88#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
89pub struct Error(NonZeroU8);
90
91impl Error {
92 const unsafe fn from_u8(err: u8) -> Error {
97 Error(NonZeroU8::new_unchecked(err))
98 }
99
100 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}