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}