Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / device / bluetooth / bluetooth_device_mac.mm
index 5d37a54..888ae69 100644 (file)
@@ -4,70 +4,63 @@
 
 #include "device/bluetooth/bluetooth_device_mac.h"
 
-#include <IOBluetooth/Bluetooth.h>
-#import <IOBluetooth/objc/IOBluetoothDevice.h>
-#import <IOBluetooth/objc/IOBluetoothSDPServiceRecord.h>
-#import <IOBluetooth/objc/IOBluetoothSDPUUID.h>
-
 #include <string>
 
 #include "base/basictypes.h"
+#include "base/bind.h"
 #include "base/hash.h"
+#include "base/mac/sdk_forward_declarations.h"
+#include "base/sequenced_task_runner.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
+#include "base/strings/string_util.h"
 #include "base/strings/sys_string_conversions.h"
-#include "device/bluetooth/bluetooth_out_of_band_pairing_data.h"
-#include "device/bluetooth/bluetooth_profile_mac.h"
-#include "device/bluetooth/bluetooth_service_record_mac.h"
 #include "device/bluetooth/bluetooth_socket_mac.h"
-
-// Replicate specific 10.7 SDK declarations for building with prior SDKs.
-#if !defined(MAC_OS_X_VERSION_10_7) || \
-    MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
-
-@interface IOBluetoothDevice (LionSDKDeclarations)
-- (NSString*)addressString;
-- (NSString*)name;
-- (unsigned int)classOfDevice;
-- (NSArray*)services;
+#include "device/bluetooth/bluetooth_uuid.h"
+
+// Undocumented API for accessing the Bluetooth transmit power level.
+// Similar to the API defined here [ http://goo.gl/20Q5vE ].
+@interface IOBluetoothHostController (UndocumentedAPI)
+- (IOReturn)
+    BluetoothHCIReadTransmitPowerLevel:(BluetoothConnectionHandle)connection
+                                inType:(BluetoothHCITransmitPowerLevelType)type
+                 outTransmitPowerLevel:(BluetoothHCITransmitPowerLevel*)level;
 @end
 
-#endif  // MAC_OS_X_VERSION_10_7
-
+namespace device {
 namespace {
 
-// Converts |uuid| to a IOBluetoothSDPUUID instance.
-//
-// |uuid| must be in the format of XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX.
-IOBluetoothSDPUUID* GetIOBluetoothSDPUUID(const std::string& uuid) {
-  DCHECK(uuid.size() == 36);
-  DCHECK(uuid[8] == '-');
-  DCHECK(uuid[13] == '-');
-  DCHECK(uuid[18] == '-');
-  DCHECK(uuid[23] == '-');
-  std::string numbers_only = uuid;
-  numbers_only.erase(23, 1);
-  numbers_only.erase(18, 1);
-  numbers_only.erase(13, 1);
-  numbers_only.erase(8, 1);
-  std::vector<uint8> uuid_bytes_vector;
-  base::HexStringToBytes(numbers_only, &uuid_bytes_vector);
-  DCHECK(uuid_bytes_vector.size() == 16);
-
-  return [IOBluetoothSDPUUID uuidWithBytes:&uuid_bytes_vector[0]
-                                    length:uuid_bytes_vector.size()];
+// Returns the first (should be, only) UUID contained within the
+// |service_class_data|. Returns an invalid (empty) UUID if none is found.
+BluetoothUUID ExtractUuid(IOBluetoothSDPDataElement* service_class_data) {
+  NSArray* inner_elements = [service_class_data getArrayValue];
+  IOBluetoothSDPUUID* sdp_uuid = nil;
+  for (IOBluetoothSDPDataElement* inner_element in inner_elements) {
+    if ([inner_element getTypeDescriptor] == kBluetoothSDPDataElementTypeUUID) {
+      sdp_uuid = [[inner_element getUUIDValue] getUUIDWithLength:16];
+      break;
+    }
+  }
+
+  if (!sdp_uuid)
+    return BluetoothUUID();
+
+  const uint8* uuid_bytes = reinterpret_cast<const uint8*>([sdp_uuid bytes]);
+  std::string uuid_str = base::HexEncode(uuid_bytes, 16);
+  DCHECK_EQ(uuid_str.size(), 32U);
+  uuid_str.insert(8, "-");
+  uuid_str.insert(13, "-");
+  uuid_str.insert(18, "-");
+  uuid_str.insert(23, "-");
+  return BluetoothUUID(uuid_str);
 }
 
 }  // namespace
 
-namespace device {
-
 BluetoothDeviceMac::BluetoothDeviceMac(IOBluetoothDevice* device)
-    : BluetoothDevice(), device_([device retain]) {
+    : device_([device retain]) {
 }
 
 BluetoothDeviceMac::~BluetoothDeviceMac() {
-  [device_ release];
 }
 
 uint32 BluetoothDeviceMac::GetBluetoothClass() const {
@@ -79,11 +72,10 @@ std::string BluetoothDeviceMac::GetDeviceName() const {
 }
 
 std::string BluetoothDeviceMac::GetAddress() const {
-  return base::SysNSStringToUTF8([device_ addressString]);
+  return GetDeviceAddress(device_);
 }
 
-BluetoothDevice::VendorIDSource
-BluetoothDeviceMac::GetVendorIDSource() const {
+BluetoothDevice::VendorIDSource BluetoothDeviceMac::GetVendorIDSource() const {
   return VENDOR_ID_UNKNOWN;
 }
 
@@ -99,6 +91,30 @@ uint16 BluetoothDeviceMac::GetDeviceID() const {
   return 0;
 }
 
+int BluetoothDeviceMac::GetRSSI() const {
+  if (![device_ isConnected]) {
+    NOTIMPLEMENTED();
+    return kUnknownPower;
+  }
+
+  int rssi = [device_ rawRSSI];
+
+  // The API guarantees that +127 is returned in case the RSSI is not readable:
+  // http://goo.gl/bpURYv
+  if (rssi == 127)
+    return kUnknownPower;
+
+  return rssi;
+}
+
+int BluetoothDeviceMac::GetCurrentHostTransmitPower() const {
+  return GetHostTransmitPower(kReadCurrentTransmitPowerLevel);
+}
+
+int BluetoothDeviceMac::GetMaximumHostTransmitPower() const {
+  return GetHostTransmitPower(kReadMaximumTransmitPowerLevel);
+}
+
 bool BluetoothDeviceMac::IsPaired() const {
   return [device_ isPaired];
 }
@@ -115,13 +131,18 @@ bool BluetoothDeviceMac::IsConnecting() const {
   return false;
 }
 
-// TODO(keybuk): BluetoothServiceRecord is deprecated; implement this method
-// without using BluetoothServiceRecord.
 BluetoothDevice::UUIDList BluetoothDeviceMac::GetUUIDs() const {
   UUIDList uuids;
-  for (IOBluetoothSDPServiceRecord* service in [device_ services]) {
-    BluetoothServiceRecordMac service_record(service);
-    uuids.push_back(service_record.uuid());
+  for (IOBluetoothSDPServiceRecord* service_record in [device_ services]) {
+    IOBluetoothSDPDataElement* service_class_data =
+        [service_record getAttributeDataElement:
+            kBluetoothSDPAttributeIdentifierServiceClassIDList];
+    if ([service_class_data getTypeDescriptor] ==
+            kBluetoothSDPDataElementTypeDataElementSequence) {
+      BluetoothUUID uuid = ExtractUuid(service_class_data);
+      if (uuid.IsValid())
+        uuids.push_back(uuid);
+    }
   }
   return uuids;
 }
@@ -168,9 +189,8 @@ void BluetoothDeviceMac::CancelPairing() {
   NOTIMPLEMENTED();
 }
 
-void BluetoothDeviceMac::Disconnect(
-    const base::Closure& callback,
-    const ErrorCallback& error_callback) {
+void BluetoothDeviceMac::Disconnect(const base::Closure& callback,
+                                    const ErrorCallback& error_callback) {
   NOTIMPLEMENTED();
 }
 
@@ -179,40 +199,56 @@ void BluetoothDeviceMac::Forget(const ErrorCallback& error_callback) {
 }
 
 void BluetoothDeviceMac::ConnectToService(
-    const std::string& service_uuid,
-    const SocketCallback& callback) {
-  IOBluetoothSDPServiceRecord* record =
-      [device_ getServiceRecordForUUID:GetIOBluetoothSDPUUID(service_uuid)];
-  if (record != nil) {
-    BluetoothServiceRecordMac service_record(record);
-    scoped_refptr<BluetoothSocket> socket(
-        BluetoothSocketMac::CreateBluetoothSocket(service_record));
-    if (socket.get() != NULL)
-      callback.Run(socket);
-  }
+    const BluetoothUUID& uuid,
+    const ConnectToServiceCallback& callback,
+    const ConnectToServiceErrorCallback& error_callback) {
+  scoped_refptr<BluetoothSocketMac> socket = BluetoothSocketMac::CreateSocket();
+  socket->Connect(
+      device_.get(), uuid, base::Bind(callback, socket), error_callback);
 }
 
-void BluetoothDeviceMac::ConnectToProfile(
-    device::BluetoothProfile* profile,
-    const base::Closure& callback,
-    const ErrorCallback& error_callback) {
-  if (static_cast<BluetoothProfileMac*>(profile)->Connect(device_))
-    callback.Run();
-  else
-    error_callback.Run();
+void BluetoothDeviceMac::CreateGattConnection(
+      const GattConnectionCallback& callback,
+      const ConnectErrorCallback& error_callback) {
+  // TODO(armansito): Implement.
+  error_callback.Run(ERROR_UNSUPPORTED_DEVICE);
 }
 
-void BluetoothDeviceMac::SetOutOfBandPairingData(
-    const BluetoothOutOfBandPairingData& data,
+void BluetoothDeviceMac::StartConnectionMonitor(
     const base::Closure& callback,
     const ErrorCallback& error_callback) {
   NOTIMPLEMENTED();
 }
 
-void BluetoothDeviceMac::ClearOutOfBandPairingData(
-    const base::Closure& callback,
-    const ErrorCallback& error_callback) {
-  NOTIMPLEMENTED();
+NSDate* BluetoothDeviceMac::GetLastInquiryUpdate() {
+  return [device_ getLastInquiryUpdate];
+}
+
+int BluetoothDeviceMac::GetHostTransmitPower(
+    BluetoothHCITransmitPowerLevelType power_level_type) const {
+  IOBluetoothHostController* controller =
+      [IOBluetoothHostController defaultController];
+
+  // Bail if the undocumented API is unavailable on this machine.
+  SEL selector = @selector(
+      BluetoothHCIReadTransmitPowerLevel:inType:outTransmitPowerLevel:);
+  if (![controller respondsToSelector:selector])
+    return kUnknownPower;
+
+  BluetoothHCITransmitPowerLevel power_level;
+  IOReturn result =
+      [controller BluetoothHCIReadTransmitPowerLevel:[device_ connectionHandle]
+                                              inType:power_level_type
+                               outTransmitPowerLevel:&power_level];
+  if (result != kIOReturnSuccess)
+    return kUnknownPower;
+
+  return power_level;
+}
+
+// static
+std::string BluetoothDeviceMac::GetDeviceAddress(IOBluetoothDevice* device) {
+  return CanonicalizeAddress(base::SysNSStringToUTF8([device addressString]));
 }
 
 }  // namespace device