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