prns_interfaces_embassy/bluetooth_auto/trouble/
mod.rs1mod backend;
2mod discovery;
3mod platform;
4mod sessions;
5mod tasks;
6
7use core::cell::{Cell, RefCell};
8
9use bt_hci::transport::Transport;
10use bt_hci::FromHciBytesError;
11use embassy_futures::select::{select, select3, select4, Either, Either3, Either4};
12use embassy_futures::yield_now;
13use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex as BridgeMutex;
14use embassy_sync::blocking_mutex::Mutex as BlockingMutex;
15use embassy_sync::channel::{Channel, Receiver, Sender};
16use embassy_sync::semaphore::{FairSemaphore, Semaphore, SemaphoreReleaser};
17use embassy_sync::signal::Signal;
18use embassy_sync_07::blocking_mutex::raw::NoopRawMutex;
19use embassy_time::{with_timeout, Duration, Instant, Timer};
20use heapless_09::Vec as GattVec;
21use portable_atomic::{AtomicBool, Ordering};
22use trouble_host::att::{AttClient, AttReq};
23use trouble_host::prelude::*;
24
25use prns_core::interfaces::bluetooth_auto::{
26 columba_connection_role, columba_role_capabilities, contains_service, encode_stream_frame,
27 fragments_of, BleAddress, BleIdentity, BleRoleCapabilities, ColumbaConnectionRole, Control,
28 Fragment, L2capPlan, PeerProtocol, Reassembler, BLE_HW_MTU, BLE_SERVICE_UUID_BYTES,
29 CONTROL_MAX_LEN, FRAGMENT_HEADER_LEN, STREAM_FRAME_PREFIX_LEN,
30};
31use prns_core::interfaces::bluetooth_auto::{
32 AdvertisingMode, BleBackend, BleEvent, BleLink, BleSink, BleSource, DialOutcome, Origin,
33 RadioMode, ScanningMode,
34};
35
36use super::connection_slots::{
37 ConnectionSlotDataOwners, ConnectionSlotLease, ConnectionSlotLinkLease, ConnectionSlotOwners,
38 ConnectionSlotPool, ConnectionSlotSinkLease, ConnectionSlotSourceLease,
39 ConnectionSlotWorkerLease, ReadyConnectionSlot, ReadyConnectionSlotParts,
40};
41use super::frame_pool::{FrameLease, FramePoolError, SharedFramePool};
42use super::runtime::BluetoothAutoStatus;
43
44pub use platform::PEER_CAPACITY;
45use platform::*;
46
47const HCI_COMMAND_CAPACITY: usize = 20;
48const ATTRIBUTE_TABLE: usize = 32;
49const CCCD_TABLE: usize = 4;
50pub const GATT_VALUE_CAP: usize = 244;
51const MAX_SERVICES: usize = 2;
52
53const CONTROL_UUID_LAST: u8 = 0xe7;
54const DATA_UUID_LAST: u8 = 0xe8;
55const COLUMBA_TX_UUID_LAST: u8 = 0xe4;
56const COLUMBA_RX_UUID_LAST: u8 = 0xe5;
57const COLUMBA_IDENTITY_UUID_LAST: u8 = 0xe6;
58const SERVICE_UUID_LAST: u8 = 0xe3;
59
60const GATT_REASSEMBLY_CAP: usize = 600;
61
62const GATT_OPERATION_TIMEOUT: Duration = Duration::from_secs(2);
63const CONNECT_TIMEOUT: Duration = Duration::from_secs(6);
65const GATT_SETUP_TIMEOUT: Duration = Duration::from_secs(6);
66
67const ADV_WINDOW: Duration = Duration::from_millis(600);
69const DISCOVERY_TURN_REST: Duration = Duration::from_millis(20);
70
71const CONTROL_QUEUE_DEPTH: usize = 2;
72const FRAME_QUEUE_DEPTH: usize = 2;
73const FRAME_POOL_CAPACITY: usize = PEER_CAPACITY;
74const FRAME_POOL_WAITERS: usize = PEER_CAPACITY + 1;
75const SIGHTING_DEPTH: usize = PEER_CAPACITY * 2;
76const SIGHTING_COALESCE_MS: u64 = 2_000;
77const RADIO_WAITERS: usize = 2;
78
79pub const L2CAP_PSM: u16 = 0x0080;
81const L2CAP_SDU_LEN: usize = STREAM_FRAME_PREFIX_LEN + BLE_HW_MTU;
82const L2CAP_SDU_LENGTH_PREFIX_LEN: u16 = size_of::<u16>() as u16;
83const L2CAP_CREDITS: u16 = (L2CAP_SDU_LEN as u16 + L2CAP_SDU_LENGTH_PREFIX_LEN).div_ceil(L2CAP_MPS);
84const _: () = assert!(L2CAP_SDU_LEN <= <DefaultPacketPool as trouble_host::PacketPool>::MTU);
85const L2CAP_HANDSHAKE_WINDOW: Duration = Duration::from_secs(5);
86const L2CAP_SETUP_RETRY: Duration = Duration::from_millis(150);
87const PHY_UPDATE_TIMEOUT: Duration = Duration::from_secs(2);
88const SEEN_CAP: usize = PEER_CAPACITY * 2;
90const FRAME_CAP: usize = BLE_HW_MTU;
91
92type RadioArbiter = FairSemaphore<BridgeMutex, RADIO_WAITERS>;
93type RadioPermit<'a> = SemaphoreReleaser<'a, RadioArbiter>;
94type DiscoveryTurnArbiter = FairSemaphore<BridgeMutex, RADIO_WAITERS>;
95type DiscoveryTurnPermit<'a> = SemaphoreReleaser<'a, DiscoveryTurnArbiter>;
96type BleSlotPool = ConnectionSlotPool<BridgeMutex, PEER_CAPACITY>;
97type BleSlotLease = ConnectionSlotLease<BridgeMutex>;
98type BleSlotWorker = ConnectionSlotWorkerLease<BridgeMutex>;
99type BleSlotLink = ConnectionSlotLinkLease<BridgeMutex>;
100type BleSlotSource = ConnectionSlotSourceLease<BridgeMutex>;
101type BleSlotSink = ConnectionSlotSinkLease<BridgeMutex>;
102type BleReadySlot = ReadyConnectionSlot<BridgeMutex>;
103type BleFramePool =
104 SharedFramePool<BridgeMutex, FRAME_CAP, FRAME_POOL_CAPACITY, FRAME_POOL_WAITERS>;
105type BleFrameLease = FrameLease<BridgeMutex, FRAME_CAP, FRAME_POOL_CAPACITY, FRAME_POOL_WAITERS>;
106pub trait TroubleTransport: Transport<Error: From<FromHciBytesError>> {}
107impl<T: Transport<Error: From<FromHciBytesError>>> TroubleTransport for T {}
108pub type TroubleController<T> = ExternalController<T, HCI_COMMAND_CAPACITY>;
109pub type TroubleStack<T> = Stack<'static, TroubleController<T>, DefaultPacketPool>;
110pub type GattServer = AttributeServer<
111 'static,
112 NoopRawMutex,
113 DefaultPacketPool,
114 ATTRIBUTE_TABLE,
115 CCCD_TABLE,
116 PEER_CAPACITY,
117>;
118pub type GattCharacteristic = Characteristic<GattVec<u8, GATT_VALUE_CAP>>;
119pub type ReticulumAttributeTable = AttributeTable<'static, NoopRawMutex, ATTRIBUTE_TABLE>;
120
121pub use backend::{
122 BleHub, Closed, EmbeddedBleBackend, EmbeddedBleLink, EmbeddedBleSink, EmbeddedBleSource,
123};
124pub use sessions::{
125 columba_identity_uuid, columba_rx_uuid, columba_tx_uuid, control_uuid, data_uuid,
126 reticulum_attribute_table, service_uuid, ReticulumGattCharacteristics, ReticulumGattUuids,
127};
128pub use tasks::{acceptor, dialer, host_runner, serve_slot};