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