Auto merge of #21442 - kingdido999:rustfmt/bluetooth, r=jdm

Format components bluetooth and bluetooth_traits

<!-- Please describe your changes on the following line: -->

```bash
rustfmt components/bluetooth/*.rs
rustfmt components/bluetooth_traits/*.rs
```
---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes fix a part of #21373 .
- [x] These changes do not require tests because it's code format change.

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/21442)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2018-08-17 03:14:56 -04:00 committed by GitHub
commit ad83faa745
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 486 additions and 340 deletions

View file

@ -75,9 +75,12 @@ impl BluetoothThreadFactory for IpcSender<BluetoothRequest> {
} else { } else {
BluetoothAdapter::init_mock() BluetoothAdapter::init_mock()
}.ok(); }.ok();
thread::Builder::new().name("BluetoothThread".to_owned()).spawn(move || { thread::Builder::new()
BluetoothManager::new(receiver, adapter, embedder_proxy).start(); .name("BluetoothThread".to_owned())
}).expect("Thread spawning failed"); .spawn(move || {
BluetoothManager::new(receiver, adapter, embedder_proxy).start();
})
.expect("Thread spawning failed");
sender sender
} }
} }
@ -179,7 +182,7 @@ fn matches_filters(device: &BluetoothDevice, filters: &BluetoothScanfilterSequen
return false; return false;
} }
return filters.iter().any(|f| matches_filter(device, f)) return filters.iter().any(|f| matches_filter(device, f));
} }
fn is_mock_adapter(adapter: &BluetoothAdapter) -> bool { fn is_mock_adapter(adapter: &BluetoothAdapter) -> bool {
@ -205,9 +208,11 @@ pub struct BluetoothManager {
} }
impl BluetoothManager { impl BluetoothManager {
pub fn new(receiver: IpcReceiver<BluetoothRequest>, pub fn new(
adapter: Option<BluetoothAdapter>, receiver: IpcReceiver<BluetoothRequest>,
embedder_proxy: EmbedderProxy) -> BluetoothManager { adapter: Option<BluetoothAdapter>,
embedder_proxy: EmbedderProxy,
) -> BluetoothManager {
BluetoothManager { BluetoothManager {
receiver: receiver, receiver: receiver,
adapter: adapter, adapter: adapter,
@ -254,9 +259,11 @@ impl BluetoothManager {
BluetoothRequest::Test(data_set_name, sender) => { BluetoothRequest::Test(data_set_name, sender) => {
let _ = sender.send(self.test(data_set_name)); let _ = sender.send(self.test(data_set_name));
}, },
BluetoothRequest::SetRepresentedToNull(service_ids, characteristic_ids, descriptor_ids) => { BluetoothRequest::SetRepresentedToNull(
self.remove_ids_from_caches(service_ids, characteristic_ids, descriptor_ids) service_ids,
}, characteristic_ids,
descriptor_ids,
) => self.remove_ids_from_caches(service_ids, characteristic_ids, descriptor_ids),
BluetoothRequest::IsRepresentedDeviceNull(id, sender) => { BluetoothRequest::IsRepresentedDeviceNull(id, sender) => {
let _ = sender.send(!self.device_is_cached(&id)); let _ = sender.send(!self.device_is_cached(&id));
}, },
@ -266,9 +273,7 @@ impl BluetoothManager {
BluetoothRequest::MatchesFilter(id, filters, sender) => { BluetoothRequest::MatchesFilter(id, filters, sender) => {
let _ = sender.send(self.device_matches_filter(&id, &filters)); let _ = sender.send(self.device_matches_filter(&id, &filters));
}, },
BluetoothRequest::Exit => { BluetoothRequest::Exit => break,
break
},
} }
} }
} }
@ -292,10 +297,12 @@ impl BluetoothManager {
} }
} }
fn remove_ids_from_caches(&mut self, fn remove_ids_from_caches(
service_ids: Vec<String>, &mut self,
characteristic_ids: Vec<String>, service_ids: Vec<String>,
descriptor_ids: Vec<String>) { characteristic_ids: Vec<String>,
descriptor_ids: Vec<String>,
) {
for id in service_ids { for id in service_ids {
self.cached_services.remove(&id); self.cached_services.remove(&id);
self.service_to_device.remove(&id); self.service_to_device.remove(&id);
@ -315,7 +322,10 @@ impl BluetoothManager {
// Adapter // Adapter
pub fn get_or_create_adapter(&mut self) -> Option<BluetoothAdapter> { pub fn get_or_create_adapter(&mut self) -> Option<BluetoothAdapter> {
let adapter_valid = self.adapter.as_ref().map_or(false, |a| a.get_address().is_ok()); let adapter_valid = self
.adapter
.as_ref()
.map_or(false, |a| a.get_address().is_ok());
if !adapter_valid { if !adapter_valid {
self.adapter = BluetoothAdapter::init().ok(); self.adapter = BluetoothAdapter::init().ok();
} }
@ -344,13 +354,14 @@ impl BluetoothManager {
// Device // Device
fn get_and_cache_devices(&mut self, adapter: &mut BluetoothAdapter) -> Vec<BluetoothDevice> { fn get_and_cache_devices(&mut self, adapter: &mut BluetoothAdapter) -> Vec<BluetoothDevice> {
let devices = adapter.get_devices().unwrap_or(vec!()); let devices = adapter.get_devices().unwrap_or(vec![]);
for device in &devices { for device in &devices {
if let Ok(address) = device.get_address() { if let Ok(address) = device.get_address() {
if !self.address_to_id.contains_key(&address) { if !self.address_to_id.contains_key(&address) {
let generated_id = self.generate_device_id(); let generated_id = self.generate_device_id();
self.address_to_id.insert(address, generated_id.clone()); self.address_to_id.insert(address, generated_id.clone());
self.cached_devices.insert(generated_id.clone(), device.clone()); self.cached_devices
.insert(generated_id.clone(), device.clone());
self.allowed_services.insert(generated_id, HashSet::new()); self.allowed_services.insert(generated_id, HashSet::new());
} }
} }
@ -358,14 +369,22 @@ impl BluetoothManager {
self.cached_devices.iter().map(|(_, d)| d.clone()).collect() self.cached_devices.iter().map(|(_, d)| d.clone()).collect()
} }
fn get_device(&mut self, adapter: &mut BluetoothAdapter, device_id: &str) -> Option<&BluetoothDevice> { fn get_device(
&mut self,
adapter: &mut BluetoothAdapter,
device_id: &str,
) -> Option<&BluetoothDevice> {
return_if_cached!(self.cached_devices, device_id); return_if_cached!(self.cached_devices, device_id);
self.get_and_cache_devices(adapter); self.get_and_cache_devices(adapter);
return_if_cached!(self.cached_devices, device_id); return_if_cached!(self.cached_devices, device_id);
None None
} }
fn select_device(&mut self, devices: Vec<BluetoothDevice>, adapter: &BluetoothAdapter) -> Option<String> { fn select_device(
&mut self,
devices: Vec<BluetoothDevice>,
adapter: &BluetoothAdapter,
) -> Option<String> {
if is_mock_adapter(adapter) || opts::get().headless { if is_mock_adapter(adapter) || opts::get().headless {
for device in &devices { for device in &devices {
if let Ok(address) = device.get_address() { if let Ok(address) = device.get_address() {
@ -375,14 +394,19 @@ impl BluetoothManager {
return None; return None;
} }
let mut dialog_rows: Vec<String> = vec!(); let mut dialog_rows: Vec<String> = vec![];
for device in devices { for device in devices {
dialog_rows.extend_from_slice(&[device.get_address().unwrap_or("".to_string()), dialog_rows.extend_from_slice(&[
device.get_name().unwrap_or("".to_string())]); device.get_address().unwrap_or("".to_string()),
device.get_name().unwrap_or("".to_string()),
]);
} }
let (ipc_sender, ipc_receiver) = ipc::channel().expect("Failed to create IPC channel!"); let (ipc_sender, ipc_receiver) = ipc::channel().expect("Failed to create IPC channel!");
let msg = (None, EmbedderMsg::GetSelectedBluetoothDevice(dialog_rows, ipc_sender)); let msg = (
None,
EmbedderMsg::GetSelectedBluetoothDevice(dialog_rows, ipc_sender),
);
self.embedder_proxy.send(msg); self.embedder_proxy.send(msg);
match ipc_receiver.recv() { match ipc_receiver.recv() {
@ -390,7 +414,7 @@ impl BluetoothManager {
Err(e) => { Err(e) => {
warn!("Failed to receive files from embedder ({}).", e); warn!("Failed to receive files from embedder ({}).", e);
None None
} },
} }
} }
@ -412,13 +436,15 @@ impl BluetoothManager {
} }
fn device_is_cached(&self, device_id: &str) -> bool { fn device_is_cached(&self, device_id: &str) -> bool {
self.cached_devices.contains_key(device_id) && self.address_to_id.values().any(|v| v == device_id) self.cached_devices.contains_key(device_id) &&
self.address_to_id.values().any(|v| v == device_id)
} }
fn device_matches_filter(&mut self, fn device_matches_filter(
device_id: &str, &mut self,
filters: &BluetoothScanfilterSequence) device_id: &str,
-> BluetoothResult<bool> { filters: &BluetoothScanfilterSequence,
) -> BluetoothResult<bool> {
let mut adapter = self.get_adapter()?; let mut adapter = self.get_adapter()?;
match self.get_device(&mut adapter, device_id) { match self.get_device(&mut adapter, device_id) {
Some(ref device) => Ok(matches_filters(device, filters)), Some(ref device) => Ok(matches_filters(device, filters)),
@ -428,27 +454,36 @@ impl BluetoothManager {
// Service // Service
fn get_and_cache_gatt_services(&mut self, fn get_and_cache_gatt_services(
adapter: &mut BluetoothAdapter, &mut self,
device_id: &str) adapter: &mut BluetoothAdapter,
-> Vec<BluetoothGATTService> { device_id: &str,
) -> Vec<BluetoothGATTService> {
let mut services = match self.get_device(adapter, device_id) { let mut services = match self.get_device(adapter, device_id) {
Some(d) => d.get_gatt_services().unwrap_or(vec!()), Some(d) => d.get_gatt_services().unwrap_or(vec![]),
None => vec!(), None => vec![],
}; };
services.retain(|s| !uuid_is_blocklisted(&s.get_uuid().unwrap_or(String::new()), Blocklist::All) && services.retain(|s| {
self.allowed_services !uuid_is_blocklisted(&s.get_uuid().unwrap_or(String::new()), Blocklist::All) &&
.get(device_id) self.allowed_services.get(device_id).map_or(false, |uuids| {
.map_or(false, |uuids| uuids.contains(&s.get_uuid().unwrap_or(String::new())))); uuids.contains(&s.get_uuid().unwrap_or(String::new()))
})
});
for service in &services { for service in &services {
self.cached_services.insert(service.get_id(), service.clone()); self.cached_services
self.service_to_device.insert(service.get_id(), device_id.to_owned()); .insert(service.get_id(), service.clone());
self.service_to_device
.insert(service.get_id(), device_id.to_owned());
} }
services services
} }
fn get_gatt_service(&mut self, adapter: &mut BluetoothAdapter, service_id: &str) -> Option<&BluetoothGATTService> { fn get_gatt_service(
&mut self,
adapter: &mut BluetoothAdapter,
service_id: &str,
) -> Option<&BluetoothGATTService> {
return_if_cached!(self.cached_services, service_id); return_if_cached!(self.cached_services, service_id);
let device_id = self.service_to_device.get(service_id)?.clone(); let device_id = self.service_to_device.get(service_id)?.clone();
self.get_and_cache_gatt_services(adapter, &device_id); self.get_and_cache_gatt_services(adapter, &device_id);
@ -457,34 +492,44 @@ impl BluetoothManager {
} }
fn service_is_cached(&self, service_id: &str) -> bool { fn service_is_cached(&self, service_id: &str) -> bool {
self.cached_services.contains_key(service_id) && self.service_to_device.contains_key(service_id) self.cached_services.contains_key(service_id) &&
self.service_to_device.contains_key(service_id)
} }
// Characteristic // Characteristic
fn get_and_cache_gatt_characteristics(&mut self, fn get_and_cache_gatt_characteristics(
adapter: &mut BluetoothAdapter, &mut self,
service_id: &str) adapter: &mut BluetoothAdapter,
-> Vec<BluetoothGATTCharacteristic> { service_id: &str,
) -> Vec<BluetoothGATTCharacteristic> {
let mut characteristics = match self.get_gatt_service(adapter, service_id) { let mut characteristics = match self.get_gatt_service(adapter, service_id) {
Some(s) => s.get_gatt_characteristics().unwrap_or(vec!()), Some(s) => s.get_gatt_characteristics().unwrap_or(vec![]),
None => vec!(), None => vec![],
}; };
characteristics.retain(|c| !uuid_is_blocklisted(&c.get_uuid().unwrap_or(String::new()), Blocklist::All)); characteristics.retain(|c| {
!uuid_is_blocklisted(&c.get_uuid().unwrap_or(String::new()), Blocklist::All)
});
for characteristic in &characteristics { for characteristic in &characteristics {
self.cached_characteristics.insert(characteristic.get_id(), characteristic.clone()); self.cached_characteristics
self.characteristic_to_service.insert(characteristic.get_id(), service_id.to_owned()); .insert(characteristic.get_id(), characteristic.clone());
self.characteristic_to_service
.insert(characteristic.get_id(), service_id.to_owned());
} }
characteristics characteristics
} }
fn get_gatt_characteristic(&mut self, fn get_gatt_characteristic(
adapter: &mut BluetoothAdapter, &mut self,
characteristic_id: &str) adapter: &mut BluetoothAdapter,
-> Option<&BluetoothGATTCharacteristic> { characteristic_id: &str,
) -> Option<&BluetoothGATTCharacteristic> {
return_if_cached!(self.cached_characteristics, characteristic_id); return_if_cached!(self.cached_characteristics, characteristic_id);
let service_id = self.characteristic_to_service.get(characteristic_id)?.clone(); let service_id = self
.characteristic_to_service
.get(characteristic_id)?
.clone();
self.get_and_cache_gatt_characteristics(adapter, &service_id); self.get_and_cache_gatt_characteristics(adapter, &service_id);
return_if_cached!(self.cached_characteristics, characteristic_id); return_if_cached!(self.cached_characteristics, characteristic_id);
None None
@ -492,7 +537,7 @@ impl BluetoothManager {
fn get_characteristic_properties(&self, characteristic: &BluetoothGATTCharacteristic) -> Flags { fn get_characteristic_properties(&self, characteristic: &BluetoothGATTCharacteristic) -> Flags {
let mut props: Flags = Flags::empty(); let mut props: Flags = Flags::empty();
let flags = characteristic.get_flags().unwrap_or(vec!()); let flags = characteristic.get_flags().unwrap_or(vec![]);
for flag in flags { for flag in flags {
match flag.as_ref() { match flag.as_ref() {
"broadcast" => props.insert(Flags::BROADCAST), "broadcast" => props.insert(Flags::BROADCAST),
@ -512,34 +557,44 @@ impl BluetoothManager {
fn characteristic_is_cached(&self, characteristic_id: &str) -> bool { fn characteristic_is_cached(&self, characteristic_id: &str) -> bool {
self.cached_characteristics.contains_key(characteristic_id) && self.cached_characteristics.contains_key(characteristic_id) &&
self.characteristic_to_service.contains_key(characteristic_id) self.characteristic_to_service
.contains_key(characteristic_id)
} }
// Descriptor // Descriptor
fn get_and_cache_gatt_descriptors(&mut self, fn get_and_cache_gatt_descriptors(
adapter: &mut BluetoothAdapter, &mut self,
characteristic_id: &str) adapter: &mut BluetoothAdapter,
-> Vec<BluetoothGATTDescriptor> { characteristic_id: &str,
) -> Vec<BluetoothGATTDescriptor> {
let mut descriptors = match self.get_gatt_characteristic(adapter, characteristic_id) { let mut descriptors = match self.get_gatt_characteristic(adapter, characteristic_id) {
Some(c) => c.get_gatt_descriptors().unwrap_or(vec!()), Some(c) => c.get_gatt_descriptors().unwrap_or(vec![]),
None => vec!(), None => vec![],
}; };
descriptors.retain(|d| !uuid_is_blocklisted(&d.get_uuid().unwrap_or(String::new()), Blocklist::All)); descriptors.retain(|d| {
!uuid_is_blocklisted(&d.get_uuid().unwrap_or(String::new()), Blocklist::All)
});
for descriptor in &descriptors { for descriptor in &descriptors {
self.cached_descriptors.insert(descriptor.get_id(), descriptor.clone()); self.cached_descriptors
self.descriptor_to_characteristic.insert(descriptor.get_id(), characteristic_id.to_owned()); .insert(descriptor.get_id(), descriptor.clone());
self.descriptor_to_characteristic
.insert(descriptor.get_id(), characteristic_id.to_owned());
} }
descriptors descriptors
} }
fn get_gatt_descriptor(&mut self, fn get_gatt_descriptor(
adapter: &mut BluetoothAdapter, &mut self,
descriptor_id: &str) adapter: &mut BluetoothAdapter,
-> Option<&BluetoothGATTDescriptor> { descriptor_id: &str,
) -> Option<&BluetoothGATTDescriptor> {
return_if_cached!(self.cached_descriptors, descriptor_id); return_if_cached!(self.cached_descriptors, descriptor_id);
let characteristic_id = self.descriptor_to_characteristic.get(descriptor_id)?.clone(); let characteristic_id = self
.descriptor_to_characteristic
.get(descriptor_id)?
.clone();
self.get_and_cache_gatt_descriptors(adapter, &characteristic_id); self.get_and_cache_gatt_descriptors(adapter, &characteristic_id);
return_if_cached!(self.cached_descriptors, descriptor_id); return_if_cached!(self.cached_descriptors, descriptor_id);
None None
@ -548,9 +603,7 @@ impl BluetoothManager {
// Methods // Methods
// https://webbluetoothcg.github.io/web-bluetooth/#request-bluetooth-devices // https://webbluetoothcg.github.io/web-bluetooth/#request-bluetooth-devices
fn request_device(&mut self, fn request_device(&mut self, options: RequestDeviceoptions) -> BluetoothResponseResult {
options: RequestDeviceoptions)
-> BluetoothResponseResult {
// Step 6. // Step 6.
let mut adapter = self.get_adapter()?; let mut adapter = self.get_adapter()?;
@ -569,9 +622,10 @@ impl BluetoothManager {
// Step 8. // Step 8.
if !options.is_accepting_all_devices() { if !options.is_accepting_all_devices() {
matched_devices = matched_devices.into_iter() matched_devices = matched_devices
.filter(|d| matches_filters(d, options.get_filters())) .into_iter()
.collect(); .filter(|d| matches_filters(d, options.get_filters()))
.collect();
} }
// Step 9. // Step 9.
@ -623,7 +677,7 @@ impl BluetoothManager {
thread::sleep(Duration::from_millis(CONNECTION_TIMEOUT_MS)); thread::sleep(Duration::from_millis(CONNECTION_TIMEOUT_MS));
}, },
} }
// TODO: Step 5.1.4: Use the exchange MTU procedure. // TODO: Step 5.1.4: Use the exchange MTU procedure.
} }
// Step 5.1.3. // Step 5.1.3.
return Err(BluetoothError::Network); return Err(BluetoothError::Network);
@ -655,12 +709,13 @@ impl BluetoothManager {
} }
// https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren
fn get_gatt_children(&mut self, fn get_gatt_children(
id: String, &mut self,
uuid: Option<String>, id: String,
single: bool, uuid: Option<String>,
child_type: GATTType) single: bool,
-> BluetoothResponseResult { child_type: GATTType,
) -> BluetoothResponseResult {
let mut adapter = self.get_adapter()?; let mut adapter = self.get_adapter()?;
match child_type { match child_type {
GATTType::PrimaryService => { GATTType::PrimaryService => {
@ -670,7 +725,11 @@ impl BluetoothManager {
} }
// Step 6. // Step 6.
if let Some(ref uuid) = uuid { if let Some(ref uuid) = uuid {
if !self.allowed_services.get(&id).map_or(false, |s| s.contains(uuid)) { if !self
.allowed_services
.get(&id)
.map_or(false, |s| s.contains(uuid))
{
return Err(BluetoothError::Security); return Err(BluetoothError::Security);
} }
} }
@ -678,17 +737,15 @@ impl BluetoothManager {
if let Some(uuid) = uuid { if let Some(uuid) = uuid {
services.retain(|ref e| e.get_uuid().unwrap_or(String::new()) == uuid); services.retain(|ref e| e.get_uuid().unwrap_or(String::new()) == uuid);
} }
let mut services_vec = vec!(); let mut services_vec = vec![];
for service in services { for service in services {
if service.is_primary().unwrap_or(false) { if service.is_primary().unwrap_or(false) {
if let Ok(uuid) = service.get_uuid() { if let Ok(uuid) = service.get_uuid() {
services_vec.push( services_vec.push(BluetoothServiceMsg {
BluetoothServiceMsg { uuid: uuid,
uuid: uuid, is_primary: true,
is_primary: true, instance_id: service.get_id(),
instance_id: service.get_id(), });
}
);
} }
} }
} }
@ -705,29 +762,30 @@ impl BluetoothManager {
return Err(BluetoothError::InvalidState); return Err(BluetoothError::InvalidState);
} }
// Step 6. // Step 6.
let mut characteristics = self.get_and_cache_gatt_characteristics(&mut adapter, &id); let mut characteristics =
self.get_and_cache_gatt_characteristics(&mut adapter, &id);
if let Some(uuid) = uuid { if let Some(uuid) = uuid {
characteristics.retain(|ref e| e.get_uuid().unwrap_or(String::new()) == uuid); characteristics.retain(|ref e| e.get_uuid().unwrap_or(String::new()) == uuid);
} }
let mut characteristics_vec = vec!(); let mut characteristics_vec = vec![];
for characteristic in characteristics { for characteristic in characteristics {
if let Ok(uuid) = characteristic.get_uuid() { if let Ok(uuid) = characteristic.get_uuid() {
let properties = self.get_characteristic_properties(&characteristic); let properties = self.get_characteristic_properties(&characteristic);
characteristics_vec.push( characteristics_vec.push(BluetoothCharacteristicMsg {
BluetoothCharacteristicMsg { uuid: uuid,
uuid: uuid, instance_id: characteristic.get_id(),
instance_id: characteristic.get_id(), broadcast: properties.contains(Flags::BROADCAST),
broadcast: properties.contains(Flags::BROADCAST), read: properties.contains(Flags::READ),
read: properties.contains(Flags::READ), write_without_response: properties
write_without_response: properties.contains(Flags::WRITE_WITHOUT_RESPONSE), .contains(Flags::WRITE_WITHOUT_RESPONSE),
write: properties.contains(Flags::WRITE), write: properties.contains(Flags::WRITE),
notify: properties.contains(Flags::NOTIFY), notify: properties.contains(Flags::NOTIFY),
indicate: properties.contains(Flags::INDICATE), indicate: properties.contains(Flags::INDICATE),
authenticated_signed_writes: properties.contains(Flags::AUTHENTICATED_SIGNED_WRITES), authenticated_signed_writes: properties
reliable_write: properties.contains(Flags::RELIABLE_WRITE), .contains(Flags::AUTHENTICATED_SIGNED_WRITES),
writable_auxiliaries: properties.contains(Flags::WRITABLE_AUXILIARIES), reliable_write: properties.contains(Flags::RELIABLE_WRITE),
} writable_auxiliaries: properties.contains(Flags::WRITABLE_AUXILIARIES),
); });
} }
} }
@ -736,7 +794,10 @@ impl BluetoothManager {
return Err(BluetoothError::NotFound); return Err(BluetoothError::NotFound);
} }
return Ok(BluetoothResponse::GetCharacteristics(characteristics_vec, single)); return Ok(BluetoothResponse::GetCharacteristics(
characteristics_vec,
single,
));
}, },
GATTType::IncludedService => { GATTType::IncludedService => {
// Step 5. // Step 5.
@ -752,17 +813,15 @@ impl BluetoothManager {
Some(s) => s, Some(s) => s,
None => return Err(BluetoothError::NotFound), None => return Err(BluetoothError::NotFound),
}; };
let services = primary_service.get_includes(device).unwrap_or(vec!()); let services = primary_service.get_includes(device).unwrap_or(vec![]);
let mut services_vec = vec!(); let mut services_vec = vec![];
for service in services { for service in services {
if let Ok(service_uuid) = service.get_uuid() { if let Ok(service_uuid) = service.get_uuid() {
services_vec.push( services_vec.push(BluetoothServiceMsg {
BluetoothServiceMsg { uuid: service_uuid,
uuid: service_uuid, is_primary: service.is_primary().unwrap_or(false),
is_primary: service.is_primary().unwrap_or(false), instance_id: service.get_id(),
instance_id: service.get_id(), });
}
);
} }
} }
if let Some(uuid) = uuid { if let Some(uuid) = uuid {
@ -787,15 +846,13 @@ impl BluetoothManager {
if let Some(uuid) = uuid { if let Some(uuid) = uuid {
descriptors.retain(|ref e| e.get_uuid().unwrap_or(String::new()) == uuid); descriptors.retain(|ref e| e.get_uuid().unwrap_or(String::new()) == uuid);
} }
let mut descriptors_vec = vec!(); let mut descriptors_vec = vec![];
for descriptor in descriptors { for descriptor in descriptors {
if let Ok(uuid) = descriptor.get_uuid() { if let Ok(uuid) = descriptor.get_uuid() {
descriptors_vec.push( descriptors_vec.push(BluetoothDescriptorMsg {
BluetoothDescriptorMsg { uuid: uuid,
uuid: uuid, instance_id: descriptor.get_id(),
instance_id: descriptor.get_id(), });
}
);
} }
} }
@ -816,15 +873,17 @@ impl BluetoothManager {
let mut adapter = self.get_adapter()?; let mut adapter = self.get_adapter()?;
// (Characteristic) Step 5.3. // (Characteristic) Step 5.3.
let mut value = self.get_gatt_characteristic(&mut adapter, &id) let mut value = self
.map(|c| c.read_value().unwrap_or(vec![])); .get_gatt_characteristic(&mut adapter, &id)
.map(|c| c.read_value().unwrap_or(vec![]));
// (Characteristic) TODO: Step 5.4: Handle all the errors returned from the read_value call. // (Characteristic) TODO: Step 5.4: Handle all the errors returned from the read_value call.
// (Descriptor) Step 5.2. // (Descriptor) Step 5.2.
if value.is_none() { if value.is_none() {
value = self.get_gatt_descriptor(&mut adapter, &id) value = self
.map(|d| d.read_value().unwrap_or(vec![])); .get_gatt_descriptor(&mut adapter, &id)
.map(|d| d.read_value().unwrap_or(vec![]));
} }
// (Descriptor) TODO: Step 5.3: Handle all the errors returned from the read_value call. // (Descriptor) TODO: Step 5.3: Handle all the errors returned from the read_value call.
@ -848,15 +907,17 @@ impl BluetoothManager {
let mut adapter = self.get_adapter()?; let mut adapter = self.get_adapter()?;
// (Characteristic) Step 7.3. // (Characteristic) Step 7.3.
let mut result = self.get_gatt_characteristic(&mut adapter, &id) let mut result = self
.map(|c| c.write_value(value.clone())); .get_gatt_characteristic(&mut adapter, &id)
.map(|c| c.write_value(value.clone()));
// (Characteristic) TODO: Step 7.4: Handle all the errors returned from the write_value call. // (Characteristic) TODO: Step 7.4: Handle all the errors returned from the write_value call.
// (Descriptor) Step 7.2. // (Descriptor) Step 7.2.
if result.is_none() { if result.is_none() {
result = self.get_gatt_descriptor(&mut adapter, &id) result = self
.map(|d| d.write_value(value.clone())); .get_gatt_descriptor(&mut adapter, &id)
.map(|d| d.write_value(value.clone()));
} }
// (Descriptor) TODO: Step 7.3: Handle all the errors returned from the write_value call. // (Descriptor) TODO: Step 7.3: Handle all the errors returned from the write_value call.
@ -921,6 +982,8 @@ impl BluetoothManager {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-getavailability // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-getavailability
fn get_availability(&mut self) -> BluetoothResponseResult { fn get_availability(&mut self) -> BluetoothResponseResult {
Ok(BluetoothResponse::GetAvailability(self.get_adapter().is_ok())) Ok(BluetoothResponse::GetAvailability(
self.get_adapter().is_ok(),
))
} }
} }

View file

@ -34,7 +34,8 @@ const UNICODE_DEVICE_ADAPTER: &'static str = "UnicodeDeviceAdapter";
// https://cs.chromium.org/chromium/src/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h?l=205 // https://cs.chromium.org/chromium/src/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h?l=205
const MISSING_SERVICE_HEART_RATE_ADAPTER: &'static str = "MissingServiceHeartRateAdapter"; const MISSING_SERVICE_HEART_RATE_ADAPTER: &'static str = "MissingServiceHeartRateAdapter";
// https://cs.chromium.org/chromium/src/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h?l=219 // https://cs.chromium.org/chromium/src/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h?l=219
const MISSING_CHARACTERISTIC_HEART_RATE_ADAPTER: &'static str = "MissingCharacteristicHeartRateAdapter"; const MISSING_CHARACTERISTIC_HEART_RATE_ADAPTER: &'static str =
"MissingCharacteristicHeartRateAdapter";
const MISSING_DESCRIPTOR_HEART_RATE_ADAPTER: &'static str = "MissingDescriptorHeartRateAdapter"; const MISSING_DESCRIPTOR_HEART_RATE_ADAPTER: &'static str = "MissingDescriptorHeartRateAdapter";
// https://cs.chromium.org/chromium/src/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h?l=234 // https://cs.chromium.org/chromium/src/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h?l=234
const HEART_RATE_ADAPTER: &'static str = "HeartRateAdapter"; const HEART_RATE_ADAPTER: &'static str = "HeartRateAdapter";
@ -80,32 +81,38 @@ const HUMAN_INTERFACE_DEVICE_SERVICE_UUID: &'static str = "00001812-0000-1000-80
const TX_POWER_SERVICE_UUID: &'static str = "00001804-0000-1000-8000-00805f9b34fb"; const TX_POWER_SERVICE_UUID: &'static str = "00001804-0000-1000-8000-00805f9b34fb";
// Characteristic UUIDs // Characteristic UUIDs
const BLOCKLIST_EXCLUDE_READS_CHARACTERISTIC_UUID: &'static str = "bad1c9a2-9a5b-4015-8b60-1579bbbf2135"; const BLOCKLIST_EXCLUDE_READS_CHARACTERISTIC_UUID: &'static str =
"bad1c9a2-9a5b-4015-8b60-1579bbbf2135";
// https://www.bluetooth.com/specifications/gatt/ // https://www.bluetooth.com/specifications/gatt/
// viewer?attributeXmlFile=org.bluetooth.characteristic.body_sensor_location.xml // viewer?attributeXmlFile=org.bluetooth.characteristic.body_sensor_location.xml
const BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID: &'static str = "00002a38-0000-1000-8000-00805f9b34fb"; const BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID: &'static str =
"00002a38-0000-1000-8000-00805f9b34fb";
// https://www.bluetooth.com/specifications/gatt/ // https://www.bluetooth.com/specifications/gatt/
// viewer?attributeXmlFile=org.bluetooth.characteristic.gap.device_name.xml // viewer?attributeXmlFile=org.bluetooth.characteristic.gap.device_name.xml
const DEVICE_NAME_CHARACTERISTIC_UUID: &'static str = "00002a00-0000-1000-8000-00805f9b34fb"; const DEVICE_NAME_CHARACTERISTIC_UUID: &'static str = "00002a00-0000-1000-8000-00805f9b34fb";
// https://www.bluetooth.com/specifications/gatt/ // https://www.bluetooth.com/specifications/gatt/
// viewer?attributeXmlFile=org.bluetooth.characteristic.heart_rate_measurement.xml // viewer?attributeXmlFile=org.bluetooth.characteristic.heart_rate_measurement.xml
const HEART_RATE_MEASUREMENT_CHARACTERISTIC_UUID: &'static str = "00002a37-0000-1000-8000-00805f9b34fb"; const HEART_RATE_MEASUREMENT_CHARACTERISTIC_UUID: &'static str =
"00002a37-0000-1000-8000-00805f9b34fb";
// https://www.bluetooth.com/specifications/gatt/ // https://www.bluetooth.com/specifications/gatt/
// viewer?attributeXmlFile=org.bluetooth.characteristic.gap.peripheral_privacy_flag.xml // viewer?attributeXmlFile=org.bluetooth.characteristic.gap.peripheral_privacy_flag.xml
const PERIPHERAL_PRIVACY_FLAG_CHARACTERISTIC_UUID: &'static str = "00002a02-0000-1000-8000-00805f9b34fb"; const PERIPHERAL_PRIVACY_FLAG_CHARACTERISTIC_UUID: &'static str =
"00002a02-0000-1000-8000-00805f9b34fb";
// https://www.bluetooth.com/specifications/gatt/ // https://www.bluetooth.com/specifications/gatt/
// viewer?attributeXmlFile=org.bluetooth.characteristic.serial_number_string.xml // viewer?attributeXmlFile=org.bluetooth.characteristic.serial_number_string.xml
const SERIAL_NUMBER_STRING_UUID: &'static str = "00002a25-0000-1000-8000-00805f9b34fb"; const SERIAL_NUMBER_STRING_UUID: &'static str = "00002a25-0000-1000-8000-00805f9b34fb";
// Descriptor UUIDs // Descriptor UUIDs
const BLOCKLIST_EXCLUDE_READS_DESCRIPTOR_UUID: &'static str = "aaaaaaaa-aaaa-1181-0510-810819516110"; const BLOCKLIST_EXCLUDE_READS_DESCRIPTOR_UUID: &'static str =
"aaaaaaaa-aaaa-1181-0510-810819516110";
const BLOCKLIST_DESCRIPTOR_UUID: &'static str = "07711111-6104-0970-7011-1107105110aa"; const BLOCKLIST_DESCRIPTOR_UUID: &'static str = "07711111-6104-0970-7011-1107105110aa";
// https://www.bluetooth.com/specifications/gatt/ // https://www.bluetooth.com/specifications/gatt/
// viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.characteristic_user_description.xml // viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.characteristic_user_description.xml
const CHARACTERISTIC_USER_DESCRIPTION_UUID: &'static str = "00002901-0000-1000-8000-00805f9b34fb"; const CHARACTERISTIC_USER_DESCRIPTION_UUID: &'static str = "00002901-0000-1000-8000-00805f9b34fb";
// https://www.bluetooth.com/specifications/gatt/ // https://www.bluetooth.com/specifications/gatt/
// viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml // viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
const CLIENT_CHARACTERISTIC_CONFIGURATION_UUID: &'static str = "00002902-0000-1000-8000-00805f9b34fb"; const CLIENT_CHARACTERISTIC_CONFIGURATION_UUID: &'static str =
"00002902-0000-1000-8000-00805f9b34fb";
// https://www.bluetooth.com/specifications/gatt/ // https://www.bluetooth.com/specifications/gatt/
// viewer?attributeXmlFile=org.bluetooth.descriptor.number_of_digitals.xml // viewer?attributeXmlFile=org.bluetooth.descriptor.number_of_digitals.xml
const NUMBER_OF_DIGITALS_UUID: &'static str = "00002909-0000-1000-8000-00805f9b34fb"; const NUMBER_OF_DIGITALS_UUID: &'static str = "00002909-0000-1000-8000-00805f9b34fb";
@ -117,12 +124,12 @@ fn generate_id() -> Uuid {
let mut generated = false; let mut generated = false;
while !generated { while !generated {
id = Uuid::new_v4(); id = Uuid::new_v4();
CACHED_IDS.with(|cache| CACHED_IDS.with(|cache| {
if !cache.borrow().contains(&id) { if !cache.borrow().contains(&id) {
cache.borrow_mut().insert(id.clone()); cache.borrow_mut().insert(id.clone());
generated = true; generated = true;
} }
); });
} }
id id
} }
@ -136,10 +143,11 @@ fn set_adapter(adapter: &BluetoothAdapter, adapter_name: String) -> Result<(), B
} }
// Create Device // Create Device
fn create_device(adapter: &BluetoothAdapter, fn create_device(
name: String, adapter: &BluetoothAdapter,
address: String) name: String,
-> Result<BluetoothDevice, Box<Error>> { address: String,
) -> Result<BluetoothDevice, Box<Error>> {
let device = BluetoothDevice::create_mock_device(adapter.clone(), generate_id().to_string())?; let device = BluetoothDevice::create_mock_device(adapter.clone(), generate_id().to_string())?;
device.set_name(Some(name))?; device.set_name(Some(name))?;
device.set_address(address)?; device.set_address(address)?;
@ -148,162 +156,192 @@ fn create_device(adapter: &BluetoothAdapter,
} }
// Create Device with UUIDs // Create Device with UUIDs
fn create_device_with_uuids(adapter: &BluetoothAdapter, fn create_device_with_uuids(
name: String, adapter: &BluetoothAdapter,
address: String, name: String,
uuids: Vec<String>) address: String,
-> Result<BluetoothDevice, Box<Error>> { uuids: Vec<String>,
) -> Result<BluetoothDevice, Box<Error>> {
let device = create_device(adapter, name, address)?; let device = create_device(adapter, name, address)?;
device.set_uuids(uuids)?; device.set_uuids(uuids)?;
Ok(device) Ok(device)
} }
// Create Service // Create Service
fn create_service(device: &BluetoothDevice, fn create_service(
uuid: String) device: &BluetoothDevice,
-> Result<BluetoothGATTService, Box<Error>> { uuid: String,
let service = BluetoothGATTService::create_mock_service(device.clone(), generate_id().to_string())?; ) -> Result<BluetoothGATTService, Box<Error>> {
let service =
BluetoothGATTService::create_mock_service(device.clone(), generate_id().to_string())?;
service.set_uuid(uuid)?; service.set_uuid(uuid)?;
Ok(service) Ok(service)
} }
// Create Characteristic // Create Characteristic
fn create_characteristic(service: &BluetoothGATTService, fn create_characteristic(
uuid: String) service: &BluetoothGATTService,
-> Result<BluetoothGATTCharacteristic, Box<Error>> { uuid: String,
let characteristic = ) -> Result<BluetoothGATTCharacteristic, Box<Error>> {
BluetoothGATTCharacteristic::create_mock_characteristic(service.clone(), generate_id().to_string())?; let characteristic = BluetoothGATTCharacteristic::create_mock_characteristic(
service.clone(),
generate_id().to_string(),
)?;
characteristic.set_uuid(uuid)?; characteristic.set_uuid(uuid)?;
Ok(characteristic) Ok(characteristic)
} }
// Create Characteristic with value // Create Characteristic with value
fn create_characteristic_with_value(service: &BluetoothGATTService, fn create_characteristic_with_value(
uuid: String, service: &BluetoothGATTService,
value: Vec<u8>) uuid: String,
-> Result<BluetoothGATTCharacteristic, Box<Error>> { value: Vec<u8>,
) -> Result<BluetoothGATTCharacteristic, Box<Error>> {
let characteristic = create_characteristic(service, uuid)?; let characteristic = create_characteristic(service, uuid)?;
characteristic.set_value(value)?; characteristic.set_value(value)?;
Ok(characteristic) Ok(characteristic)
} }
// Create Descriptor // Create Descriptor
fn create_descriptor(characteristic: &BluetoothGATTCharacteristic, fn create_descriptor(
uuid: String) characteristic: &BluetoothGATTCharacteristic,
-> Result<BluetoothGATTDescriptor, Box<Error>> { uuid: String,
let descriptor = ) -> Result<BluetoothGATTDescriptor, Box<Error>> {
BluetoothGATTDescriptor::create_mock_descriptor(characteristic.clone(), generate_id().to_string())?; let descriptor = BluetoothGATTDescriptor::create_mock_descriptor(
characteristic.clone(),
generate_id().to_string(),
)?;
descriptor.set_uuid(uuid)?; descriptor.set_uuid(uuid)?;
Ok(descriptor) Ok(descriptor)
} }
// Create Descriptor with value // Create Descriptor with value
fn create_descriptor_with_value(characteristic: &BluetoothGATTCharacteristic, fn create_descriptor_with_value(
uuid: String, characteristic: &BluetoothGATTCharacteristic,
value: Vec<u8>) uuid: String,
-> Result<BluetoothGATTDescriptor, Box<Error>> { value: Vec<u8>,
) -> Result<BluetoothGATTDescriptor, Box<Error>> {
let descriptor = create_descriptor(characteristic, uuid)?; let descriptor = create_descriptor(characteristic, uuid)?;
descriptor.set_value(value)?; descriptor.set_value(value)?;
Ok(descriptor) Ok(descriptor)
} }
fn create_heart_rate_service(device: &BluetoothDevice, fn create_heart_rate_service(
empty: bool) device: &BluetoothDevice,
-> Result<BluetoothGATTService, Box<Error>> { empty: bool,
) -> Result<BluetoothGATTService, Box<Error>> {
// Heart Rate Service // Heart Rate Service
let heart_rate_service = create_service(device, HEART_RATE_SERVICE_UUID.to_owned())?; let heart_rate_service = create_service(device, HEART_RATE_SERVICE_UUID.to_owned())?;
if empty { if empty {
return Ok(heart_rate_service) return Ok(heart_rate_service);
} }
// Heart Rate Measurement Characteristic // Heart Rate Measurement Characteristic
let heart_rate_measurement_characteristic = let heart_rate_measurement_characteristic = create_characteristic_with_value(
create_characteristic_with_value(&heart_rate_service, &heart_rate_service,
HEART_RATE_MEASUREMENT_CHARACTERISTIC_UUID.to_owned(), HEART_RATE_MEASUREMENT_CHARACTERISTIC_UUID.to_owned(),
vec![0])?; vec![0],
heart_rate_measurement_characteristic.set_flags(vec![NOTIFY_FLAG.to_string(), )?;
READ_FLAG.to_string(), heart_rate_measurement_characteristic.set_flags(vec![
WRITE_FLAG.to_string()])?; NOTIFY_FLAG.to_string(),
READ_FLAG.to_string(),
WRITE_FLAG.to_string(),
])?;
// Body Sensor Location Characteristic 1 // Body Sensor Location Characteristic 1
let body_sensor_location_characteristic_1 = let body_sensor_location_characteristic_1 = create_characteristic_with_value(
create_characteristic_with_value(&heart_rate_service, &heart_rate_service,
BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID.to_owned(), BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID.to_owned(),
vec![49])?; vec![49],
body_sensor_location_characteristic_1.set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?; )?;
body_sensor_location_characteristic_1
.set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?;
// Body Sensor Location Characteristic 2 // Body Sensor Location Characteristic 2
let body_sensor_location_characteristic_2 = let body_sensor_location_characteristic_2 = create_characteristic_with_value(
create_characteristic_with_value(&heart_rate_service, &heart_rate_service,
BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID.to_owned(), BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID.to_owned(),
vec![50])?; vec![50],
body_sensor_location_characteristic_2.set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?; )?;
body_sensor_location_characteristic_2
.set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?;
Ok(heart_rate_service) Ok(heart_rate_service)
} }
fn create_generic_access_service(device: &BluetoothDevice, fn create_generic_access_service(
empty: bool) device: &BluetoothDevice,
-> Result<BluetoothGATTService, Box<Error>> { empty: bool,
) -> Result<BluetoothGATTService, Box<Error>> {
// Generic Access Service // Generic Access Service
let generic_access_service = let generic_access_service = create_service(device, GENERIC_ACCESS_SERVICE_UUID.to_owned())?;
create_service(device, GENERIC_ACCESS_SERVICE_UUID.to_owned())?;
if empty { if empty {
return Ok(generic_access_service) return Ok(generic_access_service);
} }
// Device Name Characteristic // Device Name Characteristic
let device_name_characteristic = let device_name_characteristic = create_characteristic_with_value(
create_characteristic_with_value(&generic_access_service, &generic_access_service,
DEVICE_NAME_CHARACTERISTIC_UUID.to_owned(), DEVICE_NAME_CHARACTERISTIC_UUID.to_owned(),
HEART_RATE_DEVICE_NAME.as_bytes().to_vec())?; HEART_RATE_DEVICE_NAME.as_bytes().to_vec(),
)?;
device_name_characteristic.set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?; device_name_characteristic.set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?;
// Number of Digitals descriptor // Number of Digitals descriptor
let number_of_digitals_descriptor_1 = let number_of_digitals_descriptor_1 = create_descriptor_with_value(
create_descriptor_with_value(&device_name_characteristic, &device_name_characteristic,
NUMBER_OF_DIGITALS_UUID.to_owned(), NUMBER_OF_DIGITALS_UUID.to_owned(),
vec![49])?; vec![49],
)?;
number_of_digitals_descriptor_1.set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?; number_of_digitals_descriptor_1.set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?;
let number_of_digitals_descriptor_2 = let number_of_digitals_descriptor_2 = create_descriptor_with_value(
create_descriptor_with_value(&device_name_characteristic, &device_name_characteristic,
NUMBER_OF_DIGITALS_UUID.to_owned(), NUMBER_OF_DIGITALS_UUID.to_owned(),
vec![50])?; vec![50],
)?;
number_of_digitals_descriptor_2.set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?; number_of_digitals_descriptor_2.set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?;
// Characteristic User Description Descriptor // Characteristic User Description Descriptor
let _characteristic_user_description = let _characteristic_user_description = create_descriptor_with_value(
create_descriptor_with_value(&device_name_characteristic, &device_name_characteristic,
CHARACTERISTIC_USER_DESCRIPTION_UUID.to_owned(), CHARACTERISTIC_USER_DESCRIPTION_UUID.to_owned(),
HEART_RATE_DEVICE_NAME_DESCRIPTION.as_bytes().to_vec())?; HEART_RATE_DEVICE_NAME_DESCRIPTION.as_bytes().to_vec(),
)?;
// Client Characteristic Configuration descriptor // Client Characteristic Configuration descriptor
let _client_characteristic_configuration = let _client_characteristic_configuration = create_descriptor_with_value(
create_descriptor_with_value(&device_name_characteristic, &device_name_characteristic,
CLIENT_CHARACTERISTIC_CONFIGURATION_UUID.to_owned(), CLIENT_CHARACTERISTIC_CONFIGURATION_UUID.to_owned(),
vec![0])?; vec![0],
)?;
// Peripheral Privacy Flag Characteristic // Peripheral Privacy Flag Characteristic
let peripheral_privacy_flag_characteristic = let peripheral_privacy_flag_characteristic = create_characteristic(
create_characteristic(&generic_access_service, PERIPHERAL_PRIVACY_FLAG_CHARACTERISTIC_UUID.to_owned())?; &generic_access_service,
PERIPHERAL_PRIVACY_FLAG_CHARACTERISTIC_UUID.to_owned(),
)?;
peripheral_privacy_flag_characteristic peripheral_privacy_flag_characteristic
.set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?; .set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?;
Ok(generic_access_service) Ok(generic_access_service)
} }
// Create Heart Rate Device // Create Heart Rate Device
fn create_heart_rate_device(adapter: &BluetoothAdapter, fn create_heart_rate_device(
empty: bool) adapter: &BluetoothAdapter,
-> Result<BluetoothDevice, Box<Error>> { empty: bool,
) -> Result<BluetoothDevice, Box<Error>> {
// Heart Rate Device // Heart Rate Device
let heart_rate_device = let heart_rate_device = create_device_with_uuids(
create_device_with_uuids(adapter, adapter,
HEART_RATE_DEVICE_NAME.to_owned(), HEART_RATE_DEVICE_NAME.to_owned(),
HEART_RATE_DEVICE_ADDRESS.to_owned(), HEART_RATE_DEVICE_ADDRESS.to_owned(),
vec![GENERIC_ACCESS_SERVICE_UUID.to_owned(), vec![
HEART_RATE_SERVICE_UUID.to_owned()])?; GENERIC_ACCESS_SERVICE_UUID.to_owned(),
HEART_RATE_SERVICE_UUID.to_owned(),
],
)?;
if empty { if empty {
return Ok(heart_rate_device); return Ok(heart_rate_device);
@ -318,30 +356,39 @@ fn create_heart_rate_device(adapter: &BluetoothAdapter,
Ok(heart_rate_device) Ok(heart_rate_device)
} }
fn create_missing_characterisitc_heart_rate_device(adapter: &BluetoothAdapter) -> Result<(), Box<Error>> { fn create_missing_characterisitc_heart_rate_device(
adapter: &BluetoothAdapter,
) -> Result<(), Box<Error>> {
let heart_rate_device_empty = create_heart_rate_device(adapter, true)?; let heart_rate_device_empty = create_heart_rate_device(adapter, true)?;
let _generic_access_service_empty = create_generic_access_service(&heart_rate_device_empty, true)?; let _generic_access_service_empty =
create_generic_access_service(&heart_rate_device_empty, true)?;
let _heart_rate_service_empty = create_heart_rate_service(&heart_rate_device_empty, true)?; let _heart_rate_service_empty = create_heart_rate_service(&heart_rate_device_empty, true)?;
Ok(()) Ok(())
} }
fn create_missing_descriptor_heart_rate_device(adapter: &BluetoothAdapter) -> Result<(), Box<Error>> { fn create_missing_descriptor_heart_rate_device(
adapter: &BluetoothAdapter,
) -> Result<(), Box<Error>> {
let heart_rate_device_empty = create_heart_rate_device(adapter, true)?; let heart_rate_device_empty = create_heart_rate_device(adapter, true)?;
let generic_access_service_empty = create_generic_access_service(&heart_rate_device_empty, true)?; let generic_access_service_empty =
create_generic_access_service(&heart_rate_device_empty, true)?;
let _device_name_characteristic = let _device_name_characteristic = create_characteristic_with_value(
create_characteristic_with_value(&generic_access_service_empty, &generic_access_service_empty,
DEVICE_NAME_CHARACTERISTIC_UUID.to_owned(), DEVICE_NAME_CHARACTERISTIC_UUID.to_owned(),
HEART_RATE_DEVICE_NAME.as_bytes().to_vec())?; HEART_RATE_DEVICE_NAME.as_bytes().to_vec(),
)?;
let peripheral_privacy_flag_characteristic = let peripheral_privacy_flag_characteristic = create_characteristic(
create_characteristic(&generic_access_service_empty, &generic_access_service_empty,
PERIPHERAL_PRIVACY_FLAG_CHARACTERISTIC_UUID.to_owned())?; PERIPHERAL_PRIVACY_FLAG_CHARACTERISTIC_UUID.to_owned(),
peripheral_privacy_flag_characteristic.set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?; )?;
peripheral_privacy_flag_characteristic
.set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?;
let _heart_rate_service = create_heart_rate_service(&heart_rate_device_empty, false)?; let _heart_rate_service = create_heart_rate_service(&heart_rate_device_empty, false)?;
@ -351,9 +398,11 @@ fn create_missing_descriptor_heart_rate_device(adapter: &BluetoothAdapter) -> Re
fn create_two_heart_rate_services_device(adapter: &BluetoothAdapter) -> Result<(), Box<Error>> { fn create_two_heart_rate_services_device(adapter: &BluetoothAdapter) -> Result<(), Box<Error>> {
let heart_rate_device_empty = create_heart_rate_device(adapter, true)?; let heart_rate_device_empty = create_heart_rate_device(adapter, true)?;
heart_rate_device_empty.set_uuids(vec![GENERIC_ACCESS_SERVICE_UUID.to_owned(), heart_rate_device_empty.set_uuids(vec![
HEART_RATE_SERVICE_UUID.to_owned(), GENERIC_ACCESS_SERVICE_UUID.to_owned(),
HEART_RATE_SERVICE_UUID.to_owned()])?; HEART_RATE_SERVICE_UUID.to_owned(),
HEART_RATE_SERVICE_UUID.to_owned(),
])?;
let _generic_access_service = create_generic_access_service(&heart_rate_device_empty, false)?; let _generic_access_service = create_generic_access_service(&heart_rate_device_empty, false)?;
@ -361,73 +410,92 @@ fn create_two_heart_rate_services_device(adapter: &BluetoothAdapter) -> Result<(
let heart_rate_service_empty_2 = create_heart_rate_service(&heart_rate_device_empty, true)?; let heart_rate_service_empty_2 = create_heart_rate_service(&heart_rate_device_empty, true)?;
let heart_rate_measurement_characteristic = let heart_rate_measurement_characteristic = create_characteristic_with_value(
create_characteristic_with_value(&heart_rate_service_empty_1, &heart_rate_service_empty_1,
HEART_RATE_MEASUREMENT_CHARACTERISTIC_UUID.to_owned(), HEART_RATE_MEASUREMENT_CHARACTERISTIC_UUID.to_owned(),
vec![0])?; vec![0],
)?;
heart_rate_measurement_characteristic.set_flags(vec![NOTIFY_FLAG.to_string()])?; heart_rate_measurement_characteristic.set_flags(vec![NOTIFY_FLAG.to_string()])?;
let _body_sensor_location_characteristic_1 = let _body_sensor_location_characteristic_1 = create_characteristic_with_value(
create_characteristic_with_value(&heart_rate_service_empty_1, &heart_rate_service_empty_1,
BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID.to_owned(), BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID.to_owned(),
vec![49])?; vec![49],
)?;
let _body_sensor_location_characteristic_2 = let _body_sensor_location_characteristic_2 = create_characteristic_with_value(
create_characteristic_with_value(&heart_rate_service_empty_2, &heart_rate_service_empty_2,
BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID.to_owned(), BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID.to_owned(),
vec![50])?; vec![50],
)?;
Ok(()) Ok(())
} }
fn create_blocklisted_device(adapter: &BluetoothAdapter) -> Result<(), Box<Error>> { fn create_blocklisted_device(adapter: &BluetoothAdapter) -> Result<(), Box<Error>> {
let connectable_device = let connectable_device = create_device_with_uuids(
create_device_with_uuids(adapter, adapter,
CONNECTABLE_DEVICE_NAME.to_owned(), CONNECTABLE_DEVICE_NAME.to_owned(),
CONNECTABLE_DEVICE_ADDRESS.to_owned(), CONNECTABLE_DEVICE_ADDRESS.to_owned(),
vec![BLOCKLIST_TEST_SERVICE_UUID.to_owned(), vec![
DEVICE_INFORMATION_UUID.to_owned(), BLOCKLIST_TEST_SERVICE_UUID.to_owned(),
GENERIC_ACCESS_SERVICE_UUID.to_owned(), DEVICE_INFORMATION_UUID.to_owned(),
HEART_RATE_SERVICE_UUID.to_owned(), GENERIC_ACCESS_SERVICE_UUID.to_owned(),
HUMAN_INTERFACE_DEVICE_SERVICE_UUID.to_owned()])?; HEART_RATE_SERVICE_UUID.to_owned(),
HUMAN_INTERFACE_DEVICE_SERVICE_UUID.to_owned(),
],
)?;
let blocklist_test_service = create_service(&connectable_device, BLOCKLIST_TEST_SERVICE_UUID.to_owned())?; let blocklist_test_service =
create_service(&connectable_device, BLOCKLIST_TEST_SERVICE_UUID.to_owned())?;
let blocklist_exclude_reads_characteristic = let blocklist_exclude_reads_characteristic = create_characteristic(
create_characteristic(&blocklist_test_service, &blocklist_test_service,
BLOCKLIST_EXCLUDE_READS_CHARACTERISTIC_UUID.to_owned())?; BLOCKLIST_EXCLUDE_READS_CHARACTERISTIC_UUID.to_owned(),
)?;
blocklist_exclude_reads_characteristic blocklist_exclude_reads_characteristic
.set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?; .set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?;
let _blocklist_exclude_reads_descriptor = let _blocklist_exclude_reads_descriptor = create_descriptor_with_value(
create_descriptor_with_value(&blocklist_exclude_reads_characteristic, &blocklist_exclude_reads_characteristic,
BLOCKLIST_EXCLUDE_READS_DESCRIPTOR_UUID.to_owned(), BLOCKLIST_EXCLUDE_READS_DESCRIPTOR_UUID.to_owned(),
vec![54; 3])?; vec![54; 3],
)?;
let _blocklist_descriptor = let _blocklist_descriptor = create_descriptor_with_value(
create_descriptor_with_value(&blocklist_exclude_reads_characteristic, &blocklist_exclude_reads_characteristic,
BLOCKLIST_DESCRIPTOR_UUID.to_owned(), BLOCKLIST_DESCRIPTOR_UUID.to_owned(),
vec![54; 3])?; vec![54; 3],
)?;
let device_information_service = create_service(&connectable_device, DEVICE_INFORMATION_UUID.to_owned())?; let device_information_service =
create_service(&connectable_device, DEVICE_INFORMATION_UUID.to_owned())?;
let _serial_number_string_characteristic = let _serial_number_string_characteristic = create_characteristic(
create_characteristic(&device_information_service, SERIAL_NUMBER_STRING_UUID.to_owned())?; &device_information_service,
SERIAL_NUMBER_STRING_UUID.to_owned(),
)?;
let _generic_access_service = create_generic_access_service(&connectable_device, false)?; let _generic_access_service = create_generic_access_service(&connectable_device, false)?;
let _heart_rate_service = create_heart_rate_service(&connectable_device, false)?; let _heart_rate_service = create_heart_rate_service(&connectable_device, false)?;
let _human_interface_device_service = let _human_interface_device_service = create_service(
create_service(&connectable_device, HUMAN_INTERFACE_DEVICE_SERVICE_UUID.to_owned())?; &connectable_device,
HUMAN_INTERFACE_DEVICE_SERVICE_UUID.to_owned(),
)?;
Ok(()) Ok(())
} }
fn create_glucose_heart_rate_devices(adapter: &BluetoothAdapter) -> Result<(), Box<Error>> { fn create_glucose_heart_rate_devices(adapter: &BluetoothAdapter) -> Result<(), Box<Error>> {
let glucose_devie = create_device_with_uuids(adapter, let glucose_devie = create_device_with_uuids(
GLUCOSE_DEVICE_NAME.to_owned(), adapter,
GLUCOSE_DEVICE_ADDRESS.to_owned(), GLUCOSE_DEVICE_NAME.to_owned(),
vec![GLUCOSE_SERVICE_UUID.to_owned(), GLUCOSE_DEVICE_ADDRESS.to_owned(),
TX_POWER_SERVICE_UUID.to_owned()])?; vec![
GLUCOSE_SERVICE_UUID.to_owned(),
TX_POWER_SERVICE_UUID.to_owned(),
],
)?;
let heart_rate_device_empty = create_heart_rate_device(adapter, true)?; let heart_rate_device_empty = create_heart_rate_device(adapter, true)?;
@ -470,9 +538,11 @@ pub fn test(manager: &mut BluetoothManager, data_set_name: String) -> Result<(),
UNICODE_DEVICE_ADAPTER => { UNICODE_DEVICE_ADAPTER => {
set_adapter(adapter, UNICODE_DEVICE_ADAPTER.to_owned())?; set_adapter(adapter, UNICODE_DEVICE_ADAPTER.to_owned())?;
let _unicode_device = create_device(adapter, let _unicode_device = create_device(
UNICODE_DEVICE_NAME.to_owned(), adapter,
UNICODE_DEVICE_ADDRESS.to_owned())?; UNICODE_DEVICE_NAME.to_owned(),
UNICODE_DEVICE_ADDRESS.to_owned(),
)?;
}, },
MISSING_SERVICE_HEART_RATE_ADAPTER => { MISSING_SERVICE_HEART_RATE_ADAPTER => {
set_adapter(adapter, MISSING_SERVICE_HEART_RATE_ADAPTER.to_owned())?; set_adapter(adapter, MISSING_SERVICE_HEART_RATE_ADAPTER.to_owned())?;
@ -480,7 +550,10 @@ pub fn test(manager: &mut BluetoothManager, data_set_name: String) -> Result<(),
let _heart_rate_device_empty = create_heart_rate_device(adapter, true)?; let _heart_rate_device_empty = create_heart_rate_device(adapter, true)?;
}, },
MISSING_CHARACTERISTIC_HEART_RATE_ADAPTER => { MISSING_CHARACTERISTIC_HEART_RATE_ADAPTER => {
set_adapter(adapter, MISSING_CHARACTERISTIC_HEART_RATE_ADAPTER.to_owned())?; set_adapter(
adapter,
MISSING_CHARACTERISTIC_HEART_RATE_ADAPTER.to_owned(),
)?;
let _ = create_missing_characterisitc_heart_rate_device(adapter)?; let _ = create_missing_characterisitc_heart_rate_device(adapter)?;
}, },

View file

@ -10,24 +10,17 @@ use std::string::String;
const EXCLUDE_READS: &'static str = "exclude-reads"; const EXCLUDE_READS: &'static str = "exclude-reads";
const EXCLUDE_WRITES: &'static str = "exclude-writes"; const EXCLUDE_WRITES: &'static str = "exclude-writes";
const VALID_UUID_REGEX: &'static str = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"; const VALID_UUID_REGEX: &'static str =
"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
thread_local!(pub static BLUETOOTH_BLOCKLIST: RefCell<BluetoothBlocklist> = thread_local!(pub static BLUETOOTH_BLOCKLIST: RefCell<BluetoothBlocklist> =
RefCell::new(BluetoothBlocklist(parse_blocklist()))); RefCell::new(BluetoothBlocklist(parse_blocklist())));
pub fn uuid_is_blocklisted(uuid: &str, exclude_type: Blocklist) -> bool { pub fn uuid_is_blocklisted(uuid: &str, exclude_type: Blocklist) -> bool {
BLUETOOTH_BLOCKLIST.with(|blist| { BLUETOOTH_BLOCKLIST.with(|blist| match exclude_type {
match exclude_type { Blocklist::All => blist.borrow().is_blocklisted(uuid),
Blocklist::All => { Blocklist::Reads => blist.borrow().is_blocklisted_for_reads(uuid),
blist.borrow().is_blocklisted(uuid) Blocklist::Writes => blist.borrow().is_blocklisted_for_writes(uuid),
},
Blocklist::Reads => {
blist.borrow().is_blocklisted_for_reads(uuid)
}
Blocklist::Writes => {
blist.borrow().is_blocklisted_for_writes(uuid)
}
}
}) })
} }
@ -52,8 +45,9 @@ impl BluetoothBlocklist {
// https://webbluetoothcg.github.io/web-bluetooth/#blocklisted-for-reads // https://webbluetoothcg.github.io/web-bluetooth/#blocklisted-for-reads
pub fn is_blocklisted_for_reads(&self, uuid: &str) -> bool { pub fn is_blocklisted_for_reads(&self, uuid: &str) -> bool {
match self.0 { match self.0 {
Some(ref map) => map.get(uuid).map_or(false, |et| et.eq(&Blocklist::All) || Some(ref map) => map.get(uuid).map_or(false, |et| {
et.eq(&Blocklist::Reads)), et.eq(&Blocklist::All) || et.eq(&Blocklist::Reads)
}),
None => false, None => false,
} }
} }
@ -61,8 +55,9 @@ impl BluetoothBlocklist {
// https://webbluetoothcg.github.io/web-bluetooth/#blocklisted-for-writes // https://webbluetoothcg.github.io/web-bluetooth/#blocklisted-for-writes
pub fn is_blocklisted_for_writes(&self, uuid: &str) -> bool { pub fn is_blocklisted_for_writes(&self, uuid: &str) -> bool {
match self.0 { match self.0 {
Some(ref map) => map.get(uuid).map_or(false, |et| et.eq(&Blocklist::All) || Some(ref map) => map.get(uuid).map_or(false, |et| {
et.eq(&Blocklist::Writes)), et.eq(&Blocklist::All) || et.eq(&Blocklist::Writes)
}),
None => false, None => false,
} }
} }
@ -98,7 +93,7 @@ fn parse_blocklist() -> Option<HashMap<String, Blocklist>> {
exclude_type = Blocklist::Reads; exclude_type = Blocklist::Reads;
}, },
Some(EXCLUDE_WRITES) => { Some(EXCLUDE_WRITES) => {
exclude_type = Blocklist::Writes; exclude_type = Blocklist::Writes;
}, },
// Step 4.4 // Step 4.4
_ => { _ => {

View file

@ -5,7 +5,8 @@
extern crate embedder_traits; extern crate embedder_traits;
extern crate ipc_channel; extern crate ipc_channel;
extern crate regex; extern crate regex;
#[macro_use] extern crate serde; #[macro_use]
extern crate serde;
pub mod blocklist; pub mod blocklist;
pub mod scanfilter; pub mod scanfilter;
@ -83,7 +84,13 @@ pub enum BluetoothRequest {
RequestDevice(RequestDeviceoptions, IpcSender<BluetoothResponseResult>), RequestDevice(RequestDeviceoptions, IpcSender<BluetoothResponseResult>),
GATTServerConnect(String, IpcSender<BluetoothResponseResult>), GATTServerConnect(String, IpcSender<BluetoothResponseResult>),
GATTServerDisconnect(String, IpcSender<BluetoothResult<()>>), GATTServerDisconnect(String, IpcSender<BluetoothResult<()>>),
GetGATTChildren(String, Option<String>, bool, GATTType, IpcSender<BluetoothResponseResult>), GetGATTChildren(
String,
Option<String>,
bool,
GATTType,
IpcSender<BluetoothResponseResult>,
),
ReadValue(String, IpcSender<BluetoothResponseResult>), ReadValue(String, IpcSender<BluetoothResponseResult>),
WriteValue(String, Vec<u8>, IpcSender<BluetoothResponseResult>), WriteValue(String, Vec<u8>, IpcSender<BluetoothResponseResult>),
EnableNotification(String, bool, IpcSender<BluetoothResponseResult>), EnableNotification(String, bool, IpcSender<BluetoothResponseResult>),
@ -91,7 +98,11 @@ pub enum BluetoothRequest {
SetRepresentedToNull(Vec<String>, Vec<String>, Vec<String>), SetRepresentedToNull(Vec<String>, Vec<String>, Vec<String>),
IsRepresentedDeviceNull(String, IpcSender<bool>), IsRepresentedDeviceNull(String, IpcSender<bool>),
GetAvailability(IpcSender<BluetoothResponseResult>), GetAvailability(IpcSender<BluetoothResponseResult>),
MatchesFilter(String, BluetoothScanfilterSequence, IpcSender<BluetoothResult<bool>>), MatchesFilter(
String,
BluetoothScanfilterSequence,
IpcSender<BluetoothResult<bool>>,
),
Test(String, IpcSender<BluetoothResult<()>>), Test(String, IpcSender<BluetoothResult<()>>),
Exit, Exit,
} }

View file

@ -36,12 +36,13 @@ pub struct BluetoothScanfilter {
} }
impl BluetoothScanfilter { impl BluetoothScanfilter {
pub fn new(name: Option<String>, pub fn new(
name_prefix: String, name: Option<String>,
services: Vec<String>, name_prefix: String,
manufacturer_data: Option<ManufacturerData>, services: Vec<String>,
service_data: Option<ServiceData>) manufacturer_data: Option<ManufacturerData>,
-> BluetoothScanfilter { service_data: Option<ServiceData>,
) -> BluetoothScanfilter {
BluetoothScanfilter { BluetoothScanfilter {
name: name, name: name,
name_prefix: name_prefix, name_prefix: name_prefix,
@ -73,12 +74,12 @@ impl BluetoothScanfilter {
pub fn is_empty_or_invalid(&self) -> bool { pub fn is_empty_or_invalid(&self) -> bool {
(self.name.is_none() && (self.name.is_none() &&
self.name_prefix.is_empty() && self.name_prefix.is_empty() &&
self.get_services().is_empty() && self.get_services().is_empty() &&
self.manufacturer_data.is_none() && self.manufacturer_data.is_none() &&
self.service_data.is_none()) || self.service_data.is_none()) ||
self.get_name().unwrap_or("").len() > MAX_NAME_LENGTH || self.get_name().unwrap_or("").len() > MAX_NAME_LENGTH ||
self.name_prefix.len() > MAX_NAME_LENGTH self.name_prefix.len() > MAX_NAME_LENGTH
} }
} }
@ -99,7 +100,9 @@ impl BluetoothScanfilterSequence {
} }
fn get_services_set(&self) -> HashSet<String> { fn get_services_set(&self) -> HashSet<String> {
self.iter().flat_map(|filter| filter.services.get_services_set()).collect() self.iter()
.flat_map(|filter| filter.services.get_services_set())
.collect()
} }
fn is_empty(&self) -> bool { fn is_empty(&self) -> bool {
@ -114,9 +117,10 @@ pub struct RequestDeviceoptions {
} }
impl RequestDeviceoptions { impl RequestDeviceoptions {
pub fn new(filters: BluetoothScanfilterSequence, pub fn new(
services: ServiceUUIDSequence) filters: BluetoothScanfilterSequence,
-> RequestDeviceoptions { services: ServiceUUIDSequence,
) -> RequestDeviceoptions {
RequestDeviceoptions { RequestDeviceoptions {
filters: filters, filters: filters,
optional_services: services, optional_services: services,