aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorMartin Robinson <mrobinson@igalia.com>2024-01-09 10:13:41 +0100
committerGitHub <noreply@github.com>2024-01-09 09:13:41 +0000
commit6a804cd775e3976103269ac54ae997a3accc8618 (patch)
tree1a125d1901e5aa3cc98a1f5beabebd927a3b9472 /components
parentfddc4a430fca591152c69f0793ab946dcdc81617 (diff)
downloadservo-6a804cd775e3976103269ac54ae997a3accc8618.tar.gz
servo-6a804cd775e3976103269ac54ae997a3accc8618.zip
Integrate the `devices` respository (#30974)
Despite the name of this dependency, it only handles bluetooth. Because it's a separate repository. Integrating it, allows changes here to be tested more consistently. In addition, it's likely that new bluetooth libraries will allow removing the majority of the platform-specific code in this directory. This is based on the version of this dependency from: https://github.com/servo/devices/pull/34
Diffstat (limited to 'components')
-rw-r--r--components/bluetooth/Cargo.toml14
-rw-r--r--components/bluetooth/README.md55
-rw-r--r--components/bluetooth/adapter.rs408
-rw-r--r--components/bluetooth/bluetooth.rs753
-rw-r--r--components/bluetooth/empty.rs377
-rw-r--r--components/bluetooth/lib.rs26
-rw-r--r--components/bluetooth/macros.rs98
-rw-r--r--components/bluetooth/test.rs8
8 files changed, 1725 insertions, 14 deletions
diff --git a/components/bluetooth/Cargo.toml b/components/bluetooth/Cargo.toml
index fa2a6feb742..4046b256a1b 100644
--- a/components/bluetooth/Cargo.toml
+++ b/components/bluetooth/Cargo.toml
@@ -13,7 +13,7 @@ path = "lib.rs"
[dependencies]
bitflags = { workspace = true }
bluetooth_traits = { workspace = true }
-device = { git = "https://github.com/servo/devices", features = ["bluetooth-test"], rev = "cb28c4725ffbfece99dab842d17d3e8c50774778" }
+blurmock = { version = "0.1.2", optional = true }
embedder_traits = { workspace = true }
ipc-channel = { workspace = true }
log = { workspace = true }
@@ -22,4 +22,14 @@ servo_rand = { path = "../rand" }
uuid = { workspace = true }
[features]
-native-bluetooth = ["device/bluetooth"]
+native-bluetooth = ["blurz", "blurdroid", "blurmac", "bluetooth-test"]
+bluetooth-test = ["blurmock"]
+
+[target.'cfg(target_os = "linux")'.dependencies]
+blurz = { version = "0.3", optional = true }
+
+[target.'cfg(target_os = "android")'.dependencies]
+blurdroid = { version = "0.1.2", optional = true }
+
+[target.'cfg(target_os = "macos")'.dependencies]
+blurmac = { path = "../../third_party/blurmac", optional = true }
diff --git a/components/bluetooth/README.md b/components/bluetooth/README.md
new file mode 100644
index 00000000000..ec6e536d66a
--- /dev/null
+++ b/components/bluetooth/README.md
@@ -0,0 +1,55 @@
+# Bluetooth Rust lib using macOS CoreBluetooth
+
+[![Build Status](https://travis-ci.org/akosthekiss/blurmac.svg?branch=master)](https://travis-ci.org/akosthekiss/blurmac)
+[![Crates.io](https://img.shields.io/crates/v/blurmac.svg)](https://crates.io/crates/blurmac)
+
+The main aim of BlurMac is to enable [WebBluetooth](https://webbluetoothcg.github.io)
+in [Servo](https://github.com/servo/servo) on macOS. Thus, API and implementation
+decisions are affected by the encapsulating [Devices](https://github.com/servo/devices),
+and the sibling [BlurZ](https://github.com/szeged/blurz) and [BlurDroid](https://github.com/szeged/blurdroid)
+crates.
+
+
+## Run Servo with WebBluetooth Enabled
+
+Usually, you don't want to work with BlurMac on its own but use it within Servo.
+So, most probably you'll want to run Servo with WebBluetooth enabled:
+
+```
+RUST_LOG=blurmac \
+./mach run \
+ --dev \
+ --pref=dom.bluetooth.enabled \
+ --pref=dom.permissions.testing.allowed_in_nonsecure_contexts \
+ URL
+```
+
+Notes:
+* The above command is actually not really BlurMac-specific (except for the `RUST_LOG`
+ part). It runs Servo with WBT enabled on any platform where WBT is supported.
+* You don't need the `RUST_LOG=blurmac` part if you don't want to see BlurMac debug
+ messages on the console.
+* You don't need the `--dev` part if you want to run a release build.
+* You don't need the `--pref=dom.permissions.testing.allowed_in_nonsecure_contexts`
+ part if your `URL` is https (but you do need it if you test a local file).
+
+
+## Known Issues
+
+* Device RSSI can not be retrieved yet.
+* Support for included services is incomplete.
+* Descriptors are not supported yet.
+* Notifications on characteristics are not supported yet (the limitation comes from
+ Devices).
+
+
+## Compatibility
+
+Tested on:
+
+* macOS Sierra 10.12.
+
+
+## Copyright and Licensing
+
+Licensed under the BSD 3-Clause [License](LICENSE.md).
diff --git a/components/bluetooth/adapter.rs b/components/bluetooth/adapter.rs
new file mode 100644
index 00000000000..b5cd71b4543
--- /dev/null
+++ b/components/bluetooth/adapter.rs
@@ -0,0 +1,408 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use std::error::Error;
+use std::sync::Arc;
+
+#[cfg(all(target_os = "android", feature = "bluetooth"))]
+use blurdroid::bluetooth_adapter::Adapter as BluetoothAdapterAndroid;
+#[cfg(all(target_os = "android", feature = "bluetooth"))]
+use blurdroid::bluetooth_device::Device as BluetoothDeviceAndroid;
+#[cfg(all(target_os = "android", feature = "bluetooth"))]
+use blurdroid::bluetooth_discovery_session::DiscoverySession as BluetoothDiscoverySessionAndroid;
+#[cfg(all(target_os = "macos", feature = "bluetooth"))]
+use blurmac::BluetoothAdapter as BluetoothAdapterMac;
+#[cfg(all(target_os = "macos", feature = "bluetooth"))]
+use blurmac::BluetoothDevice as BluetoothDeviceMac;
+#[cfg(all(target_os = "macos", feature = "bluetooth"))]
+use blurmac::BluetoothDiscoverySession as BluetoothDiscoverySessionMac;
+#[cfg(feature = "bluetooth-test")]
+use blurmock::fake_adapter::FakeBluetoothAdapter;
+#[cfg(feature = "bluetooth-test")]
+use blurmock::fake_device::FakeBluetoothDevice;
+#[cfg(feature = "bluetooth-test")]
+use blurmock::fake_discovery_session::FakeBluetoothDiscoverySession;
+#[cfg(all(target_os = "linux", feature = "bluetooth"))]
+use blurz::bluetooth_adapter::BluetoothAdapter as BluetoothAdapterBluez;
+#[cfg(all(target_os = "linux", feature = "bluetooth"))]
+use blurz::bluetooth_device::BluetoothDevice as BluetoothDeviceBluez;
+#[cfg(all(target_os = "linux", feature = "bluetooth"))]
+use blurz::bluetooth_discovery_session::BluetoothDiscoverySession as BluetoothDiscoverySessionBluez;
+
+use super::bluetooth::{BluetoothDevice, BluetoothDiscoverySession};
+#[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+)))]
+use super::empty::BluetoothDevice as BluetoothDeviceEmpty;
+#[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+)))]
+use super::empty::BluetoothDiscoverySession as BluetoothDiscoverySessionEmpty;
+#[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+)))]
+use super::empty::EmptyAdapter as BluetoothAdapterEmpty;
+use super::macros::get_inner_and_call;
+#[cfg(feature = "bluetooth-test")]
+use super::macros::get_inner_and_call_test_func;
+
+#[derive(Clone, Debug)]
+pub enum BluetoothAdapter {
+ #[cfg(all(target_os = "linux", feature = "bluetooth"))]
+ Bluez(Arc<BluetoothAdapterBluez>),
+ #[cfg(all(target_os = "android", feature = "bluetooth"))]
+ Android(Arc<BluetoothAdapterAndroid>),
+ #[cfg(all(target_os = "macos", feature = "bluetooth"))]
+ Mac(Arc<BluetoothAdapterMac>),
+ #[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+ )))]
+ Empty(Arc<BluetoothAdapterEmpty>),
+ #[cfg(feature = "bluetooth-test")]
+ Mock(Arc<FakeBluetoothAdapter>),
+}
+
+impl BluetoothAdapter {
+ #[cfg(all(target_os = "linux", feature = "bluetooth"))]
+ pub fn new() -> Result<BluetoothAdapter, Box<dyn Error>> {
+ let bluez_adapter = BluetoothAdapterBluez::init()?;
+ Ok(Self::Bluez(Arc::new(bluez_adapter)))
+ }
+
+ #[cfg(all(target_os = "android", feature = "bluetooth"))]
+ pub fn new() -> Result<BluetoothAdapter, Box<dyn Error>> {
+ let blurdroid_adapter = BluetoothAdapterAndroid::get_adapter()?;
+ Ok(Self::Android(Arc::new(blurdroid_adapter)))
+ }
+
+ #[cfg(all(target_os = "macos", feature = "bluetooth"))]
+ pub fn new() -> Result<BluetoothAdapter, Box<dyn Error>> {
+ let mac_adapter = BluetoothAdapterMac::init()?;
+ Ok(Self::Mac(Arc::new(mac_adapter)))
+ }
+
+ #[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+ )))]
+ pub fn new() -> Result<BluetoothAdapter, Box<dyn Error>> {
+ let adapter = BluetoothAdapterEmpty::init()?;
+ Ok(Self::Empty(Arc::new(adapter)))
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn new_mock() -> Result<BluetoothAdapter, Box<dyn Error>> {
+ Ok(Self::Mock(FakeBluetoothAdapter::new_empty()))
+ }
+
+ pub fn get_id(&self) -> String {
+ get_inner_and_call!(self, BluetoothAdapter, get_id)
+ }
+
+ pub fn get_devices(&self) -> Result<Vec<BluetoothDevice>, Box<dyn Error>> {
+ match self {
+ #[cfg(all(target_os = "linux", feature = "bluetooth"))]
+ BluetoothAdapter::Bluez(inner) => {
+ let device_list = inner.get_device_list()?;
+ Ok(device_list
+ .into_iter()
+ .map(|device| {
+ BluetoothDevice::Bluez(BluetoothDeviceBluez::new_empty(
+ self.0.clone(),
+ device,
+ ))
+ })
+ .collect())
+ },
+ #[cfg(all(target_os = "android", feature = "bluetooth"))]
+ BluetoothAdapter::Android(inner) => {
+ let device_list = inner.get_device_list()?;
+ Ok(device_list
+ .into_iter()
+ .map(|device| {
+ BluetoothDevice::Android(BluetoothDeviceAndroid::new_empty(
+ self.0.clone(),
+ device,
+ ))
+ })
+ .collect())
+ },
+ #[cfg(all(target_os = "macos", feature = "bluetooth"))]
+ BluetoothAdapter::Mac(inner) => {
+ let device_list = inner.get_device_list()?;
+ Ok(device_list
+ .into_iter()
+ .map(|device| {
+ BluetoothDevice::Mac(Arc::new(BluetoothDeviceMac::new(
+ inner.clone(),
+ device,
+ )))
+ })
+ .collect())
+ },
+ #[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+ )))]
+ BluetoothAdapter::Empty(inner) => {
+ let device_list = inner.get_device_list()?;
+ Ok(device_list
+ .into_iter()
+ .map(|device| {
+ BluetoothDevice::Empty(Arc::new(BluetoothDeviceEmpty::new(device)))
+ })
+ .collect())
+ },
+ #[cfg(feature = "bluetooth-test")]
+ BluetoothAdapter::Mock(inner) => {
+ let device_list = inner.get_device_list()?;
+ Ok(device_list
+ .into_iter()
+ .map(|device| {
+ BluetoothDevice::Mock(FakeBluetoothDevice::new_empty(inner.clone(), device))
+ })
+ .collect())
+ },
+ }
+ }
+
+ pub fn get_device(&self, address: String) -> Result<Option<BluetoothDevice>, Box<dyn Error>> {
+ let devices = self.get_devices()?;
+ for device in devices {
+ if device.get_address()? == address {
+ return Ok(Some(device));
+ }
+ }
+ Ok(None)
+ }
+
+ pub fn create_mock_device(&self, _device: String) -> Result<BluetoothDevice, Box<dyn Error>> {
+ match self {
+ #[cfg(feature = "bluetooth-test")]
+ BluetoothAdapter::Mock(inner) => Ok(BluetoothDevice::Mock(
+ FakeBluetoothDevice::new_empty(inner.clone(), _device),
+ )),
+ _ => Err(Box::from(
+ "Error! Test functions are not supported on real devices!",
+ )),
+ }
+ }
+
+ pub fn create_discovery_session(&self) -> Result<BluetoothDiscoverySession, Box<dyn Error>> {
+ let discovery_session = match self {
+ #[cfg(all(target_os = "linux", feature = "bluetooth"))]
+ BluetoothAdapter::Bluez(inner) => {
+ BluetoothDiscoverySession::Bluez(Arc::new(
+ BluetoothDiscoverySessionBluez::create_session(inner.get_id())?,
+ ));
+ },
+ #[cfg(all(target_os = "android", feature = "bluetooth"))]
+ BluetoothAdapter::Android(inner) => BluetoothDiscoverySession::Android(Arc::new(
+ BluetoothDiscoverySessionAndroid::create_session(inner.clone())?,
+ )),
+ #[cfg(all(target_os = "macos", feature = "bluetooth"))]
+ BluetoothAdapter::Mac(_) => {
+ BluetoothDiscoverySession::Mac(Arc::new(BluetoothDiscoverySessionMac {}))
+ },
+ #[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+ )))]
+ BluetoothAdapter::Empty(_) => {
+ BluetoothDiscoverySession::Empty(Arc::new(BluetoothDiscoverySessionEmpty {}))
+ },
+ #[cfg(feature = "bluetooth-test")]
+ BluetoothAdapter::Mock(inner) => BluetoothDiscoverySession::Mock(Arc::new(
+ FakeBluetoothDiscoverySession::create_session(inner.clone())?,
+ )),
+ };
+ Ok(discovery_session)
+ }
+
+ pub fn get_address(&self) -> Result<String, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, get_address)
+ }
+
+ pub fn get_name(&self) -> Result<String, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, get_name)
+ }
+
+ pub fn get_alias(&self) -> Result<String, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, get_alias)
+ }
+
+ pub fn get_class(&self) -> Result<u32, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, get_class)
+ }
+
+ pub fn is_powered(&self) -> Result<bool, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, is_powered)
+ }
+
+ pub fn is_discoverable(&self) -> Result<bool, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, is_discoverable)
+ }
+
+ pub fn is_pairable(&self) -> Result<bool, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, is_pairable)
+ }
+
+ pub fn get_pairable_timeout(&self) -> Result<u32, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, get_pairable_timeout)
+ }
+
+ pub fn get_discoverable_timeout(&self) -> Result<u32, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, get_discoverable_timeout)
+ }
+
+ pub fn is_discovering(&self) -> Result<bool, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, is_discovering)
+ }
+
+ pub fn get_uuids(&self) -> Result<Vec<String>, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, get_uuids)
+ }
+
+ pub fn get_vendor_id_source(&self) -> Result<String, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, get_vendor_id_source)
+ }
+
+ pub fn get_vendor_id(&self) -> Result<u32, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, get_vendor_id)
+ }
+
+ pub fn get_product_id(&self) -> Result<u32, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, get_product_id)
+ }
+
+ pub fn get_device_id(&self) -> Result<u32, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, get_device_id)
+ }
+
+ pub fn get_modalias(&self) -> Result<(String, u32, u32, u32), Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, get_modalias)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_id(&self, id: String) -> Result<(), Box<dyn Error>> {
+ match self {
+ #[cfg(feature = "bluetooth-test")]
+ BluetoothAdapter::Mock(inner) => Ok(inner.set_id(id)),
+ _ => Err(Box::from(
+ "Error! Test functions are not supported on real devices!",
+ )),
+ }
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_address(&self, address: String) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_address, address)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_name(&self, name: String) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_name, name)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_alias(&self, alias: String) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_alias, alias)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_class(&self, class: u32) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_class, class)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_powered(&self, powered: bool) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_powered, powered)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn is_present(&self) -> Result<bool, Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, is_present)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_present(&self, present: bool) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_present, present)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_discoverable(&self, discoverable: bool) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_discoverable, discoverable)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_pairable(&self, pairable: bool) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_pairable, pairable)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_pairable_timeout(&self, timeout: u32) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_pairable_timeout, timeout)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_can_start_discovery(&self, can_start_discovery: bool) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(
+ self,
+ BluetoothAdapter,
+ set_can_start_discovery,
+ can_start_discovery
+ )
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_discoverable_timeout(&self, timeout: u32) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_discoverable_timeout, timeout)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_discovering(&self, discovering: bool) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_discovering, discovering)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_can_stop_discovery(&self, can_stop_discovery: bool) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(
+ self,
+ BluetoothAdapter,
+ set_can_stop_discovery,
+ can_stop_discovery
+ )
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_uuids(&self, uuids: Vec<String>) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_uuids, uuids)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_modalias(&self, modalias: String) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_modalias, modalias)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn get_ad_datas(&self) -> Result<Vec<String>, Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, get_ad_datas)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_ad_datas(&self, ad_datas: Vec<String>) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_ad_datas, ad_datas)
+ }
+}
diff --git a/components/bluetooth/bluetooth.rs b/components/bluetooth/bluetooth.rs
new file mode 100644
index 00000000000..71766160849
--- /dev/null
+++ b/components/bluetooth/bluetooth.rs
@@ -0,0 +1,753 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use std::collections::HashMap;
+use std::error::Error;
+use std::sync::Arc;
+
+#[cfg(all(target_os = "android", feature = "bluetooth"))]
+use blurdroid::bluetooth_device::Device as BluetoothDeviceAndroid;
+#[cfg(all(target_os = "android", feature = "bluetooth"))]
+use blurdroid::bluetooth_discovery_session::DiscoverySession as BluetoothDiscoverySessionAndroid;
+#[cfg(all(target_os = "android", feature = "bluetooth"))]
+use blurdroid::bluetooth_gatt_characteristic::Characteristic as BluetoothGATTCharacteristicAndroid;
+#[cfg(all(target_os = "android", feature = "bluetooth"))]
+use blurdroid::bluetooth_gatt_descriptor::Descriptor as BluetoothGATTDescriptorAndroid;
+#[cfg(all(target_os = "android", feature = "bluetooth"))]
+use blurdroid::bluetooth_gatt_service::Service as BluetoothGATTServiceAndroid;
+#[cfg(all(target_os = "macos", feature = "bluetooth"))]
+use blurmac::BluetoothDevice as BluetoothDeviceMac;
+#[cfg(all(target_os = "macos", feature = "bluetooth"))]
+use blurmac::BluetoothDiscoverySession as BluetoothDiscoverySessionMac;
+#[cfg(all(target_os = "macos", feature = "bluetooth"))]
+use blurmac::BluetoothGATTCharacteristic as BluetoothGATTCharacteristicMac;
+#[cfg(all(target_os = "macos", feature = "bluetooth"))]
+use blurmac::BluetoothGATTDescriptor as BluetoothGATTDescriptorMac;
+#[cfg(all(target_os = "macos", feature = "bluetooth"))]
+use blurmac::BluetoothGATTService as BluetoothGATTServiceMac;
+#[cfg(feature = "bluetooth-test")]
+use blurmock::fake_characteristic::FakeBluetoothGATTCharacteristic;
+#[cfg(feature = "bluetooth-test")]
+use blurmock::fake_descriptor::FakeBluetoothGATTDescriptor;
+#[cfg(feature = "bluetooth-test")]
+use blurmock::fake_device::FakeBluetoothDevice;
+#[cfg(feature = "bluetooth-test")]
+use blurmock::fake_discovery_session::FakeBluetoothDiscoverySession;
+#[cfg(feature = "bluetooth-test")]
+use blurmock::fake_service::FakeBluetoothGATTService;
+#[cfg(all(target_os = "linux", feature = "bluetooth"))]
+use blurz::bluetooth_device::BluetoothDevice as BluetoothDeviceBluez;
+#[cfg(all(target_os = "linux", feature = "bluetooth"))]
+use blurz::bluetooth_discovery_session::BluetoothDiscoverySession as BluetoothDiscoverySessionBluez;
+#[cfg(all(target_os = "linux", feature = "bluetooth"))]
+use blurz::bluetooth_gatt_characteristic::BluetoothGATTCharacteristic as BluetoothGATTCharacteristicBluez;
+#[cfg(all(target_os = "linux", feature = "bluetooth"))]
+use blurz::bluetooth_gatt_descriptor::BluetoothGATTDescriptor as BluetoothGATTDescriptorBluez;
+#[cfg(all(target_os = "linux", feature = "bluetooth"))]
+use blurz::bluetooth_gatt_service::BluetoothGATTService as BluetoothGATTServiceBluez;
+
+pub use super::adapter::BluetoothAdapter;
+#[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+)))]
+use super::empty::BluetoothDevice as BluetoothDeviceEmpty;
+#[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+)))]
+use super::empty::BluetoothDiscoverySession as BluetoothDiscoverySessionEmpty;
+#[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+)))]
+use super::empty::BluetoothGATTCharacteristic as BluetoothGATTCharacteristicEmpty;
+#[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+)))]
+use super::empty::BluetoothGATTDescriptor as BluetoothGATTDescriptorEmpty;
+#[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+)))]
+use super::empty::BluetoothGATTService as BluetoothGATTServiceEmpty;
+use super::macros::get_inner_and_call;
+#[cfg(feature = "bluetooth-test")]
+use super::macros::get_inner_and_call_test_func;
+
+#[cfg(feature = "bluetooth-test")]
+const NOT_SUPPORTED_ON_MOCK_ERROR: &'static str =
+ "Error! The first parameter must be a mock structure!";
+
+#[derive(Debug)]
+pub enum BluetoothDiscoverySession {
+ #[cfg(all(target_os = "linux", feature = "bluetooth"))]
+ Bluez(Arc<BluetoothDiscoverySessionBluez>),
+ #[cfg(all(target_os = "android", feature = "bluetooth"))]
+ Android(Arc<BluetoothDiscoverySessionAndroid>),
+ #[cfg(all(target_os = "macos", feature = "bluetooth"))]
+ Mac(Arc<BluetoothDiscoverySessionMac>),
+ #[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+ )))]
+ Empty(Arc<BluetoothDiscoverySessionEmpty>),
+ #[cfg(feature = "bluetooth-test")]
+ Mock(Arc<FakeBluetoothDiscoverySession>),
+}
+
+#[derive(Clone, Debug)]
+pub enum BluetoothDevice {
+ #[cfg(all(target_os = "linux", feature = "bluetooth"))]
+ Bluez(Arc<BluetoothDeviceBluez>),
+ #[cfg(all(target_os = "android", feature = "bluetooth"))]
+ Android(Arc<BluetoothDeviceAndroid>),
+ #[cfg(all(target_os = "macos", feature = "bluetooth"))]
+ Mac(Arc<BluetoothDeviceMac>),
+ #[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+ )))]
+ Empty(Arc<BluetoothDeviceEmpty>),
+ #[cfg(feature = "bluetooth-test")]
+ Mock(Arc<FakeBluetoothDevice>),
+}
+
+#[derive(Clone, Debug)]
+pub enum BluetoothGATTService {
+ #[cfg(all(target_os = "linux", feature = "bluetooth"))]
+ Bluez(Arc<BluetoothGATTServiceBluez>),
+ #[cfg(all(target_os = "android", feature = "bluetooth"))]
+ Android(Arc<BluetoothGATTServiceAndroid>),
+ #[cfg(all(target_os = "macos", feature = "bluetooth"))]
+ Mac(Arc<BluetoothGATTServiceMac>),
+ #[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+ )))]
+ Empty(Arc<BluetoothGATTServiceEmpty>),
+ #[cfg(feature = "bluetooth-test")]
+ Mock(Arc<FakeBluetoothGATTService>),
+}
+
+#[derive(Clone, Debug)]
+pub enum BluetoothGATTCharacteristic {
+ #[cfg(all(target_os = "linux", feature = "bluetooth"))]
+ Bluez(Arc<BluetoothGATTCharacteristicBluez>),
+ #[cfg(all(target_os = "android", feature = "bluetooth"))]
+ Android(Arc<BluetoothGATTCharacteristicAndroid>),
+ #[cfg(all(target_os = "macos", feature = "bluetooth"))]
+ Mac(Arc<BluetoothGATTCharacteristicMac>),
+ #[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+ )))]
+ Empty(Arc<BluetoothGATTCharacteristicEmpty>),
+ #[cfg(feature = "bluetooth-test")]
+ Mock(Arc<FakeBluetoothGATTCharacteristic>),
+}
+
+#[derive(Clone, Debug)]
+pub enum BluetoothGATTDescriptor {
+ #[cfg(all(target_os = "linux", feature = "bluetooth"))]
+ Bluez(Arc<BluetoothGATTDescriptorBluez>),
+ #[cfg(all(target_os = "android", feature = "bluetooth"))]
+ Android(Arc<BluetoothGATTDescriptorAndroid>),
+ #[cfg(all(target_os = "macos", feature = "bluetooth"))]
+ Mac(Arc<BluetoothGATTDescriptorMac>),
+ #[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+ )))]
+ Empty(Arc<BluetoothGATTDescriptorEmpty>),
+ #[cfg(feature = "bluetooth-test")]
+ Mock(Arc<FakeBluetoothGATTDescriptor>),
+}
+
+impl BluetoothDiscoverySession {
+ pub fn start_discovery(&self) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDiscoverySession, start_discovery)
+ }
+
+ pub fn stop_discovery(&self) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDiscoverySession, stop_discovery)
+ }
+}
+
+impl BluetoothDevice {
+ pub fn get_id(&self) -> String {
+ get_inner_and_call!(self, BluetoothDevice, get_id)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_id(&self, id: String) {
+ match self {
+ &BluetoothDevice::Mock(ref fake_adapter) => fake_adapter.set_id(id),
+ _ => (),
+ }
+ }
+
+ pub fn get_address(&self) -> Result<String, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, get_address)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_address(&self, address: String) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothDevice, set_address, address)
+ }
+
+ pub fn get_name(&self) -> Result<String, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, get_name)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_name(&self, name: Option<String>) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothDevice, set_name, name)
+ }
+
+ pub fn get_icon(&self) -> Result<String, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, get_icon)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_icon(&self, icon: String) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothDevice, set_icon, icon)
+ }
+
+ pub fn get_class(&self) -> Result<u32, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, get_class)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_class(&self, class: u32) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothDevice, set_class, class)
+ }
+
+ pub fn get_appearance(&self) -> Result<u16, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, get_appearance)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_appearance(&self, appearance: u16) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothDevice, set_appearance, Some(appearance))
+ }
+
+ pub fn get_uuids(&self) -> Result<Vec<String>, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, get_uuids)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_uuids(&self, uuids: Vec<String>) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothDevice, set_uuids, uuids)
+ }
+
+ pub fn is_paired(&self) -> Result<bool, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, is_paired)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_paired(&self, paired: bool) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothDevice, set_paired, paired)
+ }
+
+ pub fn is_connected(&self) -> Result<bool, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, is_connected)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_connected(&self, connected: bool) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothDevice, set_connected, connected)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn is_connectable(&self) -> Result<bool, Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothDevice, is_connectable)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_connectable(&self, connectable: bool) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothDevice, set_connectable, connectable)
+ }
+
+ pub fn is_trusted(&self) -> Result<bool, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, is_trusted)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_trusted(&self, trusted: bool) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothDevice, set_trusted, trusted)
+ }
+
+ pub fn is_blocked(&self) -> Result<bool, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, is_blocked)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_blocked(&self, blocked: bool) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothDevice, set_blocked, blocked)
+ }
+
+ pub fn get_alias(&self) -> Result<String, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, get_alias)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_alias(&self, alias: String) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothDevice, set_alias, alias)
+ }
+
+ pub fn is_legacy_pairing(&self) -> Result<bool, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, is_legacy_pairing)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_legacy_pairing(&self, legacy_pairing: bool) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothDevice, set_legacy_pairing, legacy_pairing)
+ }
+
+ pub fn get_vendor_id_source(&self) -> Result<String, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, get_vendor_id_source)
+ }
+
+ pub fn get_vendor_id(&self) -> Result<u32, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, get_vendor_id)
+ }
+
+ pub fn get_product_id(&self) -> Result<u32, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, get_product_id)
+ }
+
+ pub fn get_device_id(&self) -> Result<u32, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, get_device_id)
+ }
+
+ pub fn get_modalias(&self) -> Result<(String, u32, u32, u32), Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, get_modalias)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_modalias(&self, modalias: String) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothDevice, set_modalias, modalias)
+ }
+
+ pub fn get_rssi(&self) -> Result<i16, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, get_rssi)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_rssi(&self, rssi: i16) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothDevice, set_rssi, Some(rssi))
+ }
+
+ pub fn get_tx_power(&self) -> Result<i16, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, get_tx_power)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_tx_power(&self, tx_power: i16) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothDevice, set_tx_power, Some(tx_power))
+ }
+
+ pub fn get_manufacturer_data(&self) -> Result<HashMap<u16, Vec<u8>>, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, get_manufacturer_data)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_manufacturer_data(
+ &self,
+ manufacturer_data: HashMap<u16, Vec<u8>>,
+ ) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(
+ self,
+ BluetoothDevice,
+ set_manufacturer_data,
+ Some(manufacturer_data)
+ )
+ }
+
+ pub fn get_service_data(&self) -> Result<HashMap<String, Vec<u8>>, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, get_service_data)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_service_data(
+ &self,
+ service_data: HashMap<String, Vec<u8>>,
+ ) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothDevice, set_service_data, Some(service_data))
+ }
+
+ pub fn get_gatt_services(&self) -> Result<Vec<BluetoothGATTService>, Box<dyn Error>> {
+ let services = get_inner_and_call!(self, BluetoothDevice, get_gatt_services)?;
+ Ok(services
+ .into_iter()
+ .map(|service| BluetoothGATTService::create_service(self.clone(), service))
+ .collect())
+ }
+
+ pub fn connect(&self) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, connect)
+ }
+
+ pub fn disconnect(&self) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, disconnect)
+ }
+
+ pub fn connect_profile(&self, uuid: String) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, connect_profile, uuid)
+ }
+
+ pub fn disconnect_profile(&self, uuid: String) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, disconnect_profile, uuid)
+ }
+
+ pub fn pair(&self) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, pair)
+ }
+
+ pub fn cancel_pairing(&self) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothDevice, cancel_pairing)
+ }
+}
+
+impl BluetoothGATTService {
+ fn create_service(device: BluetoothDevice, service: String) -> BluetoothGATTService {
+ match device {
+ #[cfg(all(target_os = "linux", feature = "bluetooth"))]
+ BluetoothDevice::Bluez(_bluez_device) => {
+ BluetoothGATTService::Bluez(Arc::new(BluetoothGATTServiceBluez::new(service)))
+ },
+ #[cfg(all(target_os = "android", feature = "bluetooth"))]
+ BluetoothDevice::Android(android_device) => BluetoothGATTService::Android(Arc::new(
+ BluetoothGATTServiceAndroid::new(android_device, service),
+ )),
+ #[cfg(all(target_os = "macos", feature = "bluetooth"))]
+ BluetoothDevice::Mac(mac_device) => BluetoothGATTService::Mac(Arc::new(
+ BluetoothGATTServiceMac::new(mac_device, service),
+ )),
+ #[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+ )))]
+ BluetoothDevice::Empty(_device) => {
+ BluetoothGATTService::Empty(Arc::new(BluetoothGATTServiceEmpty::new(service)))
+ },
+ #[cfg(feature = "bluetooth-test")]
+ BluetoothDevice::Mock(fake_device) => BluetoothGATTService::Mock(
+ FakeBluetoothGATTService::new_empty(fake_device, service),
+ ),
+ }
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn create_mock_service(
+ device: BluetoothDevice,
+ service: String,
+ ) -> Result<BluetoothGATTService, Box<dyn Error>> {
+ match device {
+ BluetoothDevice::Mock(fake_device) => Ok(BluetoothGATTService::Mock(
+ FakeBluetoothGATTService::new_empty(fake_device, service),
+ )),
+ _ => Err(Box::from(
+ "Error! The first parameter must be a mock structure!",
+ )),
+ }
+ }
+
+ pub fn get_id(&self) -> String {
+ get_inner_and_call!(self, BluetoothGATTService, get_id)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_id(&self, id: String) {
+ match self {
+ &BluetoothGATTService::Mock(ref fake_service) => fake_service.set_id(id),
+ _ => (),
+ }
+ }
+
+ pub fn get_uuid(&self) -> Result<String, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothGATTService, get_uuid)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_uuid(&self, uuid: String) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothGATTService, set_uuid, uuid)
+ }
+
+ pub fn is_primary(&self) -> Result<bool, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothGATTService, is_primary)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_primary(&self, primary: bool) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothGATTService, set_is_primary, primary)
+ }
+
+ pub fn get_includes(
+ &self,
+ device: BluetoothDevice,
+ ) -> Result<Vec<BluetoothGATTService>, Box<dyn Error>> {
+ let services = get_inner_and_call!(self, BluetoothGATTService, get_includes)?;
+ Ok(services
+ .into_iter()
+ .map(|service| BluetoothGATTService::create_service(device.clone(), service))
+ .collect())
+ }
+
+ pub fn get_gatt_characteristics(
+ &self,
+ ) -> Result<Vec<BluetoothGATTCharacteristic>, Box<dyn Error>> {
+ let characteristics =
+ get_inner_and_call!(self, BluetoothGATTService, get_gatt_characteristics)?;
+ Ok(characteristics
+ .into_iter()
+ .map(|characteristic| {
+ BluetoothGATTCharacteristic::create_characteristic(self.clone(), characteristic)
+ })
+ .collect())
+ }
+}
+
+impl BluetoothGATTCharacteristic {
+ fn create_characteristic(
+ service: BluetoothGATTService,
+ characteristic: String,
+ ) -> BluetoothGATTCharacteristic {
+ match service {
+ #[cfg(all(target_os = "linux", feature = "bluetooth"))]
+ BluetoothGATTService::Bluez(_bluez_service) => BluetoothGATTCharacteristic::Bluez(
+ Arc::new(BluetoothGATTCharacteristicBluez::new(characteristic)),
+ ),
+ #[cfg(all(target_os = "android", feature = "bluetooth"))]
+ BluetoothGATTService::Android(android_service) => {
+ BluetoothGATTCharacteristic::Android(Arc::new(
+ BluetoothGATTCharacteristicAndroid::new(android_service, characteristic),
+ ))
+ },
+ #[cfg(all(target_os = "macos", feature = "bluetooth"))]
+ BluetoothGATTService::Mac(mac_service) => BluetoothGATTCharacteristic::Mac(Arc::new(
+ BluetoothGATTCharacteristicMac::new(mac_service, characteristic),
+ )),
+ #[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+ )))]
+ BluetoothGATTService::Empty(_service) => BluetoothGATTCharacteristic::Empty(Arc::new(
+ BluetoothGATTCharacteristicEmpty::new(characteristic),
+ )),
+ #[cfg(feature = "bluetooth-test")]
+ BluetoothGATTService::Mock(fake_service) => BluetoothGATTCharacteristic::Mock(
+ FakeBluetoothGATTCharacteristic::new_empty(fake_service, characteristic),
+ ),
+ }
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn create_mock_characteristic(
+ service: BluetoothGATTService,
+ characteristic: String,
+ ) -> Result<BluetoothGATTCharacteristic, Box<dyn Error>> {
+ match service {
+ BluetoothGATTService::Mock(fake_service) => Ok(BluetoothGATTCharacteristic::Mock(
+ FakeBluetoothGATTCharacteristic::new_empty(fake_service, characteristic),
+ )),
+ _ => Err(Box::from(
+ "Error! The first parameter must be a mock structure!",
+ )),
+ }
+ }
+
+ pub fn get_id(&self) -> String {
+ get_inner_and_call!(self, BluetoothGATTCharacteristic, get_id)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_id(&self, id: String) {
+ match self {
+ &BluetoothGATTCharacteristic::Mock(ref fake_characteristic) => {
+ fake_characteristic.set_id(id)
+ },
+ _ => (),
+ }
+ }
+
+ pub fn get_uuid(&self) -> Result<String, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothGATTCharacteristic, get_uuid)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_uuid(&self, uuid: String) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothGATTCharacteristic, set_uuid, uuid)
+ }
+
+ pub fn get_value(&self) -> Result<Vec<u8>, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothGATTCharacteristic, get_value)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_value(&self, value: Vec<u8>) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothGATTCharacteristic, set_value, Some(value))
+ }
+
+ pub fn is_notifying(&self) -> Result<bool, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothGATTCharacteristic, is_notifying)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_notifying(&self, notifying: bool) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothGATTCharacteristic, set_notifying, notifying)
+ }
+
+ pub fn get_flags(&self) -> Result<Vec<String>, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothGATTCharacteristic, get_flags)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_flags(&self, flags: Vec<String>) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothGATTCharacteristic, set_flags, flags)
+ }
+
+ pub fn get_gatt_descriptors(&self) -> Result<Vec<BluetoothGATTDescriptor>, Box<dyn Error>> {
+ let descriptors =
+ get_inner_and_call!(self, BluetoothGATTCharacteristic, get_gatt_descriptors)?;
+ Ok(descriptors
+ .into_iter()
+ .map(|descriptor| BluetoothGATTDescriptor::create_descriptor(self.clone(), descriptor))
+ .collect())
+ }
+
+ pub fn read_value(&self) -> Result<Vec<u8>, Box<dyn Error>> {
+ get_inner_and_call!(@with_bluez_offset, self, BluetoothGATTCharacteristic, read_value)
+ }
+
+ pub fn write_value(&self, values: Vec<u8>) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call!(@with_bluez_offset, self, BluetoothGATTCharacteristic, write_value, values)
+ }
+
+ pub fn start_notify(&self) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothGATTCharacteristic, start_notify)
+ }
+
+ pub fn stop_notify(&self) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothGATTCharacteristic, stop_notify)
+ }
+}
+
+impl BluetoothGATTDescriptor {
+ fn create_descriptor(
+ characteristic: BluetoothGATTCharacteristic,
+ descriptor: String,
+ ) -> BluetoothGATTDescriptor {
+ match characteristic {
+ #[cfg(all(target_os = "linux", feature = "bluetooth"))]
+ BluetoothGATTCharacteristic::Bluez(_bluez_characteristic) => {
+ BluetoothGATTDescriptor::Bluez(Arc::new(BluetoothGATTDescriptorBluez::new(
+ descriptor,
+ )))
+ },
+ #[cfg(all(target_os = "android", feature = "bluetooth"))]
+ BluetoothGATTCharacteristic::Android(android_characteristic) => {
+ BluetoothGATTDescriptor::Android(Arc::new(BluetoothGATTDescriptorAndroid::new(
+ android_characteristic,
+ descriptor,
+ )))
+ },
+ #[cfg(all(target_os = "macos", feature = "bluetooth"))]
+ BluetoothGATTCharacteristic::Mac(_mac_characteristic) => {
+ BluetoothGATTDescriptor::Mac(Arc::new(BluetoothGATTDescriptorMac::new(descriptor)))
+ },
+ #[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+ )))]
+ BluetoothGATTCharacteristic::Empty(_characteristic) => BluetoothGATTDescriptor::Empty(
+ Arc::new(BluetoothGATTDescriptorEmpty::new(descriptor)),
+ ),
+ #[cfg(feature = "bluetooth-test")]
+ BluetoothGATTCharacteristic::Mock(fake_characteristic) => {
+ BluetoothGATTDescriptor::Mock(FakeBluetoothGATTDescriptor::new_empty(
+ fake_characteristic,
+ descriptor,
+ ))
+ },
+ }
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn create_mock_descriptor(
+ characteristic: BluetoothGATTCharacteristic,
+ descriptor: String,
+ ) -> Result<BluetoothGATTDescriptor, Box<dyn Error>> {
+ match characteristic {
+ BluetoothGATTCharacteristic::Mock(fake_characteristic) => {
+ Ok(BluetoothGATTDescriptor::Mock(
+ FakeBluetoothGATTDescriptor::new_empty(fake_characteristic, descriptor),
+ ))
+ },
+ _ => Err(Box::from(NOT_SUPPORTED_ON_MOCK_ERROR)),
+ }
+ }
+
+ pub fn get_id(&self) -> String {
+ get_inner_and_call!(self, BluetoothGATTDescriptor, get_id)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_id(&self, id: String) {
+ match self {
+ &BluetoothGATTDescriptor::Mock(ref fake_descriptor) => fake_descriptor.set_id(id),
+ _ => (),
+ }
+ }
+
+ pub fn get_uuid(&self) -> Result<String, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothGATTDescriptor, get_uuid)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_uuid(&self, uuid: String) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothGATTDescriptor, set_uuid, uuid)
+ }
+
+ pub fn get_value(&self) -> Result<Vec<u8>, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothGATTDescriptor, get_value)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_value(&self, value: Vec<u8>) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothGATTDescriptor, set_value, Some(value))
+ }
+
+ pub fn get_flags(&self) -> Result<Vec<String>, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothGATTDescriptor, get_flags)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_flags(&self, flags: Vec<String>) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothGATTDescriptor, set_flags, flags)
+ }
+
+ pub fn read_value(&self) -> Result<Vec<u8>, Box<dyn Error>> {
+ get_inner_and_call!(@with_bluez_offset, self, BluetoothGATTDescriptor, read_value)
+ }
+
+ pub fn write_value(&self, values: Vec<u8>) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call!(@with_bluez_offset, self, BluetoothGATTDescriptor, write_value, values)
+ }
+}
diff --git a/components/bluetooth/empty.rs b/components/bluetooth/empty.rs
new file mode 100644
index 00000000000..27773a10a47
--- /dev/null
+++ b/components/bluetooth/empty.rs
@@ -0,0 +1,377 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use std::collections::HashMap;
+use std::error::Error;
+use std::sync::Arc;
+
+const NOT_SUPPORTED_ERROR: &'static str = "Error! Not supported platform!";
+
+#[derive(Clone, Debug)]
+pub struct EmptyAdapter {}
+
+impl EmptyAdapter {
+ pub fn init() -> Result<EmptyAdapter, Box<dyn Error>> {
+ Ok(EmptyAdapter::new())
+ }
+
+ fn new() -> EmptyAdapter {
+ EmptyAdapter {}
+ }
+
+ pub fn get_id(&self) -> String {
+ String::new()
+ }
+
+ pub fn get_device_list(&self) -> Result<Vec<String>, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_address(&self) -> Result<String, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_name(&self) -> Result<String, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_alias(&self) -> Result<String, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn set_alias(&self, _value: String) -> Result<(), Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_class(&self) -> Result<u32, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn is_powered(&self) -> Result<bool, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn set_powered(&self, _value: bool) -> Result<(), Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn is_discoverable(&self) -> Result<bool, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn set_discoverable(&self, _value: bool) -> Result<(), Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn is_pairable(&self) -> Result<bool, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn set_pairable(&self, _value: bool) -> Result<(), Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_pairable_timeout(&self) -> Result<u32, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn set_pairable_timeout(&self, _value: u32) -> Result<(), Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_discoverable_timeout(&self) -> Result<u32, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn set_discoverable_timeout(&self, _value: u32) -> Result<(), Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn is_discovering(&self) -> Result<bool, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_uuids(&self) -> Result<Vec<String>, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_vendor_id_source(&self) -> Result<String, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_vendor_id(&self) -> Result<u32, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_product_id(&self) -> Result<u32, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_device_id(&self) -> Result<u32, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_modalias(&self) -> Result<(String, u32, u32, u32), Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct BluetoothDiscoverySession {}
+
+impl BluetoothDiscoverySession {
+ pub fn create_session(
+ _adapter: Arc<EmptyAdapter>,
+ ) -> Result<BluetoothDiscoverySession, Box<dyn Error>> {
+ Ok(BluetoothDiscoverySession {})
+ }
+
+ pub fn start_discovery(&self) -> Result<(), Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn stop_discovery(&self) -> Result<(), Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct BluetoothDevice {}
+
+impl BluetoothDevice {
+ pub fn new(_device: String) -> BluetoothDevice {
+ BluetoothDevice {}
+ }
+
+ pub fn get_id(&self) -> String {
+ String::new()
+ }
+
+ pub fn get_address(&self) -> Result<String, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_name(&self) -> Result<String, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_icon(&self) -> Result<String, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_class(&self) -> Result<u32, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_appearance(&self) -> Result<u16, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_uuids(&self) -> Result<Vec<String>, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn is_paired(&self) -> Result<bool, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn is_connected(&self) -> Result<bool, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn is_trusted(&self) -> Result<bool, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn is_blocked(&self) -> Result<bool, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_alias(&self) -> Result<String, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn set_alias(&self, _value: String) -> Result<(), Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn is_legacy_pairing(&self) -> Result<bool, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_vendor_id_source(&self) -> Result<String, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_vendor_id(&self) -> Result<u32, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_product_id(&self) -> Result<u32, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_device_id(&self) -> Result<u32, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_modalias(&self) -> Result<(String, u32, u32, u32), Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_rssi(&self) -> Result<i16, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_tx_power(&self) -> Result<i16, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_manufacturer_data(&self) -> Result<HashMap<u16, Vec<u8>>, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_service_data(&self) -> Result<HashMap<String, Vec<u8>>, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_gatt_services(&self) -> Result<Vec<String>, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn connect(&self) -> Result<(), Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn disconnect(&self) -> Result<(), Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn connect_profile(&self, _uuid: String) -> Result<(), Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn disconnect_profile(&self, _uuid: String) -> Result<(), Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn pair(&self) -> Result<(), Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn cancel_pairing(&self) -> Result<(), Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct BluetoothGATTService {}
+
+impl BluetoothGATTService {
+ pub fn new(_service: String) -> BluetoothGATTService {
+ BluetoothGATTService {}
+ }
+
+ pub fn get_id(&self) -> String {
+ String::new()
+ }
+
+ pub fn get_uuid(&self) -> Result<String, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn is_primary(&self) -> Result<bool, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_includes(&self) -> Result<Vec<String>, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_gatt_characteristics(&self) -> Result<Vec<String>, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct BluetoothGATTCharacteristic {}
+
+impl BluetoothGATTCharacteristic {
+ pub fn new(_characteristic: String) -> BluetoothGATTCharacteristic {
+ BluetoothGATTCharacteristic {}
+ }
+
+ pub fn get_id(&self) -> String {
+ String::new()
+ }
+
+ pub fn get_uuid(&self) -> Result<String, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_value(&self) -> Result<Vec<u8>, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn is_notifying(&self) -> Result<bool, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_flags(&self) -> Result<Vec<String>, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_gatt_descriptors(&self) -> Result<Vec<String>, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn read_value(&self) -> Result<Vec<u8>, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn write_value(&self, _values: Vec<u8>) -> Result<(), Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn start_notify(&self) -> Result<(), Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn stop_notify(&self) -> Result<(), Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct BluetoothGATTDescriptor {}
+
+impl BluetoothGATTDescriptor {
+ pub fn new(_descriptor: String) -> BluetoothGATTDescriptor {
+ BluetoothGATTDescriptor {}
+ }
+
+ pub fn get_id(&self) -> String {
+ String::new()
+ }
+
+ pub fn get_uuid(&self) -> Result<String, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_value(&self) -> Result<Vec<u8>, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_flags(&self) -> Result<Vec<String>, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn read_value(&self) -> Result<Vec<u8>, Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn write_value(&self, _values: Vec<u8>) -> Result<(), Box<dyn Error>> {
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+}
diff --git a/components/bluetooth/lib.rs b/components/bluetooth/lib.rs
index e6d7a533a53..f2a7bc4de70 100644
--- a/components/bluetooth/lib.rs
+++ b/components/bluetooth/lib.rs
@@ -2,6 +2,15 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+pub mod adapter;
+pub mod bluetooth;
+#[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+)))]
+mod empty;
+mod macros;
pub mod test;
use std::borrow::ToOwned;
@@ -20,16 +29,17 @@ use bluetooth_traits::{
BluetoothRequest, BluetoothResponse, BluetoothResponseResult, BluetoothResult,
BluetoothServiceMsg, GATTType,
};
-use device::bluetooth::{
- BluetoothAdapter, BluetoothDevice, BluetoothGATTCharacteristic, BluetoothGATTDescriptor,
- BluetoothGATTService,
-};
use embedder_traits::{EmbedderMsg, EmbedderProxy};
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use log::warn;
use servo_config::pref;
use servo_rand::{self, Rng};
+use crate::bluetooth::{
+ BluetoothAdapter, BluetoothDevice, BluetoothGATTCharacteristic, BluetoothGATTDescriptor,
+ BluetoothGATTService,
+};
+
// A transaction not completed within 30 seconds shall time out. Such a transaction shall be considered to have failed.
// https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=286439 (Vol. 3, page 480)
const MAXIMUM_TRANSACTION_TIME: u8 = 30;
@@ -67,9 +77,9 @@ impl BluetoothThreadFactory for IpcSender<BluetoothRequest> {
fn new(embedder_proxy: EmbedderProxy) -> IpcSender<BluetoothRequest> {
let (sender, receiver) = ipc::channel().unwrap();
let adapter = if pref!(dom.bluetooth.enabled) {
- BluetoothAdapter::init()
+ BluetoothAdapter::new()
} else {
- BluetoothAdapter::init_mock()
+ BluetoothAdapter::new_mock()
}
.ok();
thread::Builder::new()
@@ -287,7 +297,7 @@ impl BluetoothManager {
self.cached_characteristics.clear();
self.cached_descriptors.clear();
self.allowed_services.clear();
- self.adapter = BluetoothAdapter::init_mock().ok();
+ self.adapter = BluetoothAdapter::new_mock().ok();
match test::test(self, data_set_name) {
Ok(_) => return Ok(()),
Err(error) => Err(BluetoothError::Type(error.to_string())),
@@ -324,7 +334,7 @@ impl BluetoothManager {
.as_ref()
.map_or(false, |a| a.get_address().is_ok());
if !adapter_valid {
- self.adapter = BluetoothAdapter::init().ok();
+ self.adapter = BluetoothAdapter::new().ok();
}
let adapter = self.adapter.as_ref()?;
diff --git a/components/bluetooth/macros.rs b/components/bluetooth/macros.rs
new file mode 100644
index 00000000000..fd76d1eb549
--- /dev/null
+++ b/components/bluetooth/macros.rs
@@ -0,0 +1,98 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+macro_rules! get_inner_and_call(
+ ($enum_value: expr, $enum_type: ident, $function_name: ident) => {
+ match $enum_value {
+ #[cfg(all(target_os = "linux", feature = "bluetooth"))]
+ &$enum_type::Bluez(ref bluez) => bluez.$function_name(),
+ #[cfg(all(target_os = "android", feature = "bluetooth"))]
+ &$enum_type::Android(ref android) => android.$function_name(),
+ #[cfg(all(target_os = "macos", feature = "bluetooth"))]
+ &$enum_type::Mac(ref mac) => mac.$function_name(),
+ #[cfg(not(any(all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth"))))]
+ &$enum_type::Empty(ref empty) => empty.$function_name(),
+ #[cfg(feature = "bluetooth-test")]
+ &$enum_type::Mock(ref fake) => fake.$function_name(),
+ }
+ };
+
+ (@with_bluez_offset, $enum_value: expr, $enum_type: ident, $function_name: ident) => {
+ match $enum_value {
+ #[cfg(all(target_os = "linux", feature = "bluetooth"))]
+ &$enum_type::Bluez(ref bluez) => bluez.$function_name(None),
+ #[cfg(all(target_os = "android", feature = "bluetooth"))]
+ &$enum_type::Android(ref android) => android.$function_name(),
+ #[cfg(all(target_os = "macos", feature = "bluetooth"))]
+ &$enum_type::Mac(ref mac) => mac.$function_name(),
+ #[cfg(not(any(all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth"))))]
+ &$enum_type::Empty(ref empty) => empty.$function_name(),
+ #[cfg(feature = "bluetooth-test")]
+ &$enum_type::Mock(ref fake) => fake.$function_name(),
+ }
+ };
+
+ ($enum_value: expr, $enum_type: ident, $function_name: ident, $value: expr) => {
+ match $enum_value {
+ #[cfg(all(target_os = "linux", feature = "bluetooth"))]
+ &$enum_type::Bluez(ref bluez) => bluez.$function_name($value),
+ #[cfg(all(target_os = "android", feature = "bluetooth"))]
+ &$enum_type::Android(ref android) => android.$function_name($value),
+ #[cfg(all(target_os = "macos", feature = "bluetooth"))]
+ &$enum_type::Mac(ref mac) => mac.$function_name($value),
+ #[cfg(not(any(all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth"))))]
+ &$enum_type::Empty(ref empty) => empty.$function_name($value),
+ #[cfg(feature = "bluetooth-test")]
+ &$enum_type::Mock(ref fake) => fake.$function_name($value),
+ }
+ };
+
+ (@with_bluez_offset, $enum_value: expr, $enum_type: ident, $function_name: ident, $value: expr) => {
+ match $enum_value {
+ #[cfg(all(target_os = "linux", feature = "bluetooth"))]
+ &$enum_type::Bluez(ref bluez) => bluez.$function_name($value, None),
+ #[cfg(all(target_os = "android", feature = "bluetooth"))]
+ &$enum_type::Android(ref android) => android.$function_name($value),
+ #[cfg(all(target_os = "macos", feature = "bluetooth"))]
+ &$enum_type::Mac(ref mac) => mac.$function_name($value),
+ #[cfg(not(any(all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth"))))]
+ &$enum_type::Empty(ref empty) => empty.$function_name($value),
+ #[cfg(feature = "bluetooth-test")]
+ &$enum_type::Mock(ref fake) => fake.$function_name($value),
+ }
+ };
+);
+
+#[cfg(feature = "bluetooth-test")]
+macro_rules! get_inner_and_call_test_func {
+ ($enum_value: expr, $enum_type: ident, $function_name: ident, $value: expr) => {
+ match $enum_value {
+ &$enum_type::Mock(ref fake) => fake.$function_name($value),
+ _ => Err(Box::from(
+ "Error! Test functions are not supported on real devices!",
+ )),
+ }
+ };
+
+ ($enum_value: expr, $enum_type: ident, $function_name: ident) => {
+ match $enum_value {
+ &$enum_type::Mock(ref fake) => fake.$function_name(),
+ _ => Err(Box::from(
+ "Error! Test functions are not supported on real devices!",
+ )),
+ }
+ };
+}
+
+pub(crate) use get_inner_and_call;
+#[cfg(feature = "bluetooth-test")]
+pub(crate) use get_inner_and_call_test_func;
diff --git a/components/bluetooth/test.rs b/components/bluetooth/test.rs
index 25e4d9cbb7d..bf3b19b82cc 100644
--- a/components/bluetooth/test.rs
+++ b/components/bluetooth/test.rs
@@ -8,12 +8,12 @@ use std::collections::{HashMap, HashSet};
use std::error::Error;
use std::string::String;
-use device::bluetooth::{
+use uuid::Uuid;
+
+use crate::bluetooth::{
BluetoothAdapter, BluetoothDevice, BluetoothGATTCharacteristic, BluetoothGATTDescriptor,
BluetoothGATTService,
};
-use uuid::Uuid;
-
use crate::BluetoothManager;
thread_local!(pub static CACHED_IDS: RefCell<HashSet<Uuid>> = RefCell::new(HashSet::new()));
@@ -152,7 +152,7 @@ fn create_device(
name: String,
address: String,
) -> Result<BluetoothDevice, Box<dyn Error>> {
- let device = BluetoothDevice::create_mock_device(adapter.clone(), generate_id().to_string())?;
+ let device = adapter.create_mock_device(generate_id().to_string())?;
device.set_name(Some(name))?;
device.set_address(address)?;
device.set_connectable(true)?;