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