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 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#[repr(transparent)]
80#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
81pub struct Error(NonZeroU8);
82
83impl Error {
84 const unsafe fn from_u8(err: u8) -> Error {
89 Error(NonZeroU8::new_unchecked(err))
90 }
91
92 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}