aboutsummaryrefslogtreecommitdiffstats
path: root/third_party/blurmac/src/device.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/blurmac/src/device.rs')
-rw-r--r--third_party/blurmac/src/device.rs280
1 files changed, 280 insertions, 0 deletions
diff --git a/third_party/blurmac/src/device.rs b/third_party/blurmac/src/device.rs
new file mode 100644
index 00000000000..583eefba31d
--- /dev/null
+++ b/third_party/blurmac/src/device.rs
@@ -0,0 +1,280 @@
+// Copyright (c) 2017 Akos Kiss.
+//
+// Licensed under the BSD 3-Clause License
+// <LICENSE.md or https://opensource.org/licenses/BSD-3-Clause>.
+// This file may not be copied, modified, or distributed except
+// according to those terms.
+
+use std::collections::HashMap;
+use std::error::Error;
+use std::sync::Arc;
+
+use adapter::BluetoothAdapter;
+use delegate::{bm, bmx};
+use framework::{cb, nil, ns};
+use objc::runtime::Object;
+use utils::{cbx, nsx, wait, NOT_SUPPORTED_ERROR, NO_PERIPHERAL_FOUND};
+
+#[derive(Clone, Debug)]
+pub struct BluetoothDevice {
+ pub(crate) adapter: Arc<BluetoothAdapter>,
+ pub(crate) peripheral: *mut Object,
+}
+// TODO: implement std::fmt::Debug and/or std::fmt::Display instead of derive?
+
+impl BluetoothDevice {
+ pub fn new(adapter: Arc<BluetoothAdapter>, uuid: String) -> BluetoothDevice {
+ trace!("BluetoothDevice::new");
+ // NOTE: It can happen that there is no peripheral for the given UUID, in that case
+ // self.peripheral will be nil and all methods that return a Result will return
+ // Err(Box::from(NO_PERIPHERAL_FOUND)), while others will return some meaningless value.
+ let peripheral = Self::peripheral_by_uuid(adapter.delegate, &uuid);
+
+ if peripheral == nil {
+ warn!("BluetoothDevice::new found no peripheral for UUID {}", uuid);
+ }
+
+ BluetoothDevice {
+ adapter: adapter.clone(),
+ peripheral: peripheral,
+ }
+ }
+
+ fn peripheral_by_uuid(delegate: *mut Object, uuid: &String) -> *mut Object {
+ let peripherals = bm::delegate_peripherals(delegate);
+ let keys = ns::dictionary_allkeys(peripherals);
+ for i in 0..ns::array_count(keys) {
+ let uuid_nsstring = ns::array_objectatindex(keys, i);
+ if nsx::string_to_string(uuid_nsstring) == *uuid {
+ let data = ns::dictionary_objectforkey(peripherals, uuid_nsstring);
+ return ns::dictionary_objectforkey(
+ data,
+ nsx::string_from_str(bm::PERIPHERALDATA_PERIPHERALKEY),
+ );
+ }
+ }
+ nil
+ }
+
+ pub fn get_id(&self) -> String {
+ trace!("BluetoothDevice::get_id -> get_address");
+ self.get_address().unwrap_or(String::new())
+ }
+
+ pub fn get_address(&self) -> Result<String, Box<dyn Error>> {
+ trace!("BluetoothDevice::get_address");
+ if self.peripheral == nil {
+ return Err(Box::from(NO_PERIPHERAL_FOUND));
+ }
+
+ // NOTE: There is no better substitute for address than identifier.
+ let uuid_string =
+ nsx::string_to_string(ns::uuid_uuidstring(cb::peer_identifier(self.peripheral)));
+ debug!("BluetoothDevice::get_address -> {}", uuid_string);
+ Ok(uuid_string)
+ }
+
+ pub fn get_name(&self) -> Result<String, Box<dyn Error>> {
+ trace!("BluetoothDevice::get_name");
+ if self.peripheral == nil {
+ return Err(Box::from(NO_PERIPHERAL_FOUND));
+ }
+
+ let name_nsstring = cb::peripheral_name(self.peripheral);
+ let name = if name_nsstring != nil {
+ nsx::string_to_string(name_nsstring)
+ } else {
+ String::from("")
+ };
+ debug!("BluetoothDevice::get_name -> {}", name);
+ Ok(name)
+ }
+
+ pub fn get_uuids(&self) -> Result<Vec<String>, Box<dyn Error>> {
+ trace!("BluetoothDevice::get_uuids");
+ if self.peripheral == nil {
+ return Err(Box::from(NO_PERIPHERAL_FOUND));
+ }
+
+ let data = bmx::peripheraldata(self.adapter.delegate, self.peripheral)?;
+ let mut v = vec![];
+ let cbuuids_nsarray =
+ ns::dictionary_objectforkey(data, nsx::string_from_str(bm::PERIPHERALDATA_UUIDSKEY));
+ if cbuuids_nsarray != nil {
+ for i in 0..ns::array_count(cbuuids_nsarray) {
+ v.push(cbx::uuid_to_canonical_uuid_string(ns::array_objectatindex(
+ cbuuids_nsarray,
+ i,
+ )));
+ }
+ }
+ debug!("BluetoothDevice::get_uuids -> {:?}", v);
+ Ok(v)
+ }
+
+ pub fn connect(&self) -> Result<(), Box<dyn Error>> {
+ trace!("BluetoothDevice::connect");
+ if self.peripheral == nil {
+ return Err(Box::from(NO_PERIPHERAL_FOUND));
+ }
+
+ cb::centralmanager_connectperipheral(self.adapter.manager, self.peripheral);
+ Ok(())
+ }
+
+ pub fn disconnect(&self) -> Result<(), Box<dyn Error>> {
+ trace!("BluetoothDevice::disconnect");
+ if self.peripheral == nil {
+ return Err(Box::from(NO_PERIPHERAL_FOUND));
+ }
+
+ cb::centralmanager_cancelperipheralconnection(self.adapter.manager, self.peripheral);
+ Ok(())
+ }
+
+ pub fn is_connected(&self) -> Result<bool, Box<dyn Error>> {
+ trace!("BluetoothDevice::is_connected");
+ if self.peripheral == nil {
+ return Err(Box::from(NO_PERIPHERAL_FOUND));
+ }
+
+ let state = cb::peripheral_state(self.peripheral);
+ debug!("BluetoothDevice::is_connected -> {}", state);
+ Ok(state == cb::PERIPHERALSTATE_CONNECTED)
+ }
+
+ pub fn get_gatt_services(&self) -> Result<Vec<String>, Box<dyn Error>> {
+ trace!("BluetoothDevice::get_gatt_services");
+ if self.peripheral == nil {
+ return Err(Box::from(NO_PERIPHERAL_FOUND));
+ }
+
+ let events = bmx::peripheralevents(self.adapter.delegate, self.peripheral)?;
+ let key = nsx::string_from_str(bm::PERIPHERALEVENT_SERVICESDISCOVEREDKEY);
+ wait::wait_or_timeout(|| ns::dictionary_objectforkey(events, key) != nil)?;
+
+ let mut v = vec![];
+ let services = cb::peripheral_services(self.peripheral);
+ for i in 0..ns::array_count(services) {
+ let uuid_string = cbx::uuid_to_canonical_uuid_string(cb::attribute_uuid(
+ ns::array_objectatindex(services, i),
+ ));
+ v.push(uuid_string);
+ }
+ debug!("BluetoothDevice::get_gatt_services -> {:?}", v);
+ Ok(v)
+ }
+
+ // Not supported
+
+ pub fn get_rssi(&self) -> Result<i16, Box<dyn Error>> {
+ warn!("BluetoothDevice::get_rssi not supported by BlurMac");
+ // TODO: Now available from peripheral data in BluetoothAdapter.
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_tx_power(&self) -> Result<i16, Box<dyn Error>> {
+ warn!("BluetoothDevice::get_tx_power not supported by BlurMac");
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_manufacturer_data(&self) -> Result<HashMap<u16, Vec<u8>>, Box<dyn Error>> {
+ warn!("BluetoothDevice::get_manufacturer_data not supported by BlurMac");
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_service_data(&self) -> Result<HashMap<String, Vec<u8>>, Box<dyn Error>> {
+ warn!("BluetoothDevice::get_service_data not supported by BlurMac");
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_icon(&self) -> Result<String, Box<dyn Error>> {
+ warn!("BluetoothDevice::get_icon not supported by BlurMac");
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_class(&self) -> Result<u32, Box<dyn Error>> {
+ warn!("BluetoothDevice::get_class not supported by BlurMac");
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_appearance(&self) -> Result<u16, Box<dyn Error>> {
+ warn!("BluetoothDevice::get_appearance not supported by BlurMac");
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn is_paired(&self) -> Result<bool, Box<dyn Error>> {
+ warn!("BluetoothDevice::is_paired not supported by BlurMac");
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn is_trusted(&self) -> Result<bool, Box<dyn Error>> {
+ warn!("BluetoothDevice::is_trusted not supported by BlurMac");
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn is_blocked(&self) -> Result<bool, Box<dyn Error>> {
+ warn!("BluetoothDevice::is_blocked not supported by BlurMac");
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_alias(&self) -> Result<String, Box<dyn Error>> {
+ warn!("BluetoothDevice::get_alias not supported by BlurMac");
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn set_alias(&self, _value: String) -> Result<(), Box<dyn Error>> {
+ warn!("BluetoothDevice::set_alias not supported by BlurMac");
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn is_legacy_pairing(&self) -> Result<bool, Box<dyn Error>> {
+ warn!("BluetoothDevice::is_legacy_pairing not supported by BlurMac");
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_vendor_id_source(&self) -> Result<String, Box<dyn Error>> {
+ warn!("BluetoothDevice::get_vendor_id_source not supported by BlurMac");
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_vendor_id(&self) -> Result<u32, Box<dyn Error>> {
+ warn!("BluetoothDevice::get_vendor_id not supported by BlurMac");
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_product_id(&self) -> Result<u32, Box<dyn Error>> {
+ warn!("BluetoothDevice::get_product_id not supported by BlurMac");
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_device_id(&self) -> Result<u32, Box<dyn Error>> {
+ warn!("BluetoothDevice::get_device_id not supported by BlurMac");
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn get_modalias(&self) -> Result<(String, u32, u32, u32), Box<dyn Error>> {
+ warn!("BluetoothDevice::get_modalias not supported by BlurMac");
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn connect_profile(&self, _uuid: String) -> Result<(), Box<dyn Error>> {
+ warn!("BluetoothDevice::connect_profile not supported by BlurMac");
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn disconnect_profile(&self, _uuid: String) -> Result<(), Box<dyn Error>> {
+ warn!("BluetoothDevice::disconnect_profile not supported by BlurMac");
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn pair(&self) -> Result<(), Box<dyn Error>> {
+ warn!("BluetoothDevice::pair not supported by BlurMac");
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+
+ pub fn cancel_pairing(&self) -> Result<(), Box<dyn Error>> {
+ warn!("BluetoothDevice::cancel_pairing not supported by BlurMac");
+ Err(Box::from(NOT_SUPPORTED_ERROR))
+ }
+}