1pub mod adapter;
5pub mod adapters;
6pub mod baseband;
7#[cfg(all(unix, feature = "bluez_socket"))]
8pub mod bluez_socket;
9pub mod command;
10pub mod event;
11pub mod le;
12pub mod link_control;
13pub mod packet;
14#[cfg(feature = "remote")]
15pub mod remote;
16pub mod stream;
17#[cfg(feature = "hci_usb")]
18pub mod usb;
19
20#[derive(Copy, Clone, PartialOrd, PartialEq, Ord, Eq, Hash, Debug)]
21pub enum StreamError {
22 EventError(PackError),
23 CommandError(PackError),
24 UnsupportedPacketType(u8),
25 BadOpcode,
26 BadEventCode,
27 BadPacketCode,
28 StreamClosed,
29 StreamFailed,
30}
31use crate::bytes::ToFromBytesEndian;
32use crate::ConversionError;
33use crate::PackError;
34use core::convert::{TryFrom, TryInto};
35use core::fmt::Formatter;
36
37pub const MAX_ACL_SIZE: usize = 1492 + 4;
38pub const MAX_SCO_SIZE: usize = 255;
39pub const MAX_EVENT_SIZE: usize = 260;
40pub const MAX_FRAME_SIZE: usize = MAX_ACL_SIZE + 4;
41
42pub enum DeviceEvent {
43 Reg = 1,
44 Unreg = 2,
45 Up = 3,
46 Down = 4,
47 Suspend = 5,
48 Resume = 6,
49}
50pub enum BusType {
51 Virtual = 0,
52 USB = 1,
53 PCCard = 2,
54 UART = 3,
55 RS232 = 4,
56 PCI = 5,
57 SDIO = 6,
58}
59pub enum ControllerType {
60 BREDR = 0x00,
61 AMP = 0x01,
62}
63#[derive(Copy, Clone, PartialOrd, PartialEq, Ord, Eq, Debug, Hash)]
66#[repr(u8)]
67#[non_exhaustive]
68pub enum Version {
69 Bluetooth1v0b = 0,
70 Bluetooth1v1 = 1,
71 Bluetooth1v2 = 2,
72 Bluetooth2v0 = 3,
73 Bluetooth2v1 = 4,
74 Bluetooth3v0 = 5,
75 Bluetooth4v0 = 6,
76 Bluetooth4v1 = 7,
77 Bluetooth4v2 = 8,
78 Bluetooth5v0 = 9,
79 Bluetooth5v1 = 10,
80 Bluetooth5v2 = 11,
81}
82impl From<Version> for u8 {
83 fn from(v: Version) -> Self {
84 v as u8
85 }
86}
87impl TryFrom<u8> for Version {
88 type Error = ConversionError;
89
90 fn try_from(value: u8) -> Result<Self, Self::Error> {
91 match value {
92 0 => Ok(Version::Bluetooth1v0b),
93 1 => Ok(Version::Bluetooth1v1),
94 2 => Ok(Version::Bluetooth1v2),
95 3 => Ok(Version::Bluetooth2v0),
96 4 => Ok(Version::Bluetooth2v1),
97 5 => Ok(Version::Bluetooth3v0),
98 6 => Ok(Version::Bluetooth4v0),
99 7 => Ok(Version::Bluetooth4v1),
100 8 => Ok(Version::Bluetooth4v2),
101 9 => Ok(Version::Bluetooth5v0),
102 10 => Ok(Version::Bluetooth5v1),
103 11 => Ok(Version::Bluetooth5v2),
104 _ => Err(ConversionError(())),
105 }
106 }
107}
108#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
110#[repr(u8)]
111pub enum ErrorCode {
112 Ok = 0x00,
113 UnknownHCICommand = 0x01,
114 NoConnection = 0x02,
115 HardwareFailure = 0x03,
116 PageTimeout = 0x04,
117 AuthenticationFailure = 0x05,
118 KeyMissing = 0x06,
119 MemoryFull = 0x07,
120 ConnectionTimeout = 0x08,
121 MaxNumberOfConnections = 0x09,
122 MaxNumberOfSCOConnectionsToADevice = 0x0A,
123 ACLConnectionAlreadyExists = 0x0B,
124 CommandDisallowed = 0x0C,
125 HostRejectedDueToLimitedResources = 0x0D,
126 HostRejectedDueToSecurityReasons = 0x0E,
127 HostRejectedDueToARemoteDeviceOnlyAPersonalDevice = 0x0F,
128 HostTimeout = 0x10,
129 UnsupportedFeatureOrParameterValue = 0x11,
130 InvalidHCICommandParameters = 0x12,
131 OtherEndTerminatedConnectionUserEndedConnection = 0x13,
132 OtherEndTerminatedConnectionLowResources = 0x14,
133 OtherEndTerminatedConnectionAboutToPowerOff = 0x15,
134 ConnectionTerminatedByLocalHost = 0x16,
135 RepeatedAttempts = 0x17,
136 PairingNotAllowed = 0x18,
137 UnknownLMPPDU = 0x19,
138 UnsupportedRemoteFeature = 0x1A,
139 SCOOffsetRejected = 0x1B,
140 SCOIntervalRejected = 0x1C,
141 SCOAirModeRejected = 0x1D,
142 InvalidLMPParameters = 0x1E,
143 UnspecifiedError = 0x1F,
144 UnsupportedLMPParameter = 0x20,
145 RoleChangeNotAllowed = 0x21,
146 LMPResponseTimeout = 0x22,
147 LMPErrorTransactionCollision = 0x23,
148 LMPPDUNotAllowed = 0x24,
149 EncryptionModeNotAcceptable = 0x25,
150 UnitKeyUsed = 0x26,
151 QoSNotSupported = 0x27,
152 InstantPassed = 0x28,
153 PairingWithUnitKeyNotSupported = 0x29,
154 TransactionCollision = 0x2A,
155 QOSUnacceptableParameter = 0x2C,
156 QOSRejected = 0x2D,
157 ClassificationNotSupported = 0x2E,
158 InsufficientSecurity = 0x2F,
159 ParameterOutOfRange = 0x30,
160 RoleSwitchPending = 0x32,
161 SlotViolation = 0x34,
162 RoleSwitchFailed = 0x35,
163 EIRTooLarge = 0x36,
164 SimplePairingNotSupported = 0x37,
165 HostBusyPairing = 0x38,
166}
167impl ErrorCode {
168 pub const BYTE_LEN: usize = 1;
169 pub fn is_ok(self) -> bool {
170 match self {
171 ErrorCode::Ok => true,
172 _ => false,
173 }
174 }
175 pub fn error(self) -> Result<(), ErrorCode> {
176 match self {
177 ErrorCode::Ok => Ok(()),
178 e => Err(e),
179 }
180 }
181 pub fn as_str(self) -> &'static str {
182 match self {
183 ErrorCode::Ok => "Ok",
184 ErrorCode::UnknownHCICommand => "UnknownHCICommand",
185 ErrorCode::NoConnection => "NoConnection",
186 ErrorCode::HardwareFailure => "HardwareFailure",
187 ErrorCode::PageTimeout => "PageTimeout",
188 ErrorCode::AuthenticationFailure => "AuthenticationFailure",
189 ErrorCode::KeyMissing => "KeyMissing",
190 ErrorCode::MemoryFull => "MemoryFull",
191 ErrorCode::ConnectionTimeout => "ConnectionTimeout",
192 ErrorCode::MaxNumberOfConnections => "MaxNumberOfConnections",
193 ErrorCode::MaxNumberOfSCOConnectionsToADevice => "MaxNumberOfSCOConnectionsToADevice",
194 ErrorCode::ACLConnectionAlreadyExists => "ACLConnectionAlreadyExists",
195 ErrorCode::CommandDisallowed => "CommandDisallowed",
196 ErrorCode::HostRejectedDueToLimitedResources => "HostRejectedDueToLimitedResources",
197 ErrorCode::HostRejectedDueToSecurityReasons => "HostRejectedDueToSecurityReasons",
198 ErrorCode::HostRejectedDueToARemoteDeviceOnlyAPersonalDevice => {
199 "HostRejectedDueToARemoteDeviceOnlyAPersonalDevice"
200 }
201 ErrorCode::HostTimeout => "HostTimeout",
202 ErrorCode::UnsupportedFeatureOrParameterValue => "UnsupportedFeatureOrParameterValue",
203 ErrorCode::InvalidHCICommandParameters => "InvalidHCICommandParameters",
204 ErrorCode::OtherEndTerminatedConnectionUserEndedConnection => {
205 "OtherEndTerminatedConnectionUserEndedConnection"
206 }
207 ErrorCode::OtherEndTerminatedConnectionLowResources => {
208 "OtherEndTerminatedConnectionLowResources"
209 }
210 ErrorCode::OtherEndTerminatedConnectionAboutToPowerOff => {
211 "OtherEndTerminatedConnectionAboutToPowerOff"
212 }
213 ErrorCode::ConnectionTerminatedByLocalHost => "ConnectionTerminatedByLocalHost",
214 ErrorCode::RepeatedAttempts => "RepeatedAttempts",
215 ErrorCode::PairingNotAllowed => "PairingNotAllowed",
216 ErrorCode::UnknownLMPPDU => "UnknownLMPPDU",
217 ErrorCode::UnsupportedRemoteFeature => "UnsupportedRemoteFeature",
218 ErrorCode::SCOOffsetRejected => "SCOOffsetRejected",
219 ErrorCode::SCOIntervalRejected => "SCOIntervalRejected",
220 ErrorCode::SCOAirModeRejected => "SCOAirModeRejected",
221 ErrorCode::InvalidLMPParameters => "InvalidLMPParameters",
222 ErrorCode::UnspecifiedError => "UnspecifiedError",
223 ErrorCode::UnsupportedLMPParameter => "UnsupportedLMPParameter",
224 ErrorCode::RoleChangeNotAllowed => "RoleChangeNotAllowed",
225 ErrorCode::LMPResponseTimeout => "LMPResponseTimeout",
226 ErrorCode::LMPErrorTransactionCollision => "LMPErrorTransactionCollision",
227 ErrorCode::LMPPDUNotAllowed => "LMPPDUNotAllowed",
228 ErrorCode::EncryptionModeNotAcceptable => "EncryptionModeNotAcceptable",
229 ErrorCode::UnitKeyUsed => "UnitKeyUsed",
230 ErrorCode::QoSNotSupported => "QoSNotSupported",
231 ErrorCode::InstantPassed => "InstantPassed",
232 ErrorCode::PairingWithUnitKeyNotSupported => "PairingWithUnitKeyNotSupported",
233 ErrorCode::TransactionCollision => "TransactionCollision",
234 ErrorCode::QOSUnacceptableParameter => "QOSUnacceptableParameter",
235 ErrorCode::QOSRejected => "QOSRejected",
236 ErrorCode::ClassificationNotSupported => "ClassificationNotSupported",
237 ErrorCode::InsufficientSecurity => "InsufficientSecurity",
238 ErrorCode::ParameterOutOfRange => "ParameterOutOfRange",
239 ErrorCode::RoleSwitchPending => "RoleSwitchPending",
240 ErrorCode::SlotViolation => "SlotViolation",
241 ErrorCode::RoleSwitchFailed => "RoleSwitchFailed",
242 ErrorCode::EIRTooLarge => "EIRTooLarge",
243 ErrorCode::SimplePairingNotSupported => "SimplePairingNotSupported",
244 ErrorCode::HostBusyPairing => "HostBusyPairing",
245 }
246 }
247}
248impl core::fmt::Display for ErrorCode {
249 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
250 write!(f, "{}", self.as_str())
251 }
252}
253impl From<ErrorCode> for u8 {
254 fn from(code: ErrorCode) -> Self {
255 code as u8
256 }
257}
258impl TryFrom<u8> for ErrorCode {
259 type Error = ConversionError;
260
261 fn try_from(value: u8) -> Result<Self, Self::Error> {
262 match value {
263 0x00 => Ok(ErrorCode::Ok),
264 0x01 => Ok(ErrorCode::UnknownHCICommand),
265 0x02 => Ok(ErrorCode::NoConnection),
266 0x03 => Ok(ErrorCode::HardwareFailure),
267 0x04 => Ok(ErrorCode::PageTimeout),
268 0x05 => Ok(ErrorCode::AuthenticationFailure),
269 0x06 => Ok(ErrorCode::KeyMissing),
270 0x07 => Ok(ErrorCode::MemoryFull),
271 0x08 => Ok(ErrorCode::ConnectionTimeout),
272 0x09 => Ok(ErrorCode::MaxNumberOfConnections),
273 0x0A => Ok(ErrorCode::MaxNumberOfSCOConnectionsToADevice),
274 0x0B => Ok(ErrorCode::ACLConnectionAlreadyExists),
275 0x0C => Ok(ErrorCode::CommandDisallowed),
276 0x0D => Ok(ErrorCode::HostRejectedDueToLimitedResources),
277 0x0E => Ok(ErrorCode::HostRejectedDueToSecurityReasons),
278 0x0F => Ok(ErrorCode::HostRejectedDueToARemoteDeviceOnlyAPersonalDevice),
279 0x10 => Ok(ErrorCode::HostTimeout),
280 0x11 => Ok(ErrorCode::UnsupportedFeatureOrParameterValue),
281 0x12 => Ok(ErrorCode::InvalidHCICommandParameters),
282 0x13 => Ok(ErrorCode::OtherEndTerminatedConnectionUserEndedConnection),
283 0x14 => Ok(ErrorCode::OtherEndTerminatedConnectionLowResources),
284 0x15 => Ok(ErrorCode::OtherEndTerminatedConnectionAboutToPowerOff),
285 0x16 => Ok(ErrorCode::ConnectionTerminatedByLocalHost),
286 0x17 => Ok(ErrorCode::RepeatedAttempts),
287 0x18 => Ok(ErrorCode::PairingNotAllowed),
288 0x19 => Ok(ErrorCode::UnknownLMPPDU),
289 0x1A => Ok(ErrorCode::UnsupportedRemoteFeature),
290 0x1B => Ok(ErrorCode::SCOOffsetRejected),
291 0x1C => Ok(ErrorCode::SCOIntervalRejected),
292 0x1D => Ok(ErrorCode::SCOAirModeRejected),
293 0x1E => Ok(ErrorCode::InvalidLMPParameters),
294 0x1F => Ok(ErrorCode::UnspecifiedError),
295 0x20 => Ok(ErrorCode::UnsupportedLMPParameter),
296 0x21 => Ok(ErrorCode::RoleChangeNotAllowed),
297 0x22 => Ok(ErrorCode::LMPResponseTimeout),
298 0x23 => Ok(ErrorCode::LMPErrorTransactionCollision),
299 0x24 => Ok(ErrorCode::LMPPDUNotAllowed),
300 0x25 => Ok(ErrorCode::EncryptionModeNotAcceptable),
301 0x26 => Ok(ErrorCode::UnitKeyUsed),
302 0x27 => Ok(ErrorCode::QoSNotSupported),
303 0x28 => Ok(ErrorCode::InstantPassed),
304 0x29 => Ok(ErrorCode::PairingWithUnitKeyNotSupported),
305 _ => Err(ConversionError(())),
306 }
307 }
308}
309pub const EVENT_MAX_LEN: usize = 255;
310pub const COMMAND_MAX_LEN: usize = 255;
311pub const FULL_COMMAND_MAX_LEN: usize = COMMAND_MAX_LEN + OPCODE_LEN + 1;
312pub const EVENT_CODE_LEN: usize = 1;
313#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug, Hash)]
315#[repr(u8)]
316pub enum OGF {
317 NOP = 0x00,
318 LinkControl = 0x01,
319 LinkPolicy = 0x02,
320 HCIControlBaseband = 0x03,
321 InformationalParameters = 0x04,
322 StatusParameters = 0x05,
323 Testing = 0x06,
324 LEController = 0x08,
325 VendorSpecific = 0x3F,
326}
327impl Default for OGF {
328 fn default() -> Self {
329 OGF::NOP
330 }
331}
332impl From<OGF> for u8 {
333 fn from(ogf: OGF) -> Self {
334 ogf as u8
335 }
336}
337impl TryFrom<u8> for OGF {
338 type Error = ConversionError;
339
340 fn try_from(value: u8) -> Result<Self, Self::Error> {
341 match value {
342 0x00 => Ok(OGF::NOP),
343 0x01 => Ok(OGF::LinkControl),
344 0x02 => Ok(OGF::LinkPolicy),
345 0x03 => Ok(OGF::HCIControlBaseband),
346 0x04 => Ok(OGF::InformationalParameters),
347 0x05 => Ok(OGF::StatusParameters),
348 0x06 => Ok(OGF::Testing),
349 0x08 => Ok(OGF::LEController),
350 0x3F => Ok(OGF::VendorSpecific),
351 _ => Err(ConversionError(())),
352 }
353 }
354}
355pub const OCF_MAX: u16 = (1 << 10) - 1;
356#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug, Hash, Default)]
358pub struct OCF(u16);
359impl OCF {
360 pub fn new(ocf: u16) -> Self {
364 assert!(ocf <= OCF_MAX, "ocf bigger than 10 bits");
365 Self(ocf)
366 }
367 pub fn new_masked(ocf: u16) -> Self {
369 Self(ocf & OCF_MAX)
370 }
371}
372impl From<OCF> for u16 {
373 fn from(ocf: OCF) -> Self {
374 ocf.0
375 }
376}
377pub const OPCODE_LEN: usize = 2;
378#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug, Hash, Default)]
380pub struct Opcode(pub OGF, pub OCF);
381impl Opcode {
382 pub const fn byte_len() -> usize {
383 OPCODE_LEN
384 }
385 pub fn pack(self, buf: &mut [u8]) -> Result<(), PackError> {
388 PackError::expect_length(OPCODE_LEN, buf)?;
389 buf[..2].copy_from_slice(&u16::from(self).to_bytes_le());
390 Ok(())
391 }
392 pub fn unpack(buf: &[u8]) -> Result<Opcode, PackError> {
396 PackError::expect_length(OPCODE_LEN, buf)?;
397 Ok(u16::from_bytes_le(&buf)
398 .expect("length checked above")
399 .try_into()
400 .ok()
401 .ok_or(PackError::BadBytes { index: Some(0) })?)
402 }
403 pub const fn nop() -> Opcode {
404 Opcode(OGF::NOP, OCF(0))
405 }
406 pub fn is_nop(self) -> bool {
407 self.0 == OGF::NOP
408 }
409}
410impl From<Opcode> for u16 {
411 fn from(opcode: Opcode) -> Self {
412 (opcode.1).0 | (u16::from(u8::from(opcode.0)) << 10)
413 }
414}
415impl TryFrom<u16> for Opcode {
416 type Error = ConversionError;
417
418 fn try_from(value: u16) -> Result<Self, Self::Error> {
419 let ogf = OGF::try_from(u8::try_from(value >> 10).expect("OGF is 6-bits"))?;
420 let ocf = OCF::new_masked(value);
421 Ok(Opcode(ogf, ocf))
422 }
423}