1#![no_std]
2#![allow(dead_code)]
3#![allow(unused_variables)]
4#![allow(clippy::needless_lifetimes)]
5#![doc = include_str!(concat!("../", env!("CARGO_PKG_README")))]
6#![warn(missing_docs)]
7
8use core::mem::MaybeUninit;
9
10use advertise::AdvertisementDataError;
11use bt_hci::cmd::status::ReadRssi;
12use bt_hci::cmd::{AsyncCmd, SyncCmd};
13use bt_hci::param::{AddrKind, BdAddr};
14use bt_hci::FromHciBytesError;
15use embassy_time::Duration;
16#[cfg(feature = "security")]
17use heapless::Vec;
18use rand_core::{CryptoRng, RngCore};
19
20use crate::att::AttErrorCode;
21use crate::channel_manager::ChannelStorage;
22use crate::connection_manager::ConnectionStorage;
23#[cfg(feature = "security")]
24pub use crate::security_manager::{BondInformation, IdentityResolvingKey, LongTermKey};
25pub use crate::types::capabilities::IoCapabilities;
26
27pub(crate) const BI_COUNT: usize = 10; mod fmt;
31
32#[cfg(not(any(feature = "central", feature = "peripheral")))]
33compile_error!("Must enable at least one of the `central` or `peripheral` features");
34
35pub mod att;
36#[cfg(feature = "central")]
37pub mod central;
38mod channel_manager;
39mod codec;
40mod command;
41pub mod config;
42mod connection_manager;
43mod cursor;
44#[cfg(feature = "default-packet-pool")]
45mod packet_pool;
46mod pdu;
47#[cfg(feature = "peripheral")]
48pub mod peripheral;
49#[cfg(feature = "security")]
50mod security_manager;
51pub mod types;
52
53#[cfg(feature = "central")]
54use central::*;
55#[cfg(feature = "peripheral")]
56use peripheral::*;
57
58pub mod advertise;
59pub mod connection;
60#[cfg(feature = "gatt")]
61pub mod gap;
62pub mod l2cap;
63#[cfg(feature = "scan")]
64pub mod scan;
65
66#[cfg(test)]
67pub(crate) mod mock_controller;
68
69pub(crate) mod host;
70use host::{AdvHandleState, BleHost, HostMetrics, Runner};
71
72pub mod prelude {
73 pub use bt_hci::controller::ExternalController;
75 pub use bt_hci::param::{AddrKind, BdAddr, LeConnRole as Role, PhyKind, PhyMask};
76 pub use bt_hci::transport::SerialTransport;
77 pub use bt_hci::uuid::*;
78 #[cfg(feature = "derive")]
79 pub use heapless::String as HeaplessString;
80 #[cfg(feature = "derive")]
81 pub use trouble_host_macros::*;
82
83 pub use super::att::AttErrorCode;
84 pub use super::{BleHostError, Controller, Error, Host, HostResources, Packet, PacketPool, Stack};
85 #[cfg(feature = "peripheral")]
86 pub use crate::advertise::*;
87 #[cfg(feature = "gatt")]
88 pub use crate::attribute::*;
89 #[cfg(feature = "gatt")]
90 pub use crate::attribute_server::*;
91 #[cfg(feature = "central")]
92 pub use crate::central::*;
93 pub use crate::connection::*;
94 #[cfg(feature = "gatt")]
95 pub use crate::gap::*;
96 #[cfg(feature = "gatt")]
97 pub use crate::gatt::*;
98 pub use crate::host::{ControlRunner, EventHandler, HostMetrics, Runner, RxRunner, TxRunner};
99 pub use crate::l2cap::*;
100 #[cfg(feature = "default-packet-pool")]
101 pub use crate::packet_pool::DefaultPacketPool;
102 pub use crate::pdu::Sdu;
103 #[cfg(feature = "peripheral")]
104 pub use crate::peripheral::*;
105 #[cfg(feature = "scan")]
106 pub use crate::scan::*;
107 #[cfg(feature = "security")]
108 pub use crate::security_manager::{BondInformation, IdentityResolvingKey, LongTermKey};
109 pub use crate::types::capabilities::IoCapabilities;
110 #[cfg(feature = "gatt")]
111 pub use crate::types::gatt_traits::{AsGatt, FixedGattValue, FromGatt};
112 pub use crate::{Address, Identity};
113}
114
115#[cfg(feature = "gatt")]
116pub mod attribute;
117#[cfg(feature = "gatt")]
118mod attribute_server;
119#[cfg(feature = "gatt")]
120pub mod gatt;
121
122#[derive(Debug, Clone, Copy, PartialEq)]
134pub struct Address {
135 pub kind: AddrKind,
137 pub addr: BdAddr,
139}
140
141impl Address {
142 pub fn random(val: [u8; 6]) -> Self {
144 Self {
145 kind: AddrKind::RANDOM,
146 addr: BdAddr::new(val),
147 }
148 }
149
150 pub fn to_bytes(&self) -> [u8; 7] {
152 let mut bytes = [0; 7];
153 bytes[0] = self.kind.into_inner();
154 let mut addr_bytes = self.addr.into_inner();
155 addr_bytes.reverse();
156 bytes[1..].copy_from_slice(&addr_bytes);
157 bytes
158 }
159}
160
161impl core::fmt::Display for Address {
162 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
163 let a = self.addr.into_inner();
164 write!(
165 f,
166 "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
167 a[5], a[4], a[3], a[2], a[1], a[0]
168 )
169 }
170}
171
172#[cfg(feature = "defmt")]
173impl defmt::Format for Address {
174 fn format(&self, fmt: defmt::Formatter) {
175 let a = self.addr.into_inner();
176 defmt::write!(
177 fmt,
178 "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
179 a[5],
180 a[4],
181 a[3],
182 a[2],
183 a[1],
184 a[0]
185 )
186 }
187}
188
189#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
196pub struct Identity {
197 pub bd_addr: BdAddr,
199
200 #[cfg(feature = "security")]
202 pub irk: Option<IdentityResolvingKey>,
203}
204
205#[cfg(feature = "defmt")]
206impl defmt::Format for Identity {
207 fn format(&self, fmt: defmt::Formatter) {
208 defmt::write!(fmt, "BdAddr({:X}) ", self.bd_addr);
209 #[cfg(feature = "security")]
210 defmt::write!(fmt, "Irk({:X})", self.irk);
211 }
212}
213
214impl Identity {
215 pub fn match_address(&self, address: &BdAddr) -> bool {
217 if self.bd_addr == *address {
218 return true;
219 }
220 #[cfg(feature = "security")]
221 if let Some(irk) = self.irk {
222 return irk.resolve_address(address);
223 }
224 false
225 }
226
227 pub fn match_identity(&self, identity: &Identity) -> bool {
229 if self.match_address(&identity.bd_addr) {
230 return true;
231 }
232 #[cfg(feature = "security")]
233 if let Some(irk) = identity.irk {
234 if let Some(current_irk) = self.irk {
235 return irk == current_irk;
236 } else {
237 return irk.resolve_address(&self.bd_addr);
238 }
239 }
240 false
241 }
242}
243
244#[derive(Debug)]
246#[cfg_attr(feature = "defmt", derive(defmt::Format))]
247pub enum BleHostError<E> {
248 Controller(E),
250 BleHost(Error),
252}
253
254pub const MAX_INVALID_DATA_LEN: usize = 16;
256
257#[derive(Debug, Clone, PartialEq)]
259#[cfg_attr(feature = "defmt", derive(defmt::Format))]
260pub enum Error {
261 Hci(bt_hci::param::Error),
263 HciDecode(FromHciBytesError),
265 Att(AttErrorCode),
267 #[cfg(feature = "security")]
268 Security(crate::security_manager::Reason),
270 InsufficientSpace,
272 InvalidValue,
274
275 UnexpectedDataLength {
281 expected: usize,
283 actual: usize,
285 },
286
287 CannotConstructGattValue([u8; MAX_INVALID_DATA_LEN]),
289
290 ConfigFilterAcceptListIsEmpty,
292
293 UnexpectedGattResponse,
295
296 MalformedCharacteristicDeclaration {
298 expected: usize,
300 actual: usize,
302 },
303
304 InvalidCharacteristicDeclarationData,
306
307 FailedToFinalize {
309 expected: usize,
311 actual: usize,
313 },
314
315 CodecError(codec::Error),
317
318 ExtendedAdvertisingNotSupported,
320
321 InvalidUuidLength(usize),
323
324 Advertisement(AdvertisementDataError),
326 InvalidChannelId,
328 NoChannelAvailable,
330 NotFound,
332 InvalidState,
334 OutOfMemory,
336 NotSupported,
338 ChannelClosed,
340 Timeout,
342 Busy,
344 NoPermits,
346 Disconnected,
348 ConnectionLimitReached,
350 GattSubscriberLimitReached,
354 Other,
356}
357
358impl<E> From<Error> for BleHostError<E> {
359 fn from(value: Error) -> Self {
360 Self::BleHost(value)
361 }
362}
363
364impl From<FromHciBytesError> for Error {
365 fn from(error: FromHciBytesError) -> Self {
366 Self::HciDecode(error)
367 }
368}
369
370impl From<AttErrorCode> for Error {
371 fn from(error: AttErrorCode) -> Self {
372 Self::Att(error)
373 }
374}
375
376impl<E> From<bt_hci::cmd::Error<E>> for BleHostError<E> {
377 fn from(error: bt_hci::cmd::Error<E>) -> Self {
378 match error {
379 bt_hci::cmd::Error::Hci(p) => Self::BleHost(Error::Hci(p)),
380 bt_hci::cmd::Error::Io(p) => Self::Controller(p),
381 }
382 }
383}
384
385impl<E> From<bt_hci::param::Error> for BleHostError<E> {
386 fn from(error: bt_hci::param::Error) -> Self {
387 Self::BleHost(Error::Hci(error))
388 }
389}
390
391impl From<codec::Error> for Error {
392 fn from(error: codec::Error) -> Self {
393 match error {
394 codec::Error::InsufficientSpace => Error::InsufficientSpace,
395 codec::Error::InvalidValue => Error::CodecError(error),
396 }
397 }
398}
399
400impl<E> From<codec::Error> for BleHostError<E> {
401 fn from(error: codec::Error) -> Self {
402 match error {
403 codec::Error::InsufficientSpace => BleHostError::BleHost(Error::InsufficientSpace),
404 codec::Error::InvalidValue => BleHostError::BleHost(Error::InvalidValue),
405 }
406 }
407}
408
409use bt_hci::cmd::controller_baseband::*;
410use bt_hci::cmd::info::*;
411use bt_hci::cmd::le::*;
412use bt_hci::cmd::link_control::*;
413use bt_hci::controller::{ControllerCmdAsync, ControllerCmdSync};
414
415pub trait Controller:
419 bt_hci::controller::Controller
420 + embedded_io::ErrorType
421 + ControllerCmdSync<LeReadBufferSize>
422 + ControllerCmdSync<Disconnect>
423 + ControllerCmdSync<SetEventMask>
424 + ControllerCmdSync<SetEventMaskPage2>
425 + ControllerCmdSync<LeSetEventMask>
426 + ControllerCmdSync<LeSetRandomAddr>
427 + ControllerCmdSync<HostBufferSize>
428 + ControllerCmdAsync<LeConnUpdate>
429 + ControllerCmdSync<LeReadFilterAcceptListSize>
430 + ControllerCmdSync<SetControllerToHostFlowControl>
431 + ControllerCmdSync<Reset>
432 + ControllerCmdSync<ReadRssi>
433 + ControllerCmdSync<LeCreateConnCancel>
434 + ControllerCmdSync<LeSetScanEnable>
435 + ControllerCmdSync<LeSetExtScanEnable>
436 + ControllerCmdAsync<LeCreateConn>
437 + ControllerCmdSync<LeClearFilterAcceptList>
438 + ControllerCmdSync<LeAddDeviceToFilterAcceptList>
439 + for<'t> ControllerCmdSync<LeSetAdvEnable>
440 + for<'t> ControllerCmdSync<LeSetExtAdvEnable<'t>>
441 + for<'t> ControllerCmdSync<HostNumberOfCompletedPackets<'t>>
442 + ControllerCmdSync<LeReadBufferSize>
443 + for<'t> ControllerCmdSync<LeSetAdvData>
444 + ControllerCmdSync<LeSetAdvParams>
445 + for<'t> ControllerCmdSync<LeSetAdvEnable>
446 + for<'t> ControllerCmdSync<LeSetScanResponseData>
447 + ControllerCmdSync<LeLongTermKeyRequestReply>
448 + ControllerCmdAsync<LeEnableEncryption>
449 + ControllerCmdSync<ReadBdAddr>
450{
451}
452
453impl<
454 C: bt_hci::controller::Controller
455 + embedded_io::ErrorType
456 + ControllerCmdSync<LeReadBufferSize>
457 + ControllerCmdSync<Disconnect>
458 + ControllerCmdSync<SetEventMask>
459 + ControllerCmdSync<SetEventMaskPage2>
460 + ControllerCmdSync<LeSetEventMask>
461 + ControllerCmdSync<LeSetRandomAddr>
462 + ControllerCmdSync<HostBufferSize>
463 + ControllerCmdAsync<LeConnUpdate>
464 + ControllerCmdSync<LeReadFilterAcceptListSize>
465 + ControllerCmdSync<LeClearFilterAcceptList>
466 + ControllerCmdSync<LeAddDeviceToFilterAcceptList>
467 + ControllerCmdSync<SetControllerToHostFlowControl>
468 + ControllerCmdSync<Reset>
469 + ControllerCmdSync<ReadRssi>
470 + ControllerCmdSync<LeSetScanEnable>
471 + ControllerCmdSync<LeSetExtScanEnable>
472 + ControllerCmdSync<LeCreateConnCancel>
473 + ControllerCmdAsync<LeCreateConn>
474 + for<'t> ControllerCmdSync<LeSetAdvEnable>
475 + for<'t> ControllerCmdSync<LeSetExtAdvEnable<'t>>
476 + for<'t> ControllerCmdSync<HostNumberOfCompletedPackets<'t>>
477 + ControllerCmdSync<LeReadBufferSize>
478 + for<'t> ControllerCmdSync<LeSetAdvData>
479 + ControllerCmdSync<LeSetAdvParams>
480 + for<'t> ControllerCmdSync<LeSetAdvEnable>
481 + for<'t> ControllerCmdSync<LeSetScanResponseData>
482 + ControllerCmdSync<LeLongTermKeyRequestReply>
483 + ControllerCmdAsync<LeEnableEncryption>
484 + ControllerCmdSync<ReadBdAddr>,
485 > Controller for C
486{
487}
488
489pub trait Packet: Sized + AsRef<[u8]> + AsMut<[u8]> {}
492
493pub trait PacketPool: 'static {
497 type Packet: Packet;
499
500 const MTU: usize;
502
503 fn allocate() -> Option<Self::Packet>;
511
512 fn capacity() -> usize;
514}
515
516pub struct HostResources<P: PacketPool, const CONNS: usize, const CHANNELS: usize, const ADV_SETS: usize = 1> {
521 connections: MaybeUninit<[ConnectionStorage<P::Packet>; CONNS]>,
522 channels: MaybeUninit<[ChannelStorage<P::Packet>; CHANNELS]>,
523 advertise_handles: MaybeUninit<[AdvHandleState; ADV_SETS]>,
524}
525
526impl<P: PacketPool, const CONNS: usize, const CHANNELS: usize, const ADV_SETS: usize> Default
527 for HostResources<P, CONNS, CHANNELS, ADV_SETS>
528{
529 fn default() -> Self {
530 Self::new()
531 }
532}
533
534impl<P: PacketPool, const CONNS: usize, const CHANNELS: usize, const ADV_SETS: usize>
535 HostResources<P, CONNS, CHANNELS, ADV_SETS>
536{
537 pub const fn new() -> Self {
539 Self {
540 connections: MaybeUninit::uninit(),
541 channels: MaybeUninit::uninit(),
542 advertise_handles: MaybeUninit::uninit(),
543 }
544 }
545}
546
547pub fn new<
550 'resources,
551 C: Controller,
552 P: PacketPool,
553 const CONNS: usize,
554 const CHANNELS: usize,
555 const ADV_SETS: usize,
556>(
557 controller: C,
558 resources: &'resources mut HostResources<P, CONNS, CHANNELS, ADV_SETS>,
559) -> Stack<'resources, C, P> {
560 unsafe fn transmute_slice<T>(x: &mut [T]) -> &'static mut [T] {
561 unsafe { core::mem::transmute(x) }
562 }
563
564 let connections: &mut [ConnectionStorage<P::Packet>] =
571 &mut *resources.connections.write([const { ConnectionStorage::new() }; CONNS]);
572 let connections: &'resources mut [ConnectionStorage<P::Packet>] = unsafe { transmute_slice(connections) };
573
574 let channels = &mut *resources.channels.write([const { ChannelStorage::new() }; CHANNELS]);
575 let channels: &'static mut [ChannelStorage<P::Packet>] = unsafe { transmute_slice(channels) };
576
577 let advertise_handles = &mut *resources.advertise_handles.write([AdvHandleState::None; ADV_SETS]);
578 let advertise_handles: &'static mut [AdvHandleState] = unsafe { transmute_slice(advertise_handles) };
579 let host: BleHost<'_, C, P> = BleHost::new(controller, connections, channels, advertise_handles);
580
581 Stack { host }
582}
583
584pub struct Stack<'stack, C, P: PacketPool> {
586 host: BleHost<'stack, C, P>,
587}
588
589#[non_exhaustive]
591pub struct Host<'stack, C, P: PacketPool> {
592 #[cfg(feature = "central")]
594 pub central: Central<'stack, C, P>,
595 #[cfg(feature = "peripheral")]
597 pub peripheral: Peripheral<'stack, C, P>,
598 pub runner: Runner<'stack, C, P>,
600}
601
602impl<'stack, C: Controller, P: PacketPool> Stack<'stack, C, P> {
603 pub fn set_random_address(mut self, address: Address) -> Self {
605 self.host.address.replace(address);
606 #[cfg(feature = "security")]
607 self.host.connections.security_manager.set_local_address(address);
608 self
609 }
610 pub fn set_random_generator_seed<RNG: RngCore + CryptoRng>(self, _random_generator: &mut RNG) -> Self {
612 #[cfg(feature = "security")]
613 {
614 let mut random_seed = [0u8; 32];
615 _random_generator.fill_bytes(&mut random_seed);
616 self.host
617 .connections
618 .security_manager
619 .set_random_generator_seed(random_seed);
620 }
621 self
622 }
623 pub fn set_io_capabilities(self, io_capabilities: IoCapabilities) -> Self {
627 #[cfg(feature = "security")]
628 {
629 self.host
630 .connections
631 .security_manager
632 .set_io_capabilities(io_capabilities);
633 }
634 self
635 }
636
637 pub fn build(&'stack self) -> Host<'stack, C, P> {
639 #[cfg(all(feature = "security", not(feature = "dev-disable-csprng-seed-requirement")))]
640 {
641 if !self.host.connections.security_manager.get_random_generator_seeded() {
642 panic!(
643 "The security manager random number generator has not been seeded from a cryptographically secure random number generator"
644 )
645 }
646 }
647 Host {
648 #[cfg(feature = "central")]
649 central: Central::new(self),
650 #[cfg(feature = "peripheral")]
651 peripheral: Peripheral::new(self),
652 runner: Runner::new(self),
653 }
654 }
655
656 pub async fn command<T>(&self, cmd: T) -> Result<T::Return, BleHostError<C::Error>>
658 where
659 T: SyncCmd,
660 C: ControllerCmdSync<T>,
661 {
662 self.host.command(cmd).await
663 }
664
665 pub async fn async_command<T>(&self, cmd: T) -> Result<(), BleHostError<C::Error>>
667 where
668 T: AsyncCmd,
669 C: ControllerCmdAsync<T>,
670 {
671 self.host.async_command(cmd).await
672 }
673
674 pub fn metrics<F: FnOnce(&HostMetrics) -> R, R>(&self, f: F) -> R {
676 self.host.metrics(f)
677 }
678
679 pub fn log_status(&self, verbose: bool) {
681 self.host.log_status(verbose);
682 }
683
684 #[cfg(feature = "security")]
685 pub fn add_bond_information(&self, bond_information: BondInformation) -> Result<(), Error> {
687 self.host
688 .connections
689 .security_manager
690 .add_bond_information(bond_information)
691 }
692
693 #[cfg(feature = "security")]
694 pub fn remove_bond_information(&self, identity: Identity) -> Result<(), Error> {
696 self.host.connections.security_manager.remove_bond_information(identity)
697 }
698
699 #[cfg(feature = "security")]
700 pub fn get_bond_information(&self) -> Vec<BondInformation, BI_COUNT> {
702 self.host.connections.security_manager.get_bond_information()
703 }
704}
705
706pub(crate) fn bt_hci_duration<const US: u32>(d: Duration) -> bt_hci::param::Duration<US> {
707 bt_hci::param::Duration::from_micros(d.as_micros())
708}
709
710pub(crate) fn bt_hci_ext_duration<const US: u16>(d: Duration) -> bt_hci::param::ExtDuration<US> {
711 bt_hci::param::ExtDuration::from_micros(d.as_micros())
712}