mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
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
This commit is contained in:
parent
fddc4a430f
commit
6a804cd775
23 changed files with 3880 additions and 27 deletions
|
@ -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 }
|
||||
|
|
55
components/bluetooth/README.md
Normal file
55
components/bluetooth/README.md
Normal file
|
@ -0,0 +1,55 @@
|
|||
# Bluetooth Rust lib using macOS CoreBluetooth
|
||||
|
||||
[](https://travis-ci.org/akosthekiss/blurmac)
|
||||
[](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).
|
408
components/bluetooth/adapter.rs
Normal file
408
components/bluetooth/adapter.rs
Normal file
|
@ -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)
|
||||
}
|
||||
}
|
753
components/bluetooth/bluetooth.rs
Normal file
753
components/bluetooth/bluetooth.rs
Normal file
|
@ -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)
|
||||
}
|
||||
}
|
377
components/bluetooth/empty.rs
Normal file
377
components/bluetooth/empty.rs
Normal file
|
@ -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))
|
||||
}
|
||||
}
|
|
@ -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()?;
|
||||
|
|
98
components/bluetooth/macros.rs
Normal file
98
components/bluetooth/macros.rs
Normal file
|
@ -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;
|
|
@ -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)?;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue