servo/components/bluetooth/README.md
Alex Touchet 820326873b
Replace bluetooth Readme with corrected version from devices repository (#36429)
This Readme is for a different crate located in
https://github.com/servo/servo/tree/main/third_party/blurmac. Was adding
it to the bluetooth directory in #30974 a mistake?

---------

Signed-off-by: Alex Touchet <26315797+atouchet@users.noreply.github.com>
2025-04-10 18:02:45 +00:00

165 lines
5.1 KiB
Markdown

# Bluetooth
Servo-specific APIs to access Bluetooth devices.
Bluetooth related code is located in `bluetooth.rs`.
### Implementation
Underlying dependency crates:
- Android platform: [blurdroid](https://crates.io/crates/blurdroid)
- Linux platform: [blurz](https://crates.io/crates/blurz)
- macOS platform: [blurmac](https://crates.io/crates/blurmac)
- `Fake` prefixed structures: [blurmock](https://crates.io/crates/blurmock)
`Empty` prefixed structures are located in `empty.rs`.
### Usage
#### Without the *bluetooth-test* feature
There are three supported platforms (Android, Linux, macOS), on other platforms we fall back to a default (`Empty` prefixed) implementation. Each enum (`BluetoothAdapter`, `BluetoothDevice`, etc.) will contain only one variant for each targeted platform. See the following `BluetoothAdapter` example:
Android:
```rust
pub enum BluetoothAdapter {
Android(Arc<BluetoothAdapterAndroid>),
}
```
Linux:
```rust
pub enum BluetoothAdapter {
Bluez(Arc<BluetoothAdapterBluez>),
}
```
macOS:
```rust
pub enum BluetoothAdapter {
Mac(Arc<BluetoothAdapterMac>),
}
```
Unsupported platforms:
```rust
pub enum BluetoothAdapter {
Empty(Arc<BluetoothAdapterEmpty>),
}
```
You will have a platform specific adapter, e.g. on Android target, `BluetoothAdapter::init()` will create a `BluetoothAdapter::Android` enum variant, which wraps an `Arc<BluetoothAdapterAndroid>`.
```rust
pub fn init() -> Result<BluetoothAdapter, Box<Error>> {
let blurdroid_adapter = try!(BluetoothAdapterAndroid::get_adapter());
Ok(BluetoothAdapter::Android(Arc::new(blurdroid_adapter)))
}
```
On each platform you can call the same functions to reach the same GATT hierarchy elements. The following code can access the same Bluetooth device on all supported platforms:
```rust
use device::{BluetoothAdapter, BluetoothDevice};
fn main() {
// Get the bluetooth adapter.
let adapter = BluetoothAdpater::init().expect("No bluetooth adapter found!");
// Get a device with the id 01:2A:00:4D:00:04 if it exists.
let device = adapter.get_device("01:2A:00:4D:00:04".to_owned() /*device address*/)
.expect("No bluetooth device found!");
}
```
#### With the *bluetooth-test* feature
Each enum (`BluetoothAdapter`, `BluetoothDevice`, etc.) will contain one variant of the three possible default target, and a `Mock` variant, which wraps a `Fake` structure.
Android:
```rust
pub enum BluetoothAdapter {
Android(Arc<BluetoothAdapterAndroid>),
Mock(Arc<FakeBluetoothAdapter>),
}
```
Linux:
```rust
pub enum BluetoothAdapter {
Bluez(Arc<BluetoothAdapterBluez>),
Mock(Arc<FakeBluetoothAdapter>),
}
```
macOS:
```rust
pub enum BluetoothAdapter {
Mac(Arc<BluetoothAdapterMac>),
Mock(Arc<FakeBluetoothAdapter>),
}
```
Unsupported platforms:
```rust
pub enum BluetoothAdapter {
Empty(Arc<BluetoothAdapterEmpty>),
Mock(Arc<FakeBluetoothAdapter>),
}
```
Beside the platform specific structures, you can create and access mock adapters, devices, services etc. These mock structures implements all the platform specific functions too. To create a mock GATT hierarchy, first you need to call the `BluetoothAdapter::init_mock()` function, insted of `BluetoothAdapter::init()`.
```rust
use device::{BluetoothAdapter, BluetoothDevice};
use std::String;
// This function takes a BluetoothAdapter,
// and print the ids of the devices, which the adapter can find.
fn print_device_ids(adapter: &BluetoothAdpater) {
let devices = match adapter.get_devices().expect("No devices on the adapter!");
for device in devices {
println!("{:?}", device.get_id());
}
}
fn main() {
// This code uses a real adapter.
// Get the bluetooth adapter.
let adapter = BluetoothAdpater::init().expect("No bluetooth adapter found!");
// Get a device with the id 01:2A:00:4D:00:04 if it exists.
let device = adapter.get_device("01:2A:00:4D:00:04".to_owned() /*device address*/)
.expect("No bluetooth device found!");
// This code uses a mock adapter.
// Creating a mock adapter.
let mock_adapter = BluetoothAdpater::init_mock().unwrap();
// Creating a mock device.
let mock_device =
BluetoothDevice::create_mock_device(mock_adapter,
"device_id_string_goes_here".to_owned())
.unwrap();
// Changing its device_id.
let new_device_id = String::from("new_device_id_string".to_owned());
mock_device.set_id(new_device_id.clone());
// Calling the get_id function must return the last id we set.
assert_equals!(new_device_id, mock_device.get_id());
// Getting the mock_device with its id
// must return the same mock device object we created before.
assert_equals!(Some(mock_device),
mock_adapter.get_device(new_device_id.clone()).unwrap());
// The print_device_ids function accept real and mock adapters too.
print_device_ids(&adapter);
print_device_ids(&mock_adapter);
}
```
Calling a test function on a not `Mock` structure, will result an error with the message: `Error! Test functions are not supported on real devices!`.