1 //! Main BT lifecycle support 2 3 pub mod hal; 4 pub mod hci; 5 pub mod link; 6 7 use crate::hal::rootcanal_hal::RootcanalConfig; 8 use crate::hal::snoop::{SnoopConfig, SnoopMode}; 9 use bt_common::GrpcFacade; 10 use gddi::{module, Registry, RegistryBuilder, Stoppable}; 11 use std::sync::Arc; 12 use tokio::runtime::Runtime; 13 14 module! { 15 stack_module, 16 submodules { 17 crate::hal::hal_module, 18 crate::hci::hci_module, 19 } 20 } 21 22 /// Central state manager 23 pub struct Stack { 24 registry: Arc<Registry>, 25 rt: Arc<Runtime>, 26 } 27 28 impl Stack { 29 /// Construct a new Stack new(rt: Arc<Runtime>) -> Self30 pub async fn new(rt: Arc<Runtime>) -> Self { 31 let registry = Arc::new(RegistryBuilder::new().register_module(stack_module).build()); 32 registry.inject(rt.clone()).await; 33 34 Self { registry, rt } 35 } 36 37 /// Helper to set the rootcanal port set_rootcanal_port(&self, port: Option<u16>)38 pub async fn set_rootcanal_port(&self, port: Option<u16>) { 39 if let Some(port) = port { 40 self.registry.inject(RootcanalConfig::new("127.0.0.1", port)).await; 41 } 42 } 43 44 /// Configures snoop with defaults use_default_snoop(&self)45 pub async fn use_default_snoop(&self) { 46 self.configure_snoop(None).await; 47 } 48 49 /// Configures snoop. If the path is provided, full logging is turned on configure_snoop(&self, path: Option<String>)50 pub async fn configure_snoop(&self, path: Option<String>) { 51 let mut config = SnoopConfig::default(); 52 if let Some(path) = path { 53 config.set_path(path); 54 config.set_mode(SnoopMode::Full); 55 } 56 self.registry.inject(config).await; 57 } 58 59 /// Helper forwarding to underlying registry get<T: 'static + Clone + Send + Sync + Stoppable>(&self) -> T60 pub async fn get<T: 'static + Clone + Send + Sync + Stoppable>(&self) -> T { 61 self.registry.get::<T>().await 62 } 63 64 /// Get, but blocks the current thread. get_blocking<T: 'static + Clone + Send + Sync + Stoppable>(&self) -> T65 pub fn get_blocking<T: 'static + Clone + Send + Sync + Stoppable>(&self) -> T { 66 self.rt.block_on(self.get::<T>()) 67 } 68 69 /// Helper to get a grpc service get_grpc<T: 'static + Clone + Send + Sync + GrpcFacade + Stoppable>( &self, ) -> grpcio::Service70 pub async fn get_grpc<T: 'static + Clone + Send + Sync + GrpcFacade + Stoppable>( 71 &self, 72 ) -> grpcio::Service { 73 self.get::<T>().await.into_grpc() 74 } 75 76 /// Stop the stack stop(&mut self)77 pub async fn stop(&mut self) { 78 self.registry.stop_all().await; 79 } 80 81 /// Stop, but blocks the current thread. stop_blocking(&mut self)82 pub fn stop_blocking(&mut self) { 83 let rt = self.rt.clone(); 84 rt.block_on(self.stop()); 85 } 86 87 /// Get a clone of the underlying runtime for this stack get_runtime(&self) -> Arc<Runtime>88 pub fn get_runtime(&self) -> Arc<Runtime> { 89 self.rt.clone() 90 } 91 } 92