1pub mod adapter;
6pub mod bluetooth;
7mod macros;
8pub mod test;
9
10use std::borrow::ToOwned;
11use std::collections::{HashMap, HashSet};
12use std::string::String;
13use std::thread;
14use std::time::Duration;
15
16use bitflags::bitflags;
17use embedder_traits::{BluetoothDeviceDescription, EmbedderMsg, EmbedderProxy};
18use log::warn;
19use rand::{self, Rng};
20#[cfg(not(feature = "native-bluetooth"))]
21use servo_base::generic_channel::GenericReceiver;
22use servo_base::generic_channel::{self, GenericSender};
23use servo_base::id::WebViewId;
24use servo_bluetooth_traits::blocklist::{Blocklist, uuid_is_blocklisted};
25use servo_bluetooth_traits::scanfilter::{
26 BluetoothScanfilter, BluetoothScanfilterSequence, RequestDeviceoptions,
27};
28use servo_bluetooth_traits::{
29 BluetoothCharacteristicMsg, BluetoothDescriptorMsg, BluetoothDeviceMsg, BluetoothError,
30 BluetoothRequest, BluetoothResponse, BluetoothResponseResult, BluetoothResult,
31 BluetoothServiceMsg, GATTType,
32};
33use servo_config::pref;
34
35use crate::bluetooth::{
36 BluetoothAdapter, BluetoothDevice, BluetoothGATTCharacteristic, BluetoothGATTDescriptor,
37 BluetoothGATTService,
38};
39
40const MAXIMUM_TRANSACTION_TIME: u8 = 30;
43const CONNECTION_TIMEOUT_MS: u64 = 1000;
44const DISCOVERY_TIMEOUT_MS: u64 = 1500;
46
47bitflags! {
48 struct Flags: u32 {
49 const BROADCAST = 0b000000001;
50 const READ = 0b000000010;
51 const WRITE_WITHOUT_RESPONSE = 0b000000100;
52 const WRITE = 0b000001000;
53 const NOTIFY = 0b000010000;
54 const INDICATE = 0b000100000;
55 const AUTHENTICATED_SIGNED_WRITES = 0b001000000;
56 const RELIABLE_WRITE = 0b010000000;
57 const WRITABLE_AUXILIARIES = 0b100000000;
58 }
59}
60
61macro_rules! return_if_cached(
62 ($cache:expr, $key:expr) => (
63 if $cache.contains_key($key) {
64 return $cache.get($key);
65 }
66 );
67);
68
69pub trait BluetoothThreadFactory {
70 fn new(embedder_proxy: EmbedderProxy) -> Self;
71}
72
73impl BluetoothThreadFactory for GenericSender<BluetoothRequest> {
74 #[cfg(feature = "native-bluetooth")]
75 fn new(embedder_proxy: EmbedderProxy) -> GenericSender<BluetoothRequest> {
76 let (sender, receiver) = generic_channel::channel().unwrap();
77
78 thread::Builder::new()
79 .name("Bluetooth".to_owned())
80 .spawn(move || {
81 let runtime = tokio::runtime::Builder::new_current_thread()
82 .enable_all()
83 .build()
84 .expect("Failed to create bluetooth tokio runtime");
85
86 let adapter = runtime.block_on(async {
87 if pref!(dom_bluetooth_enabled) {
88 BluetoothAdapter::new().await.ok()
89 } else {
90 BluetoothAdapter::new_mock().ok()
91 }
92 });
93
94 let (async_sender, async_receiver) = tokio::sync::mpsc::unbounded_channel();
96 thread::Builder::new()
97 .name("BluetoothTokioBridge".to_owned())
98 .spawn(move || {
99 while let Ok(message) = receiver.recv() {
100 if async_sender.send(message).is_err() {
101 break;
102 }
103 }
104 })
105 .expect("BT Tokio Bridge thread spawning failed");
106
107 let mut manager = BluetoothManager::new(adapter, embedder_proxy);
108 runtime.block_on(manager.start(async_receiver));
109 })
110 .expect("Thread spawning failed");
111 sender
112 }
113
114 #[cfg(not(feature = "native-bluetooth"))]
115 fn new(embedder_proxy: EmbedderProxy) -> GenericSender<BluetoothRequest> {
116 let (sender, receiver) = generic_channel::channel().unwrap();
117 let adapter = if pref!(dom_bluetooth_enabled) {
118 BluetoothAdapter::new()
119 } else {
120 BluetoothAdapter::new_mock()
121 }
122 .ok();
123 thread::Builder::new()
124 .name("Bluetooth".to_owned())
125 .spawn(move || {
126 BluetoothManager::new(adapter, embedder_proxy).start_sync(receiver);
127 })
128 .expect("Thread spawning failed");
129 sender
130 }
131}
132
133async fn matches_filter(device: &BluetoothDevice, filter: &BluetoothScanfilter) -> bool {
135 if filter.is_empty_or_invalid() {
136 return false;
137 }
138
139 if let Some(name) = filter.get_name() {
141 if device.get_name().await.ok() != Some(name.to_string()) {
142 return false;
143 }
144 }
145
146 if !filter.get_name_prefix().is_empty() {
148 if let Ok(device_name) = device.get_name().await {
149 if !device_name.starts_with(filter.get_name_prefix()) {
150 return false;
151 }
152 } else {
153 return false;
154 }
155 }
156
157 if !filter.get_services().is_empty() {
159 if let Ok(device_uuids) = device.get_uuids().await {
160 for service in filter.get_services() {
161 if !device_uuids.iter().any(|x| x == service) {
162 return false;
163 }
164 }
165 }
166 }
167
168 if let Some(manufacturer_data) = filter.get_manufacturer_data() {
170 let advertised_manufacturer_data = match device.get_manufacturer_data().await {
171 Ok(data) => data,
172 Err(_) => return false,
173 };
174 for (id, (prefix, mask)) in manufacturer_data.iter() {
175 if let Some(advertised_data) = advertised_manufacturer_data.get(id) {
176 if !data_filter_matches(advertised_data, prefix, mask) {
177 return false;
178 }
179 } else {
180 return false;
181 }
182 }
183 }
184
185 if let Some(service_data) = filter.get_service_data() {
187 let advertised_service_data = match device.get_service_data().await {
188 Ok(data) => data,
189 Err(_) => return false,
190 };
191 for (uuid, (prefix, mask)) in service_data.iter() {
192 if let Some(advertised_data) = advertised_service_data.get(uuid.as_str()) {
193 if !data_filter_matches(advertised_data, prefix, mask) {
194 return false;
195 }
196 } else {
197 return false;
198 }
199 }
200 }
201
202 true
204}
205
206fn data_filter_matches(data: &[u8], prefix: &[u8], mask: &[u8]) -> bool {
208 if data.len() < prefix.len() {
211 return false;
212 }
213
214 for ((data, mask), prefix) in data.iter().zip(mask.iter()).zip(prefix.iter()) {
216 if data & mask != prefix & mask {
217 return false;
218 }
219 }
220
221 true
223}
224
225async fn matches_filters(device: &BluetoothDevice, filters: &BluetoothScanfilterSequence) -> bool {
226 if filters.has_empty_or_invalid_filter() {
227 return false;
228 }
229 for f in filters.iter() {
230 if matches_filter(device, f).await {
231 return true;
232 }
233 }
234 false
235}
236
237async fn async_sleep(duration: Duration) {
239 #[cfg(feature = "native-bluetooth")]
240 {
241 tokio::time::sleep(duration).await;
242 }
243 #[cfg(not(feature = "native-bluetooth"))]
244 {
245 thread::sleep(duration);
246 }
247}
248
249fn is_mock_adapter(adapter: &BluetoothAdapter) -> bool {
250 matches!(adapter, &BluetoothAdapter::Mock(_))
251}
252
253pub struct BluetoothManager {
254 adapter: Option<BluetoothAdapter>,
255 address_to_id: HashMap<String, String>,
256 service_to_device: HashMap<String, String>,
257 characteristic_to_service: HashMap<String, String>,
258 descriptor_to_characteristic: HashMap<String, String>,
259 cached_devices: HashMap<String, BluetoothDevice>,
260 cached_services: HashMap<String, BluetoothGATTService>,
261 cached_characteristics: HashMap<String, BluetoothGATTCharacteristic>,
262 cached_descriptors: HashMap<String, BluetoothGATTDescriptor>,
263 allowed_services: HashMap<String, HashSet<String>>,
264 embedder_proxy: EmbedderProxy,
265}
266
267impl BluetoothManager {
268 pub fn new(
269 adapter: Option<BluetoothAdapter>,
270 embedder_proxy: EmbedderProxy,
271 ) -> BluetoothManager {
272 BluetoothManager {
273 adapter,
274 address_to_id: HashMap::new(),
275 service_to_device: HashMap::new(),
276 characteristic_to_service: HashMap::new(),
277 descriptor_to_characteristic: HashMap::new(),
278 cached_devices: HashMap::new(),
279 cached_services: HashMap::new(),
280 cached_characteristics: HashMap::new(),
281 cached_descriptors: HashMap::new(),
282 allowed_services: HashMap::new(),
283 embedder_proxy,
284 }
285 }
286
287 #[cfg(feature = "native-bluetooth")]
290 async fn start(&mut self, mut rx: tokio::sync::mpsc::UnboundedReceiver<BluetoothRequest>) {
291 while let Some(msg) = rx.recv().await {
292 if self.handle_message(msg).await {
293 break;
294 }
295 }
296 }
297
298 #[cfg(not(feature = "native-bluetooth"))]
300 fn start_sync(&mut self, receiver: GenericReceiver<BluetoothRequest>) {
301 while let Ok(msg) = receiver.recv() {
304 let should_exit = futures::executor::block_on(self.handle_message(msg));
305 if should_exit {
306 break;
307 }
308 }
309 }
310
311 async fn handle_message(&mut self, msg: BluetoothRequest) -> bool {
313 match msg {
314 BluetoothRequest::RequestDevice(options, sender) => {
315 let _ = sender.send(self.request_device(options).await);
316 },
317 BluetoothRequest::GATTServerConnect(device_id, sender) => {
318 let _ = sender.send(self.gatt_server_connect(device_id).await);
319 },
320 BluetoothRequest::GATTServerDisconnect(device_id, sender) => {
321 let _ = sender.send(self.gatt_server_disconnect(device_id).await);
322 },
323 BluetoothRequest::GetGATTChildren(id, uuid, single, child_type, sender) => {
324 let _ = sender.send(self.get_gatt_children(id, uuid, single, child_type).await);
325 },
326 BluetoothRequest::ReadValue(id, sender) => {
327 let _ = sender.send(self.read_value(id).await);
328 },
329 BluetoothRequest::WriteValue(id, value, sender) => {
330 let _ = sender.send(self.write_value(id, value).await);
331 },
332 BluetoothRequest::EnableNotification(id, enable, sender) => {
333 let _ = sender.send(self.enable_notification(id, enable).await);
334 },
335 BluetoothRequest::WatchAdvertisements(id, sender) => {
336 let _ = sender.send(self.watch_advertisements(id));
337 },
338 BluetoothRequest::Test(data_set_name, sender) => {
339 let _ = sender.send(self.test(data_set_name).await);
340 },
341 BluetoothRequest::SetRepresentedToNull(
342 service_ids,
343 characteristic_ids,
344 descriptor_ids,
345 ) => self.remove_ids_from_caches(service_ids, characteristic_ids, descriptor_ids),
346 BluetoothRequest::IsRepresentedDeviceNull(id, sender) => {
347 let _ = sender.send(!self.device_is_cached(&id));
348 },
349 BluetoothRequest::GetAvailability(sender) => {
350 let _ = sender.send(self.get_availability().await);
351 },
352 BluetoothRequest::MatchesFilter(id, filters, sender) => {
353 let _ = sender.send(self.device_matches_filter(&id, &filters).await);
354 },
355 BluetoothRequest::Exit => return true,
356 }
357 false
358 }
359
360 async fn test(&mut self, data_set_name: String) -> BluetoothResult<()> {
363 self.address_to_id.clear();
364 self.service_to_device.clear();
365 self.characteristic_to_service.clear();
366 self.descriptor_to_characteristic.clear();
367 self.cached_devices.clear();
368 self.cached_services.clear();
369 self.cached_characteristics.clear();
370 self.cached_descriptors.clear();
371 self.allowed_services.clear();
372 self.adapter = BluetoothAdapter::new_mock().ok();
373 match test::test(self, data_set_name).await {
374 Ok(_) => Ok(()),
375 Err(error) => Err(BluetoothError::Type(error.to_string())),
376 }
377 }
378
379 fn remove_ids_from_caches(
380 &mut self,
381 service_ids: Vec<String>,
382 characteristic_ids: Vec<String>,
383 descriptor_ids: Vec<String>,
384 ) {
385 for id in service_ids {
386 self.cached_services.remove(&id);
387 self.service_to_device.remove(&id);
388 }
389
390 for id in characteristic_ids {
391 self.cached_characteristics.remove(&id);
392 self.characteristic_to_service.remove(&id);
393 }
394
395 for id in descriptor_ids {
396 self.cached_descriptors.remove(&id);
397 self.descriptor_to_characteristic.remove(&id);
398 }
399 }
400
401 pub async fn get_or_create_adapter(&mut self) -> Option<BluetoothAdapter> {
404 let adapter_valid = match self.adapter.as_ref() {
405 Some(a) => a.get_address().await.is_ok(),
406 None => false,
407 };
408 if !adapter_valid {
409 #[cfg(feature = "native-bluetooth")]
410 {
411 self.adapter = BluetoothAdapter::new().await.ok();
412 }
413 #[cfg(not(feature = "native-bluetooth"))]
414 {
415 self.adapter = BluetoothAdapter::new().ok();
416 }
417 }
418
419 let adapter = self.adapter.as_ref()?;
420
421 if is_mock_adapter(adapter) && !adapter.is_present().unwrap_or(false) {
422 return None;
423 }
424
425 self.adapter.clone()
426 }
427
428 async fn get_adapter(&mut self) -> BluetoothResult<BluetoothAdapter> {
429 match self.get_or_create_adapter().await {
430 Some(adapter) => {
431 if !adapter.is_powered().await.unwrap_or(false) {
432 return Err(BluetoothError::NotFound);
433 }
434 Ok(adapter)
435 },
436 None => Err(BluetoothError::NotFound),
437 }
438 }
439
440 async fn get_and_cache_devices(
443 &mut self,
444 adapter: &mut BluetoothAdapter,
445 ) -> Vec<BluetoothDevice> {
446 let devices = adapter.get_devices().await.unwrap_or_default();
447 for device in &devices {
448 if let Ok(address) = device.get_address() {
449 #[allow(clippy::map_entry)] if !self.address_to_id.contains_key(&address) {
451 let generated_id = self.generate_device_id();
452 self.address_to_id.insert(address, generated_id.clone());
453 self.cached_devices
454 .insert(generated_id.clone(), device.clone());
455 self.allowed_services.insert(generated_id, HashSet::new());
456 }
457 }
458 }
459 self.cached_devices.values().cloned().collect()
460 }
461
462 async fn get_device(
463 &mut self,
464 adapter: &mut BluetoothAdapter,
465 device_id: &str,
466 ) -> Option<&BluetoothDevice> {
467 return_if_cached!(self.cached_devices, device_id);
468 self.get_and_cache_devices(adapter).await;
469 return_if_cached!(self.cached_devices, device_id);
470 None
471 }
472
473 async fn select_device(
474 &mut self,
475 webview_id: WebViewId,
476 devices: Vec<BluetoothDevice>,
477 adapter: &BluetoothAdapter,
478 ) -> Option<String> {
479 if is_mock_adapter(adapter) {
480 for device in &devices {
481 if let Ok(address) = device.get_address() {
482 return Some(address);
483 }
484 }
485 return None;
486 }
487
488 let mut device_descriptions = Vec::with_capacity(devices.len());
489 for device in devices {
490 let address = device.get_address().unwrap_or_default();
491 let name = device.get_name().await.unwrap_or_else(|_| {
492 let short = if address.len() > 8 {
493 &address[..8]
494 } else {
495 &address
496 };
497 format!("Unknown ({}...)", short)
498 });
499 device_descriptions.push(BluetoothDeviceDescription { address, name });
500 }
501
502 let (ipc_sender, ipc_receiver) =
503 generic_channel::channel().expect("Failed to create IPC channel!");
504 self.embedder_proxy
505 .send(EmbedderMsg::GetSelectedBluetoothDevice(
506 webview_id,
507 device_descriptions,
508 ipc_sender,
509 ));
510
511 match ipc_receiver.recv() {
512 Ok(result) => result,
513 Err(e) => {
514 warn!("Failed to receive files from embedder ({:?}).", e);
515 None
516 },
517 }
518 }
519
520 fn generate_device_id(&mut self) -> String {
521 let mut device_id;
522 let mut rng = rand::rng();
523 loop {
524 device_id = rng.random::<u32>().to_string();
525 if !self.cached_devices.contains_key(&device_id) {
526 break;
527 }
528 }
529 device_id
530 }
531
532 fn device_from_service_id(&self, service_id: &str) -> Option<BluetoothDevice> {
533 let device_id = self.service_to_device.get(service_id)?;
534 self.cached_devices.get(device_id).cloned()
535 }
536
537 fn device_is_cached(&self, device_id: &str) -> bool {
538 self.cached_devices.contains_key(device_id) &&
539 self.address_to_id.values().any(|v| v == device_id)
540 }
541
542 async fn device_matches_filter(
543 &mut self,
544 device_id: &str,
545 filters: &BluetoothScanfilterSequence,
546 ) -> BluetoothResult<bool> {
547 let mut adapter = self.get_adapter().await?;
548 match self.get_device(&mut adapter, device_id).await {
549 Some(device) => Ok(matches_filters(device, filters).await),
550 None => Ok(false),
551 }
552 }
553
554 async fn get_and_cache_gatt_services(
557 &mut self,
558 adapter: &mut BluetoothAdapter,
559 device_id: &str,
560 ) -> Vec<BluetoothGATTService> {
561 let mut services = match self.get_device(adapter, device_id).await {
562 Some(d) => d.get_gatt_services().await.unwrap_or_default(),
563 None => vec![],
564 };
565
566 services.retain(|s| {
567 !uuid_is_blocklisted(&s.get_uuid().unwrap_or_default(), Blocklist::All) &&
568 self.allowed_services
569 .get(device_id)
570 .is_some_and(|uuids| uuids.contains(&s.get_uuid().unwrap_or_default()))
571 });
572 for service in &services {
573 self.cached_services
574 .insert(service.get_id(), service.clone());
575 self.service_to_device
576 .insert(service.get_id(), device_id.to_owned());
577 }
578 services
579 }
580
581 async fn get_gatt_service(
582 &mut self,
583 adapter: &mut BluetoothAdapter,
584 service_id: &str,
585 ) -> Option<&BluetoothGATTService> {
586 return_if_cached!(self.cached_services, service_id);
587 let device_id = self.service_to_device.get(service_id)?.clone();
588 self.get_and_cache_gatt_services(adapter, &device_id).await;
589 return_if_cached!(self.cached_services, service_id);
590 None
591 }
592
593 fn service_is_cached(&self, service_id: &str) -> bool {
594 self.cached_services.contains_key(service_id) &&
595 self.service_to_device.contains_key(service_id)
596 }
597
598 async fn get_and_cache_gatt_characteristics(
601 &mut self,
602 adapter: &mut BluetoothAdapter,
603 service_id: &str,
604 ) -> Vec<BluetoothGATTCharacteristic> {
605 let mut characteristics = match self.get_gatt_service(adapter, service_id).await {
606 Some(s) => s.get_gatt_characteristics().unwrap_or_default(),
607 None => vec![],
608 };
609
610 characteristics
611 .retain(|c| !uuid_is_blocklisted(&c.get_uuid().unwrap_or_default(), Blocklist::All));
612 for characteristic in &characteristics {
613 self.cached_characteristics
614 .insert(characteristic.get_id(), characteristic.clone());
615 self.characteristic_to_service
616 .insert(characteristic.get_id(), service_id.to_owned());
617 }
618 characteristics
619 }
620
621 async fn get_gatt_characteristic(
622 &mut self,
623 adapter: &mut BluetoothAdapter,
624 characteristic_id: &str,
625 ) -> Option<&BluetoothGATTCharacteristic> {
626 return_if_cached!(self.cached_characteristics, characteristic_id);
627 let service_id = self
628 .characteristic_to_service
629 .get(characteristic_id)?
630 .clone();
631 self.get_and_cache_gatt_characteristics(adapter, &service_id)
632 .await;
633 return_if_cached!(self.cached_characteristics, characteristic_id);
634 None
635 }
636
637 fn get_characteristic_properties(&self, characteristic: &BluetoothGATTCharacteristic) -> Flags {
638 let mut props: Flags = Flags::empty();
639 let flags = characteristic.get_flags().unwrap_or_default();
640 for flag in flags {
641 match flag.as_ref() {
642 "broadcast" => props.insert(Flags::BROADCAST),
643 "read" => props.insert(Flags::READ),
644 "write-without-response" => props.insert(Flags::WRITE_WITHOUT_RESPONSE),
645 "write" => props.insert(Flags::WRITE),
646 "notify" => props.insert(Flags::NOTIFY),
647 "indicate" => props.insert(Flags::INDICATE),
648 "authenticated-signed-writes" => props.insert(Flags::AUTHENTICATED_SIGNED_WRITES),
649 "reliable-write" => props.insert(Flags::RELIABLE_WRITE),
650 "writable-auxiliaries" => props.insert(Flags::WRITABLE_AUXILIARIES),
651 _ => (),
652 }
653 }
654 props
655 }
656
657 fn characteristic_is_cached(&self, characteristic_id: &str) -> bool {
658 self.cached_characteristics.contains_key(characteristic_id) &&
659 self.characteristic_to_service
660 .contains_key(characteristic_id)
661 }
662
663 async fn get_and_cache_gatt_descriptors(
666 &mut self,
667 adapter: &mut BluetoothAdapter,
668 characteristic_id: &str,
669 ) -> Vec<BluetoothGATTDescriptor> {
670 let mut descriptors = match self
671 .get_gatt_characteristic(adapter, characteristic_id)
672 .await
673 {
674 Some(c) => c.get_gatt_descriptors().unwrap_or_default(),
675 None => vec![],
676 };
677
678 descriptors
679 .retain(|d| !uuid_is_blocklisted(&d.get_uuid().unwrap_or_default(), Blocklist::All));
680 for descriptor in &descriptors {
681 self.cached_descriptors
682 .insert(descriptor.get_id(), descriptor.clone());
683 self.descriptor_to_characteristic
684 .insert(descriptor.get_id(), characteristic_id.to_owned());
685 }
686 descriptors
687 }
688
689 async fn get_gatt_descriptor(
690 &mut self,
691 adapter: &mut BluetoothAdapter,
692 descriptor_id: &str,
693 ) -> Option<&BluetoothGATTDescriptor> {
694 return_if_cached!(self.cached_descriptors, descriptor_id);
695 let characteristic_id = self
696 .descriptor_to_characteristic
697 .get(descriptor_id)?
698 .clone();
699 self.get_and_cache_gatt_descriptors(adapter, &characteristic_id)
700 .await;
701 return_if_cached!(self.cached_descriptors, descriptor_id);
702 None
703 }
704
705 async fn request_device(&mut self, options: RequestDeviceoptions) -> BluetoothResponseResult {
709 let mut adapter = self.get_adapter().await?;
711
712 if let Ok(ref session) = adapter.create_discovery_session() {
715 if session.start_discovery().await.is_ok() && !is_mock_adapter(&adapter) {
716 async_sleep(Duration::from_millis(DISCOVERY_TIMEOUT_MS)).await;
717 }
718 let _ = session.stop_discovery().await;
719 }
720
721 let mut matched_devices = self.get_and_cache_devices(&mut adapter).await;
722
723 if !options.is_accepting_all_devices() {
725 let mut filtered = Vec::new();
726 for d in matched_devices {
727 if matches_filters(&d, options.get_filters()).await {
728 filtered.push(d);
729 }
730 }
731 matched_devices = filtered;
732 }
733
734 if let Some(address) = self
736 .select_device(options.webview_id(), matched_devices, &adapter)
737 .await
738 {
739 let device_id = match self.address_to_id.get(&address) {
740 Some(id) => id.clone(),
741 None => return Err(BluetoothError::NotFound),
742 };
743 let mut services = options.get_services_set();
744 if let Some(services_set) = self.allowed_services.get(&device_id) {
745 services = services_set | &services;
746 }
747 self.allowed_services.insert(device_id.clone(), services);
748 if let Some(device) = self.get_device(&mut adapter, &device_id).await {
749 let message = BluetoothDeviceMsg {
750 id: device_id,
751 name: device.get_name().await.ok(),
752 };
753 return Ok(BluetoothResponse::RequestDevice(message));
754 }
755 }
756 Err(BluetoothError::NotFound)
758 }
760
761 async fn gatt_server_connect(&mut self, device_id: String) -> BluetoothResponseResult {
763 if !self.device_is_cached(&device_id) {
765 return Err(BluetoothError::Network);
766 }
767 let mut adapter = self.get_adapter().await?;
768
769 match self.get_device(&mut adapter, &device_id).await {
771 Some(d) => {
772 if d.is_connected().await.unwrap_or(false) {
773 return Ok(BluetoothResponse::GATTServerConnect(true));
774 }
775 let _ = d.connect().await;
776 for _ in 0..MAXIMUM_TRANSACTION_TIME {
777 if d.is_connected().await.unwrap_or(false) {
778 return Ok(BluetoothResponse::GATTServerConnect(true));
779 } else {
780 if is_mock_adapter(&adapter) {
781 break;
782 }
783 async_sleep(Duration::from_millis(CONNECTION_TIMEOUT_MS)).await;
784 }
785 }
787 Err(BluetoothError::Network)
789 },
790 None => Err(BluetoothError::NotFound),
791 }
792 }
793
794 async fn gatt_server_disconnect(&mut self, device_id: String) -> BluetoothResult<()> {
796 let mut adapter = self.get_adapter().await?;
797 match self.get_device(&mut adapter, &device_id).await {
798 Some(d) => {
799 if !d.is_connected().await.unwrap_or(true) {
801 return Ok(());
802 }
803 let _ = d.disconnect().await;
804 for _ in 0..MAXIMUM_TRANSACTION_TIME {
805 if d.is_connected().await.unwrap_or(true) {
806 async_sleep(Duration::from_millis(CONNECTION_TIMEOUT_MS)).await;
807 } else {
808 return Ok(());
809 }
810 }
811 Err(BluetoothError::Network)
812 },
813 None => Err(BluetoothError::NotFound),
814 }
815 }
816
817 async fn get_gatt_children(
819 &mut self,
820 id: String,
821 uuid: Option<String>,
822 single: bool,
823 child_type: GATTType,
824 ) -> BluetoothResponseResult {
825 let mut adapter = self.get_adapter().await?;
826 match child_type {
827 GATTType::PrimaryService => {
828 if !self.device_is_cached(&id) {
830 return Err(BluetoothError::InvalidState);
831 }
832 if let Some(ref uuid) = uuid {
834 if !self
835 .allowed_services
836 .get(&id)
837 .is_some_and(|s| s.contains(uuid))
838 {
839 return Err(BluetoothError::Security);
840 }
841 }
842 let mut services = self.get_and_cache_gatt_services(&mut adapter, &id).await;
843 if let Some(uuid) = uuid {
844 services.retain(|e| e.get_uuid().unwrap_or_default() == uuid);
845 }
846 let mut services_vec = vec![];
847 for service in services {
848 if service.is_primary().unwrap_or(false) {
849 if let Ok(uuid) = service.get_uuid() {
850 services_vec.push(BluetoothServiceMsg {
851 uuid,
852 is_primary: true,
853 instance_id: service.get_id(),
854 });
855 }
856 }
857 }
858
859 if services_vec.is_empty() {
861 return Err(BluetoothError::NotFound);
862 }
863
864 Ok(BluetoothResponse::GetPrimaryServices(services_vec, single))
865 },
866 GATTType::Characteristic => {
867 if !self.service_is_cached(&id) {
869 return Err(BluetoothError::InvalidState);
870 }
871 let mut characteristics = self
873 .get_and_cache_gatt_characteristics(&mut adapter, &id)
874 .await;
875 if let Some(uuid) = uuid {
876 characteristics.retain(|e| e.get_uuid().unwrap_or_default() == uuid);
877 }
878 let mut characteristics_vec = vec![];
879 for characteristic in characteristics {
880 if let Ok(uuid) = characteristic.get_uuid() {
881 let properties = self.get_characteristic_properties(&characteristic);
882 characteristics_vec.push(BluetoothCharacteristicMsg {
883 uuid,
884 instance_id: characteristic.get_id(),
885 broadcast: properties.contains(Flags::BROADCAST),
886 read: properties.contains(Flags::READ),
887 write_without_response: properties
888 .contains(Flags::WRITE_WITHOUT_RESPONSE),
889 write: properties.contains(Flags::WRITE),
890 notify: properties.contains(Flags::NOTIFY),
891 indicate: properties.contains(Flags::INDICATE),
892 authenticated_signed_writes: properties
893 .contains(Flags::AUTHENTICATED_SIGNED_WRITES),
894 reliable_write: properties.contains(Flags::RELIABLE_WRITE),
895 writable_auxiliaries: properties.contains(Flags::WRITABLE_AUXILIARIES),
896 });
897 }
898 }
899
900 if characteristics_vec.is_empty() {
902 return Err(BluetoothError::NotFound);
903 }
904
905 Ok(BluetoothResponse::GetCharacteristics(
906 characteristics_vec,
907 single,
908 ))
909 },
910 GATTType::IncludedService => {
911 if !self.service_is_cached(&id) {
913 return Err(BluetoothError::InvalidState);
914 }
915 let device = match self.device_from_service_id(&id) {
917 Some(device) => device,
918 None => return Err(BluetoothError::NotFound),
919 };
920 let primary_service = match self.get_gatt_service(&mut adapter, &id).await {
921 Some(s) => s,
922 None => return Err(BluetoothError::NotFound),
923 };
924 let services = primary_service.get_includes(device).unwrap_or(vec![]);
925 let mut services_vec = vec![];
926 for service in services {
927 if let Ok(service_uuid) = service.get_uuid() {
928 services_vec.push(BluetoothServiceMsg {
929 uuid: service_uuid,
930 is_primary: service.is_primary().unwrap_or(false),
931 instance_id: service.get_id(),
932 });
933 }
934 }
935 if let Some(uuid) = uuid {
936 services_vec.retain(|s| s.uuid == uuid);
937 }
938 services_vec.retain(|s| !uuid_is_blocklisted(&s.uuid, Blocklist::All));
939
940 if services_vec.is_empty() {
942 return Err(BluetoothError::NotFound);
943 }
944
945 Ok(BluetoothResponse::GetIncludedServices(services_vec, single))
946 },
947 GATTType::Descriptor => {
948 if !self.characteristic_is_cached(&id) {
950 return Err(BluetoothError::InvalidState);
951 }
952 let mut descriptors = self.get_and_cache_gatt_descriptors(&mut adapter, &id).await;
954 if let Some(uuid) = uuid {
955 descriptors.retain(|e| e.get_uuid().unwrap_or_default() == uuid);
956 }
957 let mut descriptors_vec = vec![];
958 for descriptor in descriptors {
959 if let Ok(uuid) = descriptor.get_uuid() {
960 descriptors_vec.push(BluetoothDescriptorMsg {
961 uuid,
962 instance_id: descriptor.get_id(),
963 });
964 }
965 }
966
967 if descriptors_vec.is_empty() {
969 return Err(BluetoothError::NotFound);
970 }
971 Ok(BluetoothResponse::GetDescriptors(descriptors_vec, single))
972 },
973 }
974 }
975
976 async fn read_value(&mut self, id: String) -> BluetoothResponseResult {
979 let mut adapter = self.get_adapter().await?;
982
983 let mut value = match self.get_gatt_characteristic(&mut adapter, &id).await {
985 Some(c) => Some(c.read_value().await.unwrap_or_default()),
986 None => None,
987 };
988
989 if value.is_none() {
993 value = match self.get_gatt_descriptor(&mut adapter, &id).await {
994 Some(d) => Some(d.read_value().await.unwrap_or_default()),
995 None => None,
996 };
997 }
998
999 match value {
1002 Some(v) => Ok(BluetoothResponse::ReadValue(v)),
1005
1006 None => Err(BluetoothError::InvalidState),
1009 }
1010 }
1011
1012 async fn write_value(&mut self, id: String, value: Vec<u8>) -> BluetoothResponseResult {
1015 let mut adapter = self.get_adapter().await?;
1018
1019 let mut result = match self.get_gatt_characteristic(&mut adapter, &id).await {
1021 Some(c) => Some(c.write_value(value.clone()).await),
1022 None => None,
1023 };
1024
1025 if result.is_none() {
1029 result = match self.get_gatt_descriptor(&mut adapter, &id).await {
1030 Some(d) => Some(d.write_value(value.clone()).await),
1031 None => None,
1032 };
1033 }
1034
1035 match result {
1038 Some(Ok(_)) => Ok(BluetoothResponse::WriteValue(value)),
1041
1042 Some(Err(_)) => Err(BluetoothError::NotSupported),
1044
1045 None => Err(BluetoothError::InvalidState),
1048 }
1049 }
1050
1051 async fn enable_notification(&mut self, id: String, enable: bool) -> BluetoothResponseResult {
1054 if !self.characteristic_is_cached(&id) {
1057 return Err(BluetoothError::InvalidState);
1058 }
1059
1060 let mut adapter = self.get_adapter().await?;
1062 match self.get_gatt_characteristic(&mut adapter, &id).await {
1063 Some(c) => {
1064 let result = if enable {
1065 c.start_notify().await
1068 } else {
1069 c.stop_notify().await
1071 };
1072 match result {
1073 Ok(_) => Ok(BluetoothResponse::EnableNotification(())),
1076
1077 Err(_) => Err(BluetoothError::NotSupported),
1079 }
1080 },
1081 None => Err(BluetoothError::InvalidState),
1083 }
1084 }
1085
1086 fn watch_advertisements(&mut self, _device_id: String) -> BluetoothResponseResult {
1088 Err(BluetoothError::NotSupported)
1091 }
1092
1093 async fn get_availability(&mut self) -> BluetoothResponseResult {
1095 Ok(BluetoothResponse::GetAvailability(
1096 self.get_adapter().await.is_ok(),
1097 ))
1098 }
1099}