bluetooth_hci/
lib.rs

1//! A Bluetooth implementation for embedded systems.
2//!
3//! This crate is a proof-of-concept implementation of the host (application) side of the
4//! [`Bluetooth`] specification. It is still woefully incomplete, and will undoubtedly be redesigned
5//! completely, and potentially split into multiple crates before being stabilized.
6//!
7//! When the documentation refers to a specific section of "the" Bluetooth specification, the same
8//! section applies for all supported versions of the specification. If the versions differ, the
9//! specific version will also be included in the reference.
10//!
11//! # Design
12//!
13//! Like other core embedded crates (e.g, [`embedded-hal`]), this crate uses traits to be agnostic
14//! about the specific Bluetooth module. It provides a default implementation of the HCI for devices
15//! that implement the core [`Controller`] trait. The traits also make use of the [`nb`] crate to
16//! support different asynchronous or synchronous operation modes.
17//!
18//! ## Commands
19//!
20//! The [`host::Hci`] trait defines all of the functions that communicate from the host to the
21//! controller. The [`host::uart::Hci`] trait defines a read function that returns a
22//! [`host::uart::Packet`], which can contain an [`Event`], `AclData` (TODO), or `SyncData`
23//! (TODO). Both of these traits have default implementations in terms of the [`Controller`], so
24//! calling code does not need to implement any commands or event parsing code.
25//!
26//! ## Vendor-specific commands and events
27//!
28//! The [`host::uart::Hci`] trait requires specialization for the type of vendor-specific events
29//! (which implement [`event::VendorEvent`]) and vendor-specific errors. Any vendor-specific
30//! extensions will need to convert byte buffers into the appropriate event type (as defined by the
31//! vendor), but will not need to read data using the [`Controller`]. The Bluetooth standard
32//! provides packet length in a common header, so only complete packets will be passed on to the
33//! vendor code for deserialization.
34//!
35//! There is not yet support for vendor-specific commands. The vendor crate will have to serialize
36//! the command packets directly and write them to the [`Controller`].
37//!
38//! # Reference implementation
39//!
40//! The [`bluenrg`] crate provides a sample implementation for STMicro's BlueNRG Bluetooth
41//! controllers.
42//!
43//! # Ideas for discussion and improvement
44//!
45//! - Add traits to facilitate writing Bluetooth controllers. These controllers would have a host on
46//!   one side and a link layer on the other. Separate crate? If so, move common definitions (Status
47//!   codes, opcodes, etc.) to a bluetooth-core crate.
48//!
49//! - Add a helper function for vendor-specific commands. This should take care of creating the
50//!   header and writing the data to the [`Controller`]. Vendor code should only be responsible for
51//!   serializing commands into byte slices.
52//!
53//! - Remove the `cmd_link` and `event_link` modules, and merge `uart` up into `host`. The Bluetooth
54//!   spec made it seem like there were devices that do not include the packet type byte at the
55//!   beginning of packets, but STMicro's BlueNRG implementation and Nordic's Zephyr implementation
56//!   both include it. If there is a controller that does *not* include the packet type, the
57//!   `event_link` HCI can always be brought back.
58//!
59//! - Provide config features for different versions of the Bluetooth Specification.
60//!
61//! - Implement all of the specified functions and events.
62//!
63//! - Provide opt-in config features for certain types of commands and events. For example, BlueNRG
64//!   devices only implement 40 commands and 14 events, but the spec has around 250 commands and 76
65//!   events. It would be nice if unused events could be compiled out. This would be less important
66//!   for commands, since those functions would simply never be called, and could be removed by the
67//!   linker. This would entail significant work both on the part of the crate authors and on crate
68//!   users, who would need to configure the crate appropriately. All combinations of features would
69//!   also never be tested; there are simply too many, even if we only provide features for the
70//!   events. On the other hand, those features should not interact, so maybe it would be feasible.
71//!
72//! [`Bluetooth`]: https://www.bluetooth.com/specifications/bluetooth-core-specification
73//! [`embedded-hal`]: https://crates.io/crates/embedded-hal
74//! [`nb`]: https://crates.io/crates/nb
75//! [`bluenrg`]: https://github.com/danielgallagher0/bluenrg
76
77#![no_std]
78#![deny(missing_docs)]
79
80#[macro_use]
81extern crate bitflags;
82extern crate byteorder;
83extern crate nb;
84
85#[macro_use]
86mod bitflag_array;
87
88pub mod event;
89pub mod host;
90mod opcode;
91pub mod types;
92
93pub use event::Event;
94pub use opcode::Opcode;
95
96use core::convert::TryFrom;
97use core::fmt::Debug;
98
99/// Interface to the Bluetooth controller from the host's perspective.
100///
101/// The Bluetooth application host must communicate with a controller (which, in turn, communicates
102/// with the link layer) to control the Bluetooth radio. Device crates must implement this trait,
103/// which enables full access to all of the functions and events of the HCI through [`host::Hci`]
104/// and [`host::uart::Hci`], respectively.
105pub trait Controller {
106    /// Enumeration of [`Controller`] errors. These typically will be specializations of
107    /// [`host::uart::Error`] that specify both the vendor-specific error type _and_ a communication
108    /// error type. The communication error type in turn will depend on the bus used to communicate
109    /// with the controller as well as the device crate (e.g., [`linux-embedded-hal::Spidev`] uses
110    /// [`std::io::Error`]).
111    ///
112    /// [`linux-embedded-hal::Spidev`]:
113    /// https://docs.rs/linux-embedded-hal/0.1.1/linux_embedded_hal/struct.Spidev.html
114    /// [`std::io::Error`]: https://doc.rust-lang.org/nightly/std/io/struct.Error.html
115    type Error;
116
117    /// The type of header sent to the controller for HCI commands.  Should be either
118    /// [`host::uart::CommandHeader`], [`host::cmd_link::Header`], or
119    /// [`host::event_link::NoCommands`], depending on the controller implementation.
120    type Header;
121
122    /// Type containing vendor-specific extensions for the controller, including vendor-specific
123    /// errors, events, and status codes.
124    type Vendor: Vendor;
125
126    /// Writes the bytes to the controller, in a single transaction if possible. All of `header`
127    /// shall be written, followed by all of `payload`. `write` is allowed to block internally, but
128    /// should return [`nb::Error::WouldBlock`] if the controller is not ready to receive the data.
129    fn write(&mut self, header: &[u8], payload: &[u8]) -> nb::Result<(), Self::Error>;
130
131    /// Reads data from the controller into the provided `buffer`. The length of the buffer
132    /// indicates the number of bytes to read. The implementor must not return bytes in an order
133    /// different from that in which they were received from the controller. For example, the
134    /// implementor may read all available bytes from the controller and maintain them in an
135    /// internal buffer, but `read_into` shall only read the number of bytes requested.
136    ///
137    /// # Example
138    ///
139    /// ```
140    /// // Controller sends:
141    /// // +------+------+------+------+------+------+------+------+
142    /// // | 0x12 | 0x34 | 0x56 | 0x78 | 0x9a | 0xbc | 0xde | 0xf0 |
143    /// // +------+------+------+------+------+------+------+------+
144    ///
145    /// // host calls:
146    ///
147    /// # extern crate nb;
148    /// # extern crate bluetooth_hci;
149    /// # use bluetooth_hci::Controller as HciController;
150    /// # struct Controller;
151    /// # struct Error;
152    /// # struct Header;
153    /// # struct Vendor;
154    /// # impl bluetooth_hci::Vendor for Vendor {
155    /// #     type Status = VendorStatus;
156    /// #     type Event = VendorEvent;
157    /// # }
158    /// # #[derive(Clone, Debug)]
159    /// # struct VendorStatus;
160    /// # impl std::convert::TryFrom<u8> for VendorStatus {
161    /// #     type Error = bluetooth_hci::BadStatusError;
162    /// #     fn try_from(value: u8) -> Result<VendorStatus, Self::Error> {
163    /// #         Err(bluetooth_hci::BadStatusError::BadValue(value))
164    /// #     }
165    /// # }
166    /// # impl std::convert::Into<u8> for VendorStatus {
167    /// #    fn into(self) -> u8 {
168    /// #        0
169    /// #    }
170    /// # }
171    /// # struct VendorEvent;
172    /// # impl bluetooth_hci::event::VendorEvent for VendorEvent {
173    /// #     type Error = Error;
174    /// #     type Status = VendorStatus;
175    /// #     type ReturnParameters = ReturnParameters;
176    /// #     fn new(_buffer: &[u8]) -> Result<Self, bluetooth_hci::event::Error<Self::Error>>
177    /// #     where
178    /// #         Self: Sized
179    /// #     {
180    /// #         Ok(VendorEvent{})
181    /// #     }
182    /// # }
183    /// # #[derive(Clone, Debug)]
184    /// # struct ReturnParameters;
185    /// # impl bluetooth_hci::event::VendorReturnParameters for ReturnParameters {
186    /// #     type Error = Error;
187    /// #     fn new(_buffer: &[u8]) -> Result<Self, bluetooth_hci::event::Error<Self::Error>> {
188    /// #         Ok(ReturnParameters{})
189    /// #     }
190    /// # }
191    /// # impl HciController for Controller {
192    /// #     type Error = Error;
193    /// #     type Header = Header;
194    /// #     type Vendor = Vendor;
195    /// #     fn write(&mut self, _header: &[u8], _payload: &[u8]) -> nb::Result<(), Self::Error> {
196    /// #         Ok(())
197    /// #     }
198    /// #     fn read_into(&mut self, _buffer: &mut [u8]) -> nb::Result<(), Self::Error> {
199    /// #         Ok(())
200    /// #     }
201    /// #     fn peek(&mut self, _n: usize) -> nb::Result<u8, Self::Error> {
202    /// #         Ok(0)
203    /// #     }
204    /// # }
205    /// # fn main() {
206    /// # let mut controller = Controller;
207    /// let mut buffer = [0; 4];
208    /// controller.read_into(&mut buffer[1..]);  // read 3 bytes into buffer[1..]
209    ///
210    /// // buffer contains:
211    /// // +------+------+------+------+
212    /// // | 0x00 | 0x12 | 0x34 | 0x56 |
213    /// // +------+------+------+------+
214    ///
215    /// // now the host calls:
216    /// controller.read_into(&mut buffer);  // read 4 bytes into buffer
217    ///
218    /// // buffer contains:
219    /// // +------+------+------+------+
220    /// // | 0x78 | 0x9a | 0xbc | 0xde |
221    /// // +------+------+------+------+
222    /// # }
223    /// ```
224    /// If the next call to `read_into` requests more than 1 byte, the controller may return
225    /// [`nb::Error::WouldBlock`], or may attempt to read more data from the controller. If not
226    /// enough data is available from the controller, the implementor shall return
227    /// [`nb::Error::WouldBlock`].
228    fn read_into(&mut self, buffer: &mut [u8]) -> nb::Result<(), Self::Error>;
229
230    /// Looks ahead at the data coming from the Controller without consuming it. Implementors should
231    /// be able to support values of `n` up to 5 to support all potential data types.
232    ///
233    /// `peek(0)` will typically be used to the the packet type (see Bluetooth Spec, Vol 4, Part A,
234    /// Section 2), which will be followed by another peek to determine the amount of data to
235    /// read. For example, the code to read an HCI event looks like this:
236    ///
237    /// ```
238    /// # extern crate nb;
239    /// # extern crate bluetooth_hci;
240    /// # use bluetooth_hci::Controller as HciController;
241    /// # struct Controller;
242    /// # #[derive(Debug)]
243    /// # struct Error;
244    /// # struct Header;
245    /// # struct Vendor;
246    /// # impl bluetooth_hci::Vendor for Vendor {
247    /// #     type Status = VendorStatus;
248    /// #     type Event = VendorEvent;
249    /// # }
250    /// # #[derive(Clone, Debug)]
251    /// # struct VendorStatus;
252    /// # impl std::convert::TryFrom<u8> for VendorStatus {
253    /// #     type Error = bluetooth_hci::BadStatusError;
254    /// #     fn try_from(value: u8) -> Result<VendorStatus, Self::Error> {
255    /// #         Err(bluetooth_hci::BadStatusError::BadValue(value))
256    /// #     }
257    /// # }
258    /// # impl std::convert::Into<u8> for VendorStatus {
259    /// #    fn into(self) -> u8 {
260    /// #        0
261    /// #    }
262    /// # }
263    /// # struct VendorEvent;
264    /// # impl bluetooth_hci::event::VendorEvent for VendorEvent {
265    /// #     type Error = Error;
266    /// #     type Status = VendorStatus;
267    /// #     type ReturnParameters = ReturnParameters;
268    /// #     fn new(_buffer: &[u8]) -> Result<Self, bluetooth_hci::event::Error<Self::Error>>
269    /// #     where
270    /// #         Self: Sized
271    /// #     {
272    /// #         Ok(VendorEvent{})
273    /// #     }
274    /// # }
275    /// # #[derive(Clone, Debug)]
276    /// # struct ReturnParameters;
277    /// # impl bluetooth_hci::event::VendorReturnParameters for ReturnParameters {
278    /// #     type Error = Error;
279    /// #     fn new(_buffer: &[u8]) -> Result<Self, bluetooth_hci::event::Error<Self::Error>> {
280    /// #         Ok(ReturnParameters{})
281    /// #     }
282    /// # }
283    /// # impl HciController for Controller {
284    /// #     type Error = Error;
285    /// #     type Header = Header;
286    /// #     type Vendor = Vendor;
287    /// #     fn write(&mut self, _header: &[u8], _payload: &[u8]) -> nb::Result<(), Self::Error> {
288    /// #         Ok(())
289    /// #     }
290    /// #     fn read_into(&mut self, _buffer: &mut [u8]) -> nb::Result<(), Self::Error> {
291    /// #         Ok(())
292    /// #     }
293    /// #     fn peek(&mut self, _n: usize) -> nb::Result<u8, Self::Error> {
294    /// #         Ok(0)
295    /// #     }
296    /// # }
297    /// # fn main() -> nb::Result<(), Error> {
298    /// # const PACKET_TYPE_HCI_EVENT: u8 = 4;
299    /// # let mut controller = Controller;
300    /// const MAX_EVENT_LENGTH: usize = 255;
301    /// const HEADER_LENGTH: usize = 2;
302    /// let mut buffer = [0; MAX_EVENT_LENGTH + HEADER_LENGTH];
303    /// let packet_type = controller.peek(0)?;
304    /// if packet_type == PACKET_TYPE_HCI_EVENT {
305    ///     // Byte 3 has the parameter length in HCI events
306    ///     let param_len = controller.peek(3)? as usize;
307    ///
308    ///     // We want to consume the full HCI Event packet, and we now know the length.
309    ///     controller.read_into(&mut buffer[..HEADER_LENGTH + param_len])?;
310    /// }
311    /// # Ok(())
312    /// # }
313    /// ```
314    fn peek(&mut self, n: usize) -> nb::Result<u8, Self::Error>;
315}
316
317/// Trait defining vendor-specific extensions for the Bluetooth Controller.
318pub trait Vendor {
319    /// Enumeration of vendor-specific status codes.
320    type Status: TryFrom<u8, Error = BadStatusError> + Into<u8> + Clone + Debug;
321
322    /// Enumeration of vendor-specific events.
323    type Event: event::VendorEvent;
324}
325
326/// List of possible error codes, Bluetooth Spec, Vol 2, Part D, Section 2.
327///
328/// Includes an extension point for vendor-specific status codes.
329#[derive(Copy, Clone, Debug, PartialEq)]
330pub enum Status<V> {
331    /// Success
332    Success,
333    /// Unknown HCI Command
334    UnknownCommand,
335    /// Unknown Connection Identifier
336    UnknownConnectionId,
337    /// Hardware Failure
338    HardwareFailure,
339    /// Page Timeout
340    PageTimeout,
341    /// Authentication Failure
342    AuthFailure,
343    /// PIN or Key Missing
344    PinOrKeyMissing,
345    /// Memory Capacity Exceeded
346    OutOfMemory,
347    /// Connection Timeout
348    ConnectionTimeout,
349    /// Connection Limit Exceeded
350    ConnectionLimitExceeeded,
351    /// Synchronous Connection Limit To A Device Exceeded
352    SyncConnectionLimitExceeded,
353    /// Connection Already Exists
354    ConnectionAlreadyExists,
355    /// Command Disallowed
356    CommandDisallowed,
357    /// Connection Rejected due to Limited Resources
358    LimitedResources,
359    /// Connection Rejected Due To Security Reasons
360    ConnectionRejectedSecurity,
361    /// Connection Rejected due to Unacceptable BD_ADDR
362    UnacceptableBdAddr,
363    /// Connection Accept Timeout Exceeded
364    AcceptTimeoutExceeded,
365    /// Unsupported Feature or Parameter Value
366    UnsupportedFeature,
367    /// Invalid HCI Command Parameters
368    InvalidParameters,
369    /// Remote User Terminated Connection
370    RemoteTerminationByUser,
371    /// Remote Device Terminated Connection due to Low Resources
372    RemoteTerminationLowResources,
373    /// Remote Device Terminated Connection due to Power Off
374    RemoteTerminationPowerOff,
375    /// Connection Terminated By Local Host
376    ConnectionTerminatedByHost,
377    /// Repeated Attempts
378    RepeatedAttempts,
379    /// Pairing Not Allowed
380    PairingNotAllowed,
381    /// Unknown LMP PDU
382    UnknownLmpPdu,
383    /// Unsupported Remote Feature / Unsupported LMP Feature
384    UnsupportedRemoteFeature,
385    /// SCO Offset Rejected
386    ScoOffsetRejected,
387    /// SCO Interval Rejected
388    ScoIntervalRejected,
389    /// SCO Air Mode Rejected
390    ScoAirModeRejected,
391    /// Invalid LMP Parameters / Invalid LL Parameters
392    InvalidLmpParameters,
393    /// Unspecified Error
394    UnspecifiedError,
395    /// Unsupported LMP Parameter Value / Unsupported LL Parameter Value
396    UnsupportedLmpParameterValue,
397    /// Role Change Not Allowed
398    RoleChangeNotAllowed,
399    /// LMP Response Timeout / LL Response Timeout
400    LmpResponseTimeout,
401    /// LMP Error Transaction Collision / LL Procedure Collision
402    LmpTransactionCollision,
403    /// LMP PDU Not Allowed
404    LmpPduNotAllowed,
405    /// Encryption Mode Not Acceptable
406    EncryptionModeNotAcceptable,
407    /// Link Key cannot be Changed
408    LinkKeyCannotBeChanged,
409    /// Requested QoS Not Supported
410    RequestedQosNotSupported,
411    /// Instant Passed
412    InstantPassed,
413    /// Pairing With Unit Key Not Supported
414    PairingWithUnitKeyNotSupported,
415    /// Different Transaction Collision
416    DifferentTransactionCollision,
417    /// Reserved for Future Use
418    ReservedforFutureUse,
419    /// QoS Unacceptable Parameter
420    QosUnacceptableParameter,
421    /// QoS Rejected
422    QosRejected,
423    /// Channel Classification Not Supported
424    ChannelClassificationNotSupported,
425    /// Insufficient Security
426    InsufficientSecurity,
427    /// Parameter Out Of Mandatory Range
428    ParameterOutOfMandatoryRange,
429    /// Reserved for Future Use
430    ReservedForFutureUse49,
431    /// Role Switch Pending
432    RoleSwitchPending,
433    /// Reserved for Future Use
434    ReservedForFutureUse51,
435    /// Reserved Slot Violation
436    ReservedSlotViolation,
437    /// Role Switch Failed
438    RoleSwitchFailed,
439    /// Extended Inquiry Response Too Large
440    ExtendedInquiryResponseTooLarge,
441    /// Secure Simple Pairing Not Supported By Host
442    SecureSimplePairingNotSupportedByHost,
443    /// Host Busy - Pairing
444    HostBusyPairing,
445    /// Connection Rejected due to No Suitable Channel Found
446    ConnectionRejectedNoSuitableChannel,
447    /// Controller Busy
448    ControllerBusy,
449    /// Unacceptable Connection Parameters
450    UnacceptableConnectionParameters,
451    /// Advertising Timeout
452    AdvertisingTimeout,
453    /// Connection Terminated due to MIC Failure
454    ConnectionTerminatedMicFailure,
455    /// Connection Failed to be Established
456    ConnectionFailedToEstablish,
457    /// MAC Connection Failed
458    MacConnectionFailed,
459    /// Coarse Clock Adjustment Rejected but Will Try to Adjust Using Clock Dragging
460    CoarseClockAdjustmentRejectedDraggingAttempted,
461    #[cfg(feature = "version-5-0")]
462    /// Type0 Submap Not Defined
463    ///
464    /// First introduced in version 5.0
465    Type0SubmapNotDefined,
466    #[cfg(feature = "version-5-0")]
467    /// Unknown Advertising Identifier
468    ///
469    /// First introduced in version 5.0
470    UnknownAdvertisingId,
471    #[cfg(feature = "version-5-0")]
472    /// Limit Reached
473    ///
474    /// First introduced in version 5.0
475    LimitReached,
476    #[cfg(feature = "version-5-0")]
477    /// Operation Cancelled by Host
478    ///
479    /// First introduced in version 5.0
480    OperationCancelledByHost,
481    /// Vendor-specific status code
482    Vendor(V),
483}
484
485/// Wrapper enum for errors converting a u8 into a [`Status`].
486pub enum BadStatusError {
487    /// The value does not map to a [`Status`].
488    BadValue(u8),
489}
490
491impl<V> core::convert::TryFrom<u8> for Status<V>
492where
493    V: core::convert::TryFrom<u8>,
494{
495    type Error = V::Error;
496
497    fn try_from(value: u8) -> Result<Status<V>, Self::Error> {
498        match value {
499            0x00 => Ok(Status::Success),
500            0x01 => Ok(Status::UnknownCommand),
501            0x02 => Ok(Status::UnknownConnectionId),
502            0x03 => Ok(Status::HardwareFailure),
503            0x04 => Ok(Status::PageTimeout),
504            0x05 => Ok(Status::AuthFailure),
505            0x06 => Ok(Status::PinOrKeyMissing),
506            0x07 => Ok(Status::OutOfMemory),
507            0x08 => Ok(Status::ConnectionTimeout),
508            0x09 => Ok(Status::ConnectionLimitExceeeded),
509            0x0A => Ok(Status::SyncConnectionLimitExceeded),
510            0x0B => Ok(Status::ConnectionAlreadyExists),
511            0x0C => Ok(Status::CommandDisallowed),
512            0x0D => Ok(Status::LimitedResources),
513            0x0E => Ok(Status::ConnectionRejectedSecurity),
514            0x0F => Ok(Status::UnacceptableBdAddr),
515            0x10 => Ok(Status::AcceptTimeoutExceeded),
516            0x11 => Ok(Status::UnsupportedFeature),
517            0x12 => Ok(Status::InvalidParameters),
518            0x13 => Ok(Status::RemoteTerminationByUser),
519            0x14 => Ok(Status::RemoteTerminationLowResources),
520            0x15 => Ok(Status::RemoteTerminationPowerOff),
521            0x16 => Ok(Status::ConnectionTerminatedByHost),
522            0x17 => Ok(Status::RepeatedAttempts),
523            0x18 => Ok(Status::PairingNotAllowed),
524            0x19 => Ok(Status::UnknownLmpPdu),
525            0x1A => Ok(Status::UnsupportedRemoteFeature),
526            0x1B => Ok(Status::ScoOffsetRejected),
527            0x1C => Ok(Status::ScoIntervalRejected),
528            0x1D => Ok(Status::ScoAirModeRejected),
529            0x1E => Ok(Status::InvalidLmpParameters),
530            0x1F => Ok(Status::UnspecifiedError),
531            0x20 => Ok(Status::UnsupportedLmpParameterValue),
532            0x21 => Ok(Status::RoleChangeNotAllowed),
533            0x22 => Ok(Status::LmpResponseTimeout),
534            0x23 => Ok(Status::LmpTransactionCollision),
535            0x24 => Ok(Status::LmpPduNotAllowed),
536            0x25 => Ok(Status::EncryptionModeNotAcceptable),
537            0x26 => Ok(Status::LinkKeyCannotBeChanged),
538            0x27 => Ok(Status::RequestedQosNotSupported),
539            0x28 => Ok(Status::InstantPassed),
540            0x29 => Ok(Status::PairingWithUnitKeyNotSupported),
541            0x2A => Ok(Status::DifferentTransactionCollision),
542            0x2B => Ok(Status::ReservedforFutureUse),
543            0x2C => Ok(Status::QosUnacceptableParameter),
544            0x2D => Ok(Status::QosRejected),
545            0x2E => Ok(Status::ChannelClassificationNotSupported),
546            0x2F => Ok(Status::InsufficientSecurity),
547            0x30 => Ok(Status::ParameterOutOfMandatoryRange),
548            0x31 => Ok(Status::ReservedForFutureUse49),
549            0x32 => Ok(Status::RoleSwitchPending),
550            0x33 => Ok(Status::ReservedForFutureUse51),
551            0x34 => Ok(Status::ReservedSlotViolation),
552            0x35 => Ok(Status::RoleSwitchFailed),
553            0x36 => Ok(Status::ExtendedInquiryResponseTooLarge),
554            0x37 => Ok(Status::SecureSimplePairingNotSupportedByHost),
555            0x38 => Ok(Status::HostBusyPairing),
556            0x39 => Ok(Status::ConnectionRejectedNoSuitableChannel),
557            0x3A => Ok(Status::ControllerBusy),
558            0x3B => Ok(Status::UnacceptableConnectionParameters),
559            0x3C => Ok(Status::AdvertisingTimeout),
560            0x3D => Ok(Status::ConnectionTerminatedMicFailure),
561            0x3E => Ok(Status::ConnectionFailedToEstablish),
562            0x3F => Ok(Status::MacConnectionFailed),
563            0x40 => Ok(Status::CoarseClockAdjustmentRejectedDraggingAttempted),
564            0x41 => {
565                #[cfg(feature = "version-5-0")]
566                {
567                    Ok(Status::Type0SubmapNotDefined)
568                }
569                #[cfg(not(feature = "version-5-0"))]
570                {
571                    Ok(Status::Vendor(V::try_from(value)?))
572                }
573            }
574            0x42 => {
575                #[cfg(feature = "version-5-0")]
576                {
577                    Ok(Status::UnknownAdvertisingId)
578                }
579                #[cfg(not(feature = "version-5-0"))]
580                {
581                    Ok(Status::Vendor(V::try_from(value)?))
582                }
583            }
584            0x43 => {
585                #[cfg(feature = "version-5-0")]
586                {
587                    Ok(Status::LimitReached)
588                }
589                #[cfg(not(feature = "version-5-0"))]
590                {
591                    Ok(Status::Vendor(V::try_from(value)?))
592                }
593            }
594            0x44 => {
595                #[cfg(feature = "version-5-0")]
596                {
597                    Ok(Status::OperationCancelledByHost)
598                }
599                #[cfg(not(feature = "version-5-0"))]
600                {
601                    Ok(Status::Vendor(V::try_from(value)?))
602                }
603            }
604            _ => Ok(Status::Vendor(V::try_from(value)?)),
605        }
606    }
607}
608
609impl<V> core::convert::Into<u8> for Status<V>
610where
611    V: core::convert::Into<u8>,
612{
613    fn into(self) -> u8 {
614        match self {
615            Status::Success => 0x00,
616            Status::UnknownCommand => 0x01,
617            Status::UnknownConnectionId => 0x02,
618            Status::HardwareFailure => 0x03,
619            Status::PageTimeout => 0x04,
620            Status::AuthFailure => 0x05,
621            Status::PinOrKeyMissing => 0x06,
622            Status::OutOfMemory => 0x07,
623            Status::ConnectionTimeout => 0x08,
624            Status::ConnectionLimitExceeeded => 0x09,
625            Status::SyncConnectionLimitExceeded => 0x0A,
626            Status::ConnectionAlreadyExists => 0x0B,
627            Status::CommandDisallowed => 0x0C,
628            Status::LimitedResources => 0x0D,
629            Status::ConnectionRejectedSecurity => 0x0E,
630            Status::UnacceptableBdAddr => 0x0F,
631            Status::AcceptTimeoutExceeded => 0x10,
632            Status::UnsupportedFeature => 0x11,
633            Status::InvalidParameters => 0x12,
634            Status::RemoteTerminationByUser => 0x13,
635            Status::RemoteTerminationLowResources => 0x14,
636            Status::RemoteTerminationPowerOff => 0x15,
637            Status::ConnectionTerminatedByHost => 0x16,
638            Status::RepeatedAttempts => 0x17,
639            Status::PairingNotAllowed => 0x18,
640            Status::UnknownLmpPdu => 0x19,
641            Status::UnsupportedRemoteFeature => 0x1A,
642            Status::ScoOffsetRejected => 0x1B,
643            Status::ScoIntervalRejected => 0x1C,
644            Status::ScoAirModeRejected => 0x1D,
645            Status::InvalidLmpParameters => 0x1E,
646            Status::UnspecifiedError => 0x1F,
647            Status::UnsupportedLmpParameterValue => 0x20,
648            Status::RoleChangeNotAllowed => 0x21,
649            Status::LmpResponseTimeout => 0x22,
650            Status::LmpTransactionCollision => 0x23,
651            Status::LmpPduNotAllowed => 0x24,
652            Status::EncryptionModeNotAcceptable => 0x25,
653            Status::LinkKeyCannotBeChanged => 0x26,
654            Status::RequestedQosNotSupported => 0x27,
655            Status::InstantPassed => 0x28,
656            Status::PairingWithUnitKeyNotSupported => 0x29,
657            Status::DifferentTransactionCollision => 0x2A,
658            Status::ReservedforFutureUse => 0x2B,
659            Status::QosUnacceptableParameter => 0x2C,
660            Status::QosRejected => 0x2D,
661            Status::ChannelClassificationNotSupported => 0x2E,
662            Status::InsufficientSecurity => 0x2F,
663            Status::ParameterOutOfMandatoryRange => 0x30,
664            Status::ReservedForFutureUse49 => 0x31,
665            Status::RoleSwitchPending => 0x32,
666            Status::ReservedForFutureUse51 => 0x33,
667            Status::ReservedSlotViolation => 0x34,
668            Status::RoleSwitchFailed => 0x35,
669            Status::ExtendedInquiryResponseTooLarge => 0x36,
670            Status::SecureSimplePairingNotSupportedByHost => 0x37,
671            Status::HostBusyPairing => 0x38,
672            Status::ConnectionRejectedNoSuitableChannel => 0x39,
673            Status::ControllerBusy => 0x3A,
674            Status::UnacceptableConnectionParameters => 0x3B,
675            Status::AdvertisingTimeout => 0x3C,
676            Status::ConnectionTerminatedMicFailure => 0x3D,
677            Status::ConnectionFailedToEstablish => 0x3E,
678            Status::MacConnectionFailed => 0x3F,
679            Status::CoarseClockAdjustmentRejectedDraggingAttempted => 0x40,
680            _ => {
681                #[cfg(feature = "version-5-0")]
682                {
683                    match self {
684                        Status::Type0SubmapNotDefined => 0x41,
685                        Status::UnknownAdvertisingId => 0x42,
686                        Status::LimitReached => 0x43,
687                        Status::OperationCancelledByHost => 0x44,
688                        Status::Vendor(v) => v.into(),
689                        _ => 0xFF,
690                    }
691                }
692
693                #[cfg(not(feature = "version-5-0"))]
694                {
695                    if let Status::Vendor(v) = self {
696                        v.into()
697                    } else {
698                        0xFF
699                    }
700                }
701            }
702        }
703    }
704}
705
706/// Newtype for a connection handle.
707#[derive(Clone, Copy, Debug, PartialEq)]
708pub struct ConnectionHandle(pub u16);
709
710/// Newtype for BDADDR.
711#[derive(Copy, Clone, Debug, PartialEq)]
712pub struct BdAddr(pub [u8; 6]);
713
714/// Potential values for BDADDR
715#[derive(Copy, Clone, Debug, PartialEq)]
716pub enum BdAddrType {
717    /// Public address.
718    Public(BdAddr),
719
720    /// Random address.
721    Random(BdAddr),
722}
723
724impl BdAddrType {
725    /// Writes a `BdAddrType` into the given slice.  The slice must be exactly the right length (7
726    /// bytes).
727    pub fn copy_into_slice(&self, bytes: &mut [u8]) {
728        assert_eq!(bytes.len(), 7);
729        match *self {
730            BdAddrType::Public(addr) => {
731                bytes[0] = 0;
732                bytes[1..7].copy_from_slice(&addr.0);
733            }
734            BdAddrType::Random(addr) => {
735                bytes[0] = 1;
736                bytes[1..7].copy_from_slice(&addr.0);
737            }
738        }
739    }
740}
741
742/// The BD Address type is not recognized.  Includes the unrecognized byte.
743///
744/// See [`to_bd_addr_type`]
745pub struct BdAddrTypeError(pub u8);
746
747/// Wraps a [`BdAddr`] in a [`BdAddrType`].
748///
749/// # Errors
750///
751/// - `bd_addr_type` does not denote an appropriate type. Returns the byte. The address is
752///   discarded.
753pub fn to_bd_addr_type(bd_addr_type: u8, addr: BdAddr) -> Result<BdAddrType, BdAddrTypeError> {
754    match bd_addr_type {
755        0 => Ok(BdAddrType::Public(addr)),
756        1 => Ok(BdAddrType::Random(addr)),
757        _ => Err(BdAddrTypeError(bd_addr_type)),
758    }
759}
760
761bitflags! {
762    /// Bitfield for LE Remote Features.
763    ///
764    /// Fields are defined in Vol 6, Part B, Section 4.6 of the spec.  See Table 4.3 (version 4.1)
765    /// or Table 4.4 (version 4.2 and 5.0).
766    #[derive(Default)]
767    pub struct LinkLayerFeature : u64 {
768        /// See section 4.6.1
769        const LE_ENCRYPTION = 1 << 0;
770        /// See section 4.6.2
771        const CONNECTION_PARAMETERS_REQUEST_PROCEDURE = 1 << 1;
772        /// See section 4.6.3
773        const EXTENDED_REJECT_INDICATION = 1 << 2;
774        /// See section 4.6.4
775        const PERIPHERAL_INITIATED_FEATURES_EXCHANGE = 1 << 3;
776        /// See section 4.6.5
777        const LE_PING = 1 << 4;
778        /// See section 4.6.6
779        #[cfg(any(feature = "version-4-2", feature = "version-5-0"))]
780        const LE_DATA_PACKET_LENGTH_EXTENSION = 1 << 5;
781        /// See section 4.6.7
782        #[cfg(any(feature = "version-4-2", feature = "version-5-0"))]
783        const LL_PRIVACY = 1 << 6;
784        /// See section 4.6.8
785        #[cfg(any(feature = "version-4-2", feature = "version-5-0"))]
786        const EXTENDED_SCANNER_FILTER_POLICIES = 1 << 7;
787        /// See section 4.6.9
788        #[cfg(feature = "version-5-0")]
789        const LE_2M_PHY = 1 << 8;
790        /// See section 4.6.10
791        #[cfg(feature = "version-5-0")]
792        const STABLE_MODULATION_INDEX_TX = 1 << 9;
793        /// See section 4.6.11
794        #[cfg(feature = "version-5-0")]
795        const STABLE_MODULATION_INDEX_RX = 1 << 10;
796        /// Not in section 4.6
797        #[cfg(feature = "version-5-0")]
798        const LE_CODED_PHY = 1 << 11;
799        /// See section 4.6.12
800        #[cfg(feature = "version-5-0")]
801        const LE_EXTENDED_ADVERTISING = 1 << 12;
802        /// See section 4.6.13
803        #[cfg(feature = "version-5-0")]
804        const LE_PERIODIC_ADVERTISING = 1 << 13;
805        /// See section 4.6.14
806        #[cfg(feature = "version-5-0")]
807        const CHANNEL_SELECTION_ALGORITHM_2 = 1 << 14;
808        /// Not in section 4.6
809        #[cfg(feature = "version-5-0")]
810        const LE_POWER_CLASS_1 = 1 << 15;
811        /// See section 4.6.15
812        #[cfg(feature = "version-5-0")]
813        const MINIMUM_NUMBER_OF_USED_CHANNELS_PROCEDURE = 1 << 16;
814    }
815}
816
817bitflag_array! {
818    /// Channel classifications for the LE Set Host Channel Classification command.
819    ///
820    /// If a flag is set, its classification is "Unknown".  If the flag is cleared, it is known
821    /// "bad".
822    #[derive(Copy, Clone, Debug)]
823    pub struct ChannelClassification : 5;
824    pub struct ChannelFlag;
825
826    /// Channel 0 classification not known.
827    const CH_0 = 0, 1 << 0;
828    /// Channel 1 classification not known.
829    const CH_1 = 0, 1 << 1;
830    /// Channel 2 classification not known.
831    const CH_2 = 0, 1 << 2;
832    /// Channel 3 classification not known.
833    const CH_3 = 0, 1 << 3;
834    /// Channel 4 classification not known.
835    const CH_4 = 0, 1 << 4;
836    /// Channel 5 classification not known.
837    const CH_5 = 0, 1 << 5;
838    /// Channel 6 classification not known.
839    const CH_6 = 0, 1 << 6;
840    /// Channel 7 classification not known.
841    const CH_7 = 0, 1 << 7;
842    /// Channel 8 classification not known.
843    const CH_8 = 1, 1 << 0;
844    /// Channel 9 classification not known.
845    const CH_9 = 1, 1 << 1;
846    /// Channel 10 classification not known.
847    const CH_10 = 1, 1 << 2;
848    /// Channel 11 classification not known.
849    const CH_11 = 1, 1 << 3;
850    /// Channel 12 classification not known.
851    const CH_12 = 1, 1 << 4;
852    /// Channel 13 classification not known.
853    const CH_13 = 1, 1 << 5;
854    /// Channel 14 classification not known.
855    const CH_14 = 1, 1 << 6;
856    /// Channel 15 classification not known.
857    const CH_15 = 1, 1 << 7;
858    /// Channel 16 classification not known.
859    const CH_16 = 2, 1 << 0;
860    /// Channel 17 classification not known.
861    const CH_17 = 2, 1 << 1;
862    /// Channel 18 classification not known.
863    const CH_18 = 2, 1 << 2;
864    /// Channel 19 classification not known.
865    const CH_19 = 2, 1 << 3;
866    /// Channel 20 classification not known.
867    const CH_20 = 2, 1 << 4;
868    /// Channel 21 classification not known.
869    const CH_21 = 2, 1 << 5;
870    /// Channel 22 classification not known.
871    const CH_22 = 2, 1 << 6;
872    /// Channel 23 classification not known.
873    const CH_23 = 2, 1 << 7;
874    /// Channel 24 classification not known.
875    const CH_24 = 3, 1 << 0;
876    /// Channel 25 classification not known.
877    const CH_25 = 3, 1 << 1;
878    /// Channel 26 classification not known.
879    const CH_26 = 3, 1 << 2;
880    /// Channel 27 classification not known.
881    const CH_27 = 3, 1 << 3;
882    /// Channel 28 classification not known.
883    const CH_28 = 3, 1 << 4;
884    /// Channel 29 classification not known.
885    const CH_29 = 3, 1 << 5;
886    /// Channel 30 classification not known.
887    const CH_30 = 3, 1 << 6;
888    /// Channel 31 classification not known.
889    const CH_31 = 3, 1 << 7;
890    /// Channel 32 classification not known.
891    const CH_32 = 4, 1 << 0;
892    /// Channel 33 classification not known.
893    const CH_33 = 4, 1 << 1;
894    /// Channel 34 classification not known.
895    const CH_34 = 4, 1 << 2;
896    /// Channel 35 classification not known.
897    const CH_35 = 4, 1 << 3;
898    /// Channel 36 classification not known.
899    const CH_36 = 4, 1 << 4;
900}