Skip to content
This repository was archived by the owner on Jan 26, 2024. It is now read-only.

Commit 1069d67

Browse files
author
bors-servo
authored
Auto merge of #23 - servo:fork-blurmac, r=nox
Fork blurmac <!-- Reviewable:start --> This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/devices/23) <!-- Reviewable:end -->
2 parents c3b012b + eea7884 commit 1069d67

15 files changed

+1846
-5
lines changed

.travis.yml

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
11
language: rust
2-
sudo: required
2+
3+
rust:
4+
- stable
5+
- beta
6+
- nightly
7+
8+
os:
9+
- linux
10+
- osx
11+
312
dist: trusty
4-
notifications:
5-
webhooks: http://build.servo.org:54856/travis
13+
addons:
14+
apt:
15+
packages: libdbus-1-dev
616

717
script:
8-
- sudo apt-get install libdbus-1-dev
918
- cargo build --features bluetooth-test
1019
- cargo test
1120

21+
notifications:
22+
webhooks: http://build.servo.org:54856/travis

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ blurz = { version = "0.2.1", optional = true }
1515
blurdroid = { version = "0.1.2", optional = true }
1616

1717
[target.'cfg(target_os = "macos")'.dependencies]
18-
blurmac = { version = "0.0.1", optional = true }
18+
blurmac = { path = "blurmac", optional = true }
1919

2020
[dependencies]
2121
blurmock = { version = "0.1.2", optional = true }

blurmac/Cargo.toml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[package]
2+
name = "blurmac"
3+
description = "Bluetooth Rust lib using macOS CoreBluetooth"
4+
version = "0.1.0"
5+
readme = "README.md"
6+
keywords = ["bluetooth", "ble", "macOS", "CoreBluetooth"]
7+
repository = "https://github.com/akosthekiss/blurmac"
8+
authors = ["Akos Kiss <[email protected]>"]
9+
license = "BSD-3-Clause"
10+
11+
[lib]
12+
name = "blurmac"
13+
path = "src/lib.rs"
14+
crate-type = ["rlib"]
15+
16+
[dependencies]
17+
log = "0.4"
18+
objc = "0.2"

blurmac/LICENSE.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
Copyright (c) 2017 Akos Kiss.
2+
All rights reserved.
3+
4+
Redistribution and use in source and binary forms, with or without
5+
modification, are permitted provided that the following conditions are met:
6+
7+
1. Redistributions of source code must retain the above copyright notice, this
8+
list of conditions and the following disclaimer.
9+
10+
2. Redistributions in binary form must reproduce the above copyright notice,
11+
this list of conditions and the following disclaimer in the documentation
12+
and/or other materials provided with the distribution.
13+
14+
3. Neither the name of the copyright holder nor the names of its contributors
15+
may be used to endorse or promote products derived from this software
16+
without specific prior written permission.
17+
18+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

blurmac/README.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Bluetooth Rust lib using macOS CoreBluetooth
2+
3+
[![Build Status](https://travis-ci.org/akosthekiss/blurmac.svg?branch=master)](https://travis-ci.org/akosthekiss/blurmac)
4+
[![Crates.io](https://img.shields.io/crates/v/blurmac.svg)](https://crates.io/crates/blurmac)
5+
6+
The main aim of BlurMac is to enable [WebBluetooth](https://webbluetoothcg.github.io)
7+
in [Servo](https://github.com/servo/servo) on macOS. Thus, API and implementation
8+
decisions are affected by the encapsulating [Devices](https://github.com/servo/devices),
9+
and the sibling [BlurZ](https://github.com/szeged/blurz) and [BlurDroid](https://github.com/szeged/blurdroid)
10+
crates.
11+
12+
13+
## Run Servo with WebBluetooth Enabled
14+
15+
Usually, you don't want to work with BlurMac on its own but use it within Servo.
16+
So, most probably you'll want to run Servo with WebBluetooth enabled:
17+
18+
```
19+
RUST_LOG=blurmac \
20+
./mach run \
21+
--dev \
22+
--pref=dom.bluetooth.enabled \
23+
--pref=dom.permissions.testing.allowed_in_nonsecure_contexts \
24+
URL
25+
```
26+
27+
Notes:
28+
* The above command is actually not really BlurMac-specific (except for the `RUST_LOG`
29+
part). It runs Servo with WBT enabled on any platform where WBT is supported.
30+
* You don't need the `RUST_LOG=blurmac` part if you don't want to see BlurMac debug
31+
messages on the console.
32+
* You don't need the `--dev` part if you want to run a release build.
33+
* You don't need the `--pref=dom.permissions.testing.allowed_in_nonsecure_contexts`
34+
part if your `URL` is https (but you do need it if you test a local file).
35+
36+
37+
## Known Issues
38+
39+
* Device RSSI can not be retrieved yet.
40+
* Support for included services is incomplete.
41+
* Descriptors are not supported yet.
42+
* Notifications on characteristics are not supported yet (the limitation comes from
43+
Devices).
44+
45+
46+
## Compatibility
47+
48+
Tested on:
49+
50+
* macOS Sierra 10.12.
51+
52+
53+
## Copyright and Licensing
54+
55+
Licensed under the BSD 3-Clause [License](LICENSE.md).

blurmac/src/adapter.rs

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
// Copyright (c) 2017 Akos Kiss.
2+
//
3+
// Licensed under the BSD 3-Clause License
4+
// <LICENSE.md or https://opensource.org/licenses/BSD-3-Clause>.
5+
// This file may not be copied, modified, or distributed except
6+
// according to those terms.
7+
8+
use std::error::Error;
9+
use std::os::raw::c_int;
10+
11+
use objc::runtime::{Object, YES};
12+
13+
use delegate::bm;
14+
use framework::{cb, io, ns};
15+
use utils::{NOT_SUPPORTED_ERROR, nsx};
16+
17+
18+
#[derive(Clone, Debug)]
19+
pub struct BluetoothAdapter {
20+
pub(crate) manager: *mut Object,
21+
pub(crate) delegate: *mut Object,
22+
}
23+
// TODO: implement std::fmt::Debug and/or std::fmt::Display instead of derive?
24+
25+
unsafe impl Send for BluetoothAdapter {}
26+
unsafe impl Sync for BluetoothAdapter {}
27+
28+
impl BluetoothAdapter {
29+
pub fn init() -> Result<BluetoothAdapter, Box<Error>> {
30+
trace!("BluetoothAdapter::init");
31+
let delegate = bm::delegate();
32+
let manager = cb::centralmanager(delegate);
33+
let adapter = BluetoothAdapter { manager: manager, delegate: delegate };
34+
35+
// NOTE: start discovery at once, servo leaves close to no time to do a proper discovery
36+
// in a BluetoothDiscoverySession
37+
adapter.start_discovery().unwrap();
38+
39+
Ok(adapter)
40+
}
41+
42+
pub fn get_id(&self) -> String {
43+
trace!("BluetoothAdapter::get_id");
44+
// NOTE: not aware of any better native ID than the address string
45+
self.get_address().unwrap()
46+
}
47+
48+
pub fn get_name(&self) -> Result<String, Box<Error>> {
49+
trace!("BluetoothAdapter::get_name");
50+
let controller = io::bluetoothhostcontroller_defaultcontroller();
51+
let name = io::bluetoothhostcontroller_nameasstring(controller);
52+
Ok(nsx::string_to_string(name))
53+
}
54+
55+
pub fn get_address(&self) -> Result<String, Box<Error>> {
56+
trace!("BluetoothAdapter::get_address");
57+
let controller = io::bluetoothhostcontroller_defaultcontroller();
58+
let address = io::bluetoothhostcontroller_addressasstring(controller);
59+
Ok(nsx::string_to_string(address))
60+
}
61+
62+
pub fn get_class(&self) -> Result<u32, Box<Error>> {
63+
trace!("BluetoothAdapter::get_class");
64+
let controller = io::bluetoothhostcontroller_defaultcontroller();
65+
let device_class = io::bluetoothhostcontroller_classofdevice(controller);
66+
Ok(device_class)
67+
}
68+
69+
pub fn is_powered(&self) -> Result<bool, Box<Error>> {
70+
trace!("BluetoothAdapter::is_powered");
71+
// NOTE: might be also available through
72+
// [[IOBluetoothHostController defaultController] powerState], but that's readonly, so keep
73+
// it in sync with set_powered
74+
Ok(io::bluetoothpreferencegetcontrollerpowerstate() == 1)
75+
}
76+
77+
pub fn set_powered(&self, value: bool) -> Result<(), Box<Error>> {
78+
trace!("BluetoothAdapter::set_powered");
79+
io::bluetoothpreferencesetcontrollerpowerstate(value as c_int);
80+
// TODO: wait for change to happen? whether it really happened?
81+
Ok(())
82+
}
83+
84+
pub fn is_discoverable(&self) -> Result<bool, Box<Error>> {
85+
trace!("BluetoothAdapter::is_discoverable");
86+
Ok(io::bluetoothpreferencegetdiscoverablestate() == 1)
87+
}
88+
89+
pub fn set_discoverable(&self, value: bool) -> Result<(), Box<Error>> {
90+
trace!("BluetoothAdapter::set_discoverable");
91+
io::bluetoothpreferencesetdiscoverablestate(value as c_int);
92+
// TODO: wait for change to happen? whether it really happened?
93+
Ok(())
94+
}
95+
96+
pub fn get_device_list(&self) -> Result<Vec<String>, Box<Error>> {
97+
trace!("BluetoothAdapter::get_device_list");
98+
let mut v = vec!();
99+
let peripherals = bm::delegate_peripherals(self.delegate);
100+
let keys = ns::dictionary_allkeys(peripherals);
101+
for i in 0..ns::array_count(keys) {
102+
v.push(nsx::string_to_string(ns::array_objectatindex(keys, i)));
103+
}
104+
Ok(v)
105+
}
106+
107+
// Was in BluetoothDiscoverySession
108+
109+
fn start_discovery(&self) -> Result<(), Box<Error>> {
110+
trace!("BluetoothAdapter::start_discovery");
111+
let options = ns::mutabledictionary();
112+
// NOTE: If duplicates are not allowed then a peripheral will not show up again once
113+
// connected and then disconnected.
114+
ns::mutabledictionary_setobject_forkey(options, ns::number_withbool(YES), unsafe { cb::CENTRALMANAGERSCANOPTIONALLOWDUPLICATESKEY });
115+
cb::centralmanager_scanforperipherals_options(self.manager, options);
116+
Ok(())
117+
}
118+
119+
fn stop_discovery(&self) -> Result<(), Box<Error>> {
120+
trace!("BluetoothAdapter::stop_discovery");
121+
cb::centralmanager_stopscan(self.manager);
122+
Ok(())
123+
}
124+
125+
// Not supported
126+
127+
pub fn get_alias(&self) -> Result<String, Box<Error>> {
128+
warn!("BluetoothAdapter::get_alias not supported by BlurMac");
129+
Err(Box::from(NOT_SUPPORTED_ERROR))
130+
}
131+
132+
pub fn set_alias(&self, _value: String) -> Result<(), Box<Error>> {
133+
warn!("BluetoothAdapter::set_alias not supported by BlurMac");
134+
Err(Box::from(NOT_SUPPORTED_ERROR))
135+
}
136+
137+
pub fn is_pairable(&self) -> Result<bool, Box<Error>> {
138+
warn!("BluetoothAdapter::is_pairable not supported by BlurMac");
139+
Err(Box::from(NOT_SUPPORTED_ERROR))
140+
}
141+
142+
pub fn set_pairable(&self, _value: bool) -> Result<(), Box<Error>> {
143+
warn!("BluetoothAdapter::set_pairable not supported by BlurMac");
144+
Err(Box::from(NOT_SUPPORTED_ERROR))
145+
}
146+
147+
pub fn get_pairable_timeout(&self) -> Result<u32, Box<Error>> {
148+
warn!("BluetoothAdapter::get_pairable_timeout not supported by BlurMac");
149+
Err(Box::from(NOT_SUPPORTED_ERROR))
150+
}
151+
152+
pub fn set_pairable_timeout(&self, _value: u32) -> Result<(), Box<Error>> {
153+
warn!("BluetoothAdapter::set_pairable_timeout not supported by BlurMac");
154+
Err(Box::from(NOT_SUPPORTED_ERROR))
155+
}
156+
157+
pub fn get_discoverable_timeout(&self) -> Result<u32, Box<Error>> {
158+
warn!("BluetoothAdapter::get_discoverable_timeout not supported by BlurMac");
159+
Err(Box::from(NOT_SUPPORTED_ERROR))
160+
}
161+
162+
pub fn set_discoverable_timeout(&self, _value: u32) -> Result<(), Box<Error>> {
163+
warn!("BluetoothAdapter::set_discoverable_timeout not supported by BlurMac");
164+
Err(Box::from(NOT_SUPPORTED_ERROR))
165+
}
166+
167+
pub fn is_discovering(&self) -> Result<bool, Box<Error>> {
168+
warn!("BluetoothAdapter::is_discovering not supported by BlurMac");
169+
Err(Box::from(NOT_SUPPORTED_ERROR))
170+
}
171+
172+
pub fn get_uuids(&self) -> Result<Vec<String>, Box<Error>> {
173+
warn!("BluetoothAdapter::get_uuids not supported by BlurMac");
174+
Err(Box::from(NOT_SUPPORTED_ERROR))
175+
}
176+
177+
pub fn get_vendor_id_source(&self) -> Result<String, Box<Error>> {
178+
warn!("BluetoothAdapter::get_vendor_id_source not supported by BlurMac");
179+
Err(Box::from(NOT_SUPPORTED_ERROR))
180+
}
181+
182+
pub fn get_vendor_id(&self) -> Result<u32, Box<Error>> {
183+
warn!("BluetoothAdapter::get_vendor_id not supported by BlurMac");
184+
Err(Box::from(NOT_SUPPORTED_ERROR))
185+
}
186+
187+
pub fn get_product_id(&self) -> Result<u32, Box<Error>> {
188+
warn!("BluetoothAdapter::get_product_id not supported by BlurMac");
189+
Err(Box::from(NOT_SUPPORTED_ERROR))
190+
}
191+
192+
pub fn get_device_id(&self) -> Result<u32, Box<Error>> {
193+
warn!("BluetoothAdapter::get_device_id not supported by BlurMac");
194+
Err(Box::from(NOT_SUPPORTED_ERROR))
195+
}
196+
197+
pub fn get_modalias(&self) -> Result<(String, u32, u32, u32), Box<Error>> {
198+
warn!("BluetoothAdapter::get_modalias not supported by BlurMac");
199+
Err(Box::from(NOT_SUPPORTED_ERROR))
200+
}
201+
}
202+
203+
impl Drop for BluetoothAdapter {
204+
fn drop(&mut self) {
205+
trace!("BluetoothAdapter::drop");
206+
// NOTE: stop discovery only here instead of in BluetoothDiscoverySession
207+
self.stop_discovery().unwrap();
208+
}
209+
}

0 commit comments

Comments
 (0)