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