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::Connection;
23use crate::connection_manager::ConnectionStorage;
24#[cfg(feature = "security")]
25pub use crate::security_manager::{BondInformation, IdentityResolvingKey, LongTermKey};
26pub use crate::types::capabilities::IoCapabilities;
27
28pub(crate) const BI_COUNT: usize = 10; mod fmt;
32
33#[cfg(not(any(feature = "central", feature = "peripheral")))]
34compile_error!("Must enable at least one of the `central` or `peripheral` features");
35
36pub mod att;
37#[cfg(feature = "central")]
38pub mod central;
39mod channel_manager;
40mod codec;
41mod command;
42pub mod config;
43mod connection_manager;
44mod cursor;
45#[cfg(feature = "default-packet-pool")]
46mod packet_pool;
47mod pdu;
48#[cfg(feature = "peripheral")]
49pub mod peripheral;
50#[cfg(feature = "security")]
51mod security_manager;
52pub mod types;
53
54#[cfg(feature = "central")]
55use central::*;
56#[cfg(feature = "peripheral")]
57use peripheral::*;
58
59pub mod advertise;
60pub mod connection;
61#[cfg(feature = "gatt")]
62pub mod gap;
63pub mod l2cap;
64#[cfg(feature = "scan")]
65pub mod scan;
66
67#[cfg(test)]
68pub(crate) mod mock_controller;
69
70pub(crate) mod host;
71use host::{AdvHandleState, BleHost, HostMetrics, Runner};
72
73pub mod prelude {
74 pub use bt_hci::controller::ExternalController;
76 pub use bt_hci::param::{AddrKind, BdAddr, LeConnRole as Role, PhyKind, PhyMask};
77 pub use bt_hci::transport::SerialTransport;
78 pub use bt_hci::uuid::*;
79 #[cfg(feature = "derive")]
80 pub use heapless::String as HeaplessString;
81 #[cfg(feature = "derive")]
82 pub use trouble_host_macros::*;
83
84 pub use super::att::AttErrorCode;
85 pub use super::{BleHostError, Controller, Error, Host, HostResources, Packet, PacketPool, Stack};
86 #[cfg(feature = "peripheral")]
87 pub use crate::advertise::*;
88 #[cfg(feature = "gatt")]
89 pub use crate::attribute::*;
90 #[cfg(feature = "gatt")]
91 pub use crate::attribute_server::*;
92 #[cfg(feature = "central")]
93 pub use crate::central::*;
94 pub use crate::connection::*;
95 #[cfg(feature = "gatt")]
96 pub use crate::gap::*;
97 #[cfg(feature = "gatt")]
98 pub use crate::gatt::*;
99 pub use crate::host::{ControlRunner, EventHandler, HostMetrics, Runner, RxRunner, TxRunner};
100 pub use crate::l2cap::*;
101 #[cfg(feature = "default-packet-pool")]
102 pub use crate::packet_pool::DefaultPacketPool;
103 pub use crate::pdu::Sdu;
104 #[cfg(feature = "peripheral")]
105 pub use crate::peripheral::*;
106 #[cfg(feature = "scan")]
107 pub use crate::scan::*;
108 #[cfg(feature = "security")]
109 pub use crate::security_manager::{BondInformation, IdentityResolvingKey, LongTermKey};
110 pub use crate::types::capabilities::IoCapabilities;
111 #[cfg(feature = "gatt")]
112 pub use crate::types::gatt_traits::{AsGatt, FixedGattValue, FromGatt};
113 pub use crate::{Address, Identity};
114}
115
116#[cfg(feature = "gatt")]
117pub mod attribute;
118#[cfg(feature = "gatt")]
119mod attribute_server;
120#[cfg(feature = "gatt")]
121pub mod gatt;
122
123#[derive(Debug, Clone, Copy, PartialEq)]
135pub struct Address {
136 pub kind: AddrKind,
138 pub addr: BdAddr,
140}
141
142impl Address {
143 pub fn random(val: [u8; 6]) -> Self {
145 Self {
146 kind: AddrKind::RANDOM,
147 addr: BdAddr::new(val),
148 }
149 }
150
151 pub fn to_bytes(&self) -> [u8; 7] {
153 let mut bytes = [0; 7];
154 bytes[0] = self.kind.into_inner();
155 let mut addr_bytes = self.addr.into_inner();
156 addr_bytes.reverse();
157 bytes[1..].copy_from_slice(&addr_bytes);
158 bytes
159 }
160}
161
162impl core::fmt::Display for Address {
163 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
164 let a = self.addr.into_inner();
165 write!(
166 f,
167 "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
168 a[5], a[4], a[3], a[2], a[1], a[0]
169 )
170 }
171}
172
173#[cfg(feature = "defmt")]
174impl defmt::Format for Address {
175 fn format(&self, fmt: defmt::Formatter) {
176 let a = self.addr.into_inner();
177 defmt::write!(
178 fmt,
179 "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
180 a[5],
181 a[4],
182 a[3],
183 a[2],
184 a[1],
185 a[0]
186 )
187 }
188}
189
190#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
197pub struct Identity {
198 pub bd_addr: BdAddr,
200
201 #[cfg(feature = "security")]
203 pub irk: Option<IdentityResolvingKey>,
204}
205
206#[cfg(feature = "defmt")]
207impl defmt::Format for Identity {
208 fn format(&self, fmt: defmt::Formatter) {
209 defmt::write!(fmt, "BdAddr({:X}) ", self.bd_addr);
210 #[cfg(feature = "security")]
211 defmt::write!(fmt, "Irk({:X})", self.irk);
212 }
213}
214
215impl Identity {
216 pub fn match_address(&self, address: &BdAddr) -> bool {
218 if self.bd_addr == *address {
219 return true;
220 }
221 #[cfg(feature = "security")]
222 if let Some(irk) = self.irk {
223 return irk.resolve_address(address);
224 }
225 false
226 }
227
228 pub fn match_identity(&self, identity: &Identity) -> bool {
230 if self.match_address(&identity.bd_addr) {
231 return true;
232 }
233 #[cfg(feature = "security")]
234 if let Some(irk) = identity.irk {
235 if let Some(current_irk) = self.irk {
236 return irk == current_irk;
237 } else {
238 return irk.resolve_address(&self.bd_addr);
239 }
240 }
241 false
242 }
243}
244
245#[derive(Debug)]
247#[cfg_attr(feature = "defmt", derive(defmt::Format))]
248pub enum BleHostError<E> {
249 Controller(E),
251 BleHost(Error),
253}
254
255pub const MAX_INVALID_DATA_LEN: usize = 16;
257
258#[derive(Debug, Clone, PartialEq)]
260#[cfg_attr(feature = "defmt", derive(defmt::Format))]
261pub enum Error {
262 Hci(bt_hci::param::Error),
264 HciDecode(FromHciBytesError),
266 Att(AttErrorCode),
268 #[cfg(feature = "security")]
269 Security(crate::security_manager::Reason),
271 InsufficientSpace,
273 InvalidValue,
275
276 UnexpectedDataLength {
282 expected: usize,
284 actual: usize,
286 },
287
288 CannotConstructGattValue([u8; MAX_INVALID_DATA_LEN]),
290
291 ConfigFilterAcceptListIsEmpty,
293
294 UnexpectedGattResponse,
296
297 MalformedCharacteristicDeclaration {
299 expected: usize,
301 actual: usize,
303 },
304
305 InvalidCharacteristicDeclarationData,
307
308 FailedToFinalize {
310 expected: usize,
312 actual: usize,
314 },
315
316 CodecError(codec::Error),
318
319 ExtendedAdvertisingNotSupported,
321
322 InvalidUuidLength(usize),
324
325 Advertisement(AdvertisementDataError),
327 InvalidChannelId,
329 NoChannelAvailable,
331 NotFound,
333 InvalidState,
335 OutOfMemory,
337 NotSupported,
339 ChannelClosed,
341 Timeout,
343 Busy,
345 NoPermits,
347 Disconnected,
349 ConnectionLimitReached,
351 GattSubscriberLimitReached,
355 Other,
357}
358
359impl<E> From<Error> for BleHostError<E> {
360 fn from(value: Error) -> Self {
361 Self::BleHost(value)
362 }
363}
364
365impl From<FromHciBytesError> for Error {
366 fn from(error: FromHciBytesError) -> Self {
367 Self::HciDecode(error)
368 }
369}
370
371impl From<AttErrorCode> for Error {
372 fn from(error: AttErrorCode) -> Self {
373 Self::Att(error)
374 }
375}
376
377impl<E> From<bt_hci::cmd::Error<E>> for BleHostError<E> {
378 fn from(error: bt_hci::cmd::Error<E>) -> Self {
379 match error {
380 bt_hci::cmd::Error::Hci(p) => Self::BleHost(Error::Hci(p)),
381 bt_hci::cmd::Error::Io(p) => Self::Controller(p),
382 }
383 }
384}
385
386impl<E> From<bt_hci::param::Error> for BleHostError<E> {
387 fn from(error: bt_hci::param::Error) -> Self {
388 Self::BleHost(Error::Hci(error))
389 }
390}
391
392impl From<codec::Error> for Error {
393 fn from(error: codec::Error) -> Self {
394 match error {
395 codec::Error::InsufficientSpace => Error::InsufficientSpace,
396 codec::Error::InvalidValue => Error::CodecError(error),
397 }
398 }
399}
400
401impl<E> From<codec::Error> for BleHostError<E> {
402 fn from(error: codec::Error) -> Self {
403 match error {
404 codec::Error::InsufficientSpace => BleHostError::BleHost(Error::InsufficientSpace),
405 codec::Error::InvalidValue => BleHostError::BleHost(Error::InvalidValue),
406 }
407 }
408}
409
410use bt_hci::cmd::controller_baseband::*;
411use bt_hci::cmd::info::*;
412use bt_hci::cmd::le::*;
413use bt_hci::cmd::link_control::*;
414use bt_hci::controller::{ControllerCmdAsync, ControllerCmdSync};
415
416pub trait Controller:
420 bt_hci::controller::Controller
421 + embedded_io::ErrorType
422 + ControllerCmdSync<LeReadBufferSize>
423 + ControllerCmdSync<Disconnect>
424 + ControllerCmdSync<SetEventMask>
425 + ControllerCmdSync<SetEventMaskPage2>
426 + ControllerCmdSync<LeSetEventMask>
427 + ControllerCmdSync<LeSetRandomAddr>
428 + ControllerCmdSync<HostBufferSize>
429 + ControllerCmdAsync<LeConnUpdate>
430 + ControllerCmdSync<LeReadFilterAcceptListSize>
431 + ControllerCmdSync<SetControllerToHostFlowControl>
432 + ControllerCmdSync<Reset>
433 + ControllerCmdSync<ReadRssi>
434 + ControllerCmdSync<LeCreateConnCancel>
435 + ControllerCmdSync<LeSetScanEnable>
436 + ControllerCmdSync<LeSetExtScanEnable>
437 + ControllerCmdAsync<LeCreateConn>
438 + ControllerCmdSync<LeClearFilterAcceptList>
439 + ControllerCmdSync<LeAddDeviceToFilterAcceptList>
440 + for<'t> ControllerCmdSync<LeSetAdvEnable>
441 + for<'t> ControllerCmdSync<LeSetExtAdvEnable<'t>>
442 + for<'t> ControllerCmdSync<HostNumberOfCompletedPackets<'t>>
443 + ControllerCmdSync<LeReadBufferSize>
444 + for<'t> ControllerCmdSync<LeSetAdvData>
445 + ControllerCmdSync<LeSetAdvParams>
446 + for<'t> ControllerCmdSync<LeSetAdvEnable>
447 + for<'t> ControllerCmdSync<LeSetScanResponseData>
448 + ControllerCmdSync<LeLongTermKeyRequestReply>
449 + ControllerCmdAsync<LeEnableEncryption>
450 + ControllerCmdSync<ReadBdAddr>
451{
452}
453
454impl<
455 C: bt_hci::controller::Controller
456 + embedded_io::ErrorType
457 + ControllerCmdSync<LeReadBufferSize>
458 + ControllerCmdSync<Disconnect>
459 + ControllerCmdSync<SetEventMask>
460 + ControllerCmdSync<SetEventMaskPage2>
461 + ControllerCmdSync<LeSetEventMask>
462 + ControllerCmdSync<LeSetRandomAddr>
463 + ControllerCmdSync<HostBufferSize>
464 + ControllerCmdAsync<LeConnUpdate>
465 + ControllerCmdSync<LeReadFilterAcceptListSize>
466 + ControllerCmdSync<LeClearFilterAcceptList>
467 + ControllerCmdSync<LeAddDeviceToFilterAcceptList>
468 + ControllerCmdSync<SetControllerToHostFlowControl>
469 + ControllerCmdSync<Reset>
470 + ControllerCmdSync<ReadRssi>
471 + ControllerCmdSync<LeSetScanEnable>
472 + ControllerCmdSync<LeSetExtScanEnable>
473 + ControllerCmdSync<LeCreateConnCancel>
474 + ControllerCmdAsync<LeCreateConn>
475 + for<'t> ControllerCmdSync<LeSetAdvEnable>
476 + for<'t> ControllerCmdSync<LeSetExtAdvEnable<'t>>
477 + for<'t> ControllerCmdSync<HostNumberOfCompletedPackets<'t>>
478 + ControllerCmdSync<LeReadBufferSize>
479 + for<'t> ControllerCmdSync<LeSetAdvData>
480 + ControllerCmdSync<LeSetAdvParams>
481 + for<'t> ControllerCmdSync<LeSetAdvEnable>
482 + for<'t> ControllerCmdSync<LeSetScanResponseData>
483 + ControllerCmdSync<LeLongTermKeyRequestReply>
484 + ControllerCmdAsync<LeEnableEncryption>
485 + ControllerCmdSync<ReadBdAddr>,
486 > Controller for C
487{
488}
489
490pub trait Packet: Sized + AsRef<[u8]> + AsMut<[u8]> {}
493
494pub trait PacketPool: 'static {
498 type Packet: Packet;
500
501 const MTU: usize;
503
504 fn allocate() -> Option<Self::Packet>;
512
513 fn capacity() -> usize;
515}
516
517pub struct HostResources<P: PacketPool, const CONNS: usize, const CHANNELS: usize, const ADV_SETS: usize = 1> {
522 connections: MaybeUninit<[ConnectionStorage<P::Packet>; CONNS]>,
523 channels: MaybeUninit<[ChannelStorage<P::Packet>; CHANNELS]>,
524 advertise_handles: MaybeUninit<[AdvHandleState; ADV_SETS]>,
525}
526
527impl<P: PacketPool, const CONNS: usize, const CHANNELS: usize, const ADV_SETS: usize> Default
528 for HostResources<P, CONNS, CHANNELS, ADV_SETS>
529{
530 fn default() -> Self {
531 Self::new()
532 }
533}
534
535impl<P: PacketPool, const CONNS: usize, const CHANNELS: usize, const ADV_SETS: usize>
536 HostResources<P, CONNS, CHANNELS, ADV_SETS>
537{
538 pub const fn new() -> Self {
540 Self {
541 connections: MaybeUninit::uninit(),
542 channels: MaybeUninit::uninit(),
543 advertise_handles: MaybeUninit::uninit(),
544 }
545 }
546}
547
548pub fn new<
551 'resources,
552 C: Controller,
553 P: PacketPool,
554 const CONNS: usize,
555 const CHANNELS: usize,
556 const ADV_SETS: usize,
557>(
558 controller: C,
559 resources: &'resources mut HostResources<P, CONNS, CHANNELS, ADV_SETS>,
560) -> Stack<'resources, C, P> {
561 unsafe fn transmute_slice<T>(x: &mut [T]) -> &'static mut [T] {
562 unsafe { core::mem::transmute(x) }
563 }
564
565 let connections: &mut [ConnectionStorage<P::Packet>] =
572 &mut *resources.connections.write([const { ConnectionStorage::new() }; CONNS]);
573 let connections: &'resources mut [ConnectionStorage<P::Packet>] = unsafe { transmute_slice(connections) };
574
575 let channels = &mut *resources.channels.write([const { ChannelStorage::new() }; CHANNELS]);
576 let channels: &'static mut [ChannelStorage<P::Packet>] = unsafe { transmute_slice(channels) };
577
578 let advertise_handles = &mut *resources.advertise_handles.write([AdvHandleState::None; ADV_SETS]);
579 let advertise_handles: &'static mut [AdvHandleState] = unsafe { transmute_slice(advertise_handles) };
580 let host: BleHost<'_, C, P> = BleHost::new(controller, connections, channels, advertise_handles);
581
582 Stack { host }
583}
584
585pub struct Stack<'stack, C, P: PacketPool> {
587 host: BleHost<'stack, C, P>,
588}
589
590#[non_exhaustive]
592pub struct Host<'stack, C, P: PacketPool> {
593 #[cfg(feature = "central")]
595 pub central: Central<'stack, C, P>,
596 #[cfg(feature = "peripheral")]
598 pub peripheral: Peripheral<'stack, C, P>,
599 pub runner: Runner<'stack, C, P>,
601}
602
603impl<'stack, C: Controller, P: PacketPool> Stack<'stack, C, P> {
604 pub fn set_random_address(mut self, address: Address) -> Self {
606 self.host.address.replace(address);
607 #[cfg(feature = "security")]
608 self.host.connections.security_manager.set_local_address(address);
609 self
610 }
611 pub fn set_random_generator_seed<RNG: RngCore + CryptoRng>(self, _random_generator: &mut RNG) -> Self {
613 #[cfg(feature = "security")]
614 {
615 let mut random_seed = [0u8; 32];
616 _random_generator.fill_bytes(&mut random_seed);
617 self.host
618 .connections
619 .security_manager
620 .set_random_generator_seed(random_seed);
621 }
622 self
623 }
624 pub fn set_io_capabilities(&self, io_capabilities: IoCapabilities) {
628 #[cfg(feature = "security")]
629 {
630 self.host
631 .connections
632 .security_manager
633 .set_io_capabilities(io_capabilities);
634 }
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 pub fn get_connection_by_peer_address(&'stack self, peer_address: Address) -> Option<Connection<'stack, P>> {
707 self.host.connections.get_connection_by_peer_address(peer_address)
708 }
709}
710
711pub(crate) fn bt_hci_duration<const US: u32>(d: Duration) -> bt_hci::param::Duration<US> {
712 bt_hci::param::Duration::from_micros(d.as_micros())
713}
714
715pub(crate) fn bt_hci_ext_duration<const US: u16>(d: Duration) -> bt_hci::param::ExtDuration<US> {
716 bt_hci::param::ExtDuration::from_micros(d.as_micros())
717}