| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "device/bluetooth/bluetooth_device_mac.h" | |
| 6 | |
| 7 #include <string> | |
| 8 | |
| 9 #include "base/basictypes.h" | |
| 10 #include "base/bind.h" | |
| 11 #include "base/hash.h" | |
| 12 #include "base/mac/sdk_forward_declarations.h" | |
| 13 #include "base/sequenced_task_runner.h" | |
| 14 #include "base/strings/string_number_conversions.h" | |
| 15 #include "base/strings/string_util.h" | |
| 16 #include "base/strings/sys_string_conversions.h" | |
| 17 #include "device/bluetooth/bluetooth_socket_mac.h" | |
| 18 #include "device/bluetooth/bluetooth_uuid.h" | |
| 19 | |
| 20 // Undocumented API for accessing the Bluetooth transmit power level. | |
| 21 // Similar to the API defined here [ http://goo.gl/20Q5vE ]. | |
| 22 @interface IOBluetoothHostController (UndocumentedAPI) | |
| 23 - (IOReturn) | |
| 24 BluetoothHCIReadTransmitPowerLevel:(BluetoothConnectionHandle)connection | |
| 25 inType:(BluetoothHCITransmitPowerLevelType)type | |
| 26 outTransmitPowerLevel:(BluetoothHCITransmitPowerLevel*)level; | |
| 27 @end | |
| 28 | |
| 29 namespace device { | |
| 30 namespace { | |
| 31 | |
| 32 const char kApiUnavailable[] = "This API is not implemented on this platform."; | |
| 33 | |
| 34 // Returns the first (should be, only) UUID contained within the | |
| 35 // |service_class_data|. Returns an invalid (empty) UUID if none is found. | |
| 36 BluetoothUUID ExtractUuid(IOBluetoothSDPDataElement* service_class_data) { | |
| 37 NSArray* inner_elements = [service_class_data getArrayValue]; | |
| 38 IOBluetoothSDPUUID* sdp_uuid = nil; | |
| 39 for (IOBluetoothSDPDataElement* inner_element in inner_elements) { | |
| 40 if ([inner_element getTypeDescriptor] == kBluetoothSDPDataElementTypeUUID) { | |
| 41 sdp_uuid = [[inner_element getUUIDValue] getUUIDWithLength:16]; | |
| 42 break; | |
| 43 } | |
| 44 } | |
| 45 | |
| 46 if (!sdp_uuid) | |
| 47 return BluetoothUUID(); | |
| 48 | |
| 49 const uint8* uuid_bytes = reinterpret_cast<const uint8*>([sdp_uuid bytes]); | |
| 50 std::string uuid_str = base::HexEncode(uuid_bytes, 16); | |
| 51 DCHECK_EQ(uuid_str.size(), 32U); | |
| 52 uuid_str.insert(8, "-"); | |
| 53 uuid_str.insert(13, "-"); | |
| 54 uuid_str.insert(18, "-"); | |
| 55 uuid_str.insert(23, "-"); | |
| 56 return BluetoothUUID(uuid_str); | |
| 57 } | |
| 58 | |
| 59 } // namespace | |
| 60 | |
| 61 BluetoothDeviceMac::BluetoothDeviceMac(IOBluetoothDevice* device) | |
| 62 : device_([device retain]) { | |
| 63 } | |
| 64 | |
| 65 BluetoothDeviceMac::~BluetoothDeviceMac() { | |
| 66 } | |
| 67 | |
| 68 uint32 BluetoothDeviceMac::GetBluetoothClass() const { | |
| 69 return [device_ classOfDevice]; | |
| 70 } | |
| 71 | |
| 72 std::string BluetoothDeviceMac::GetDeviceName() const { | |
| 73 return base::SysNSStringToUTF8([device_ name]); | |
| 74 } | |
| 75 | |
| 76 std::string BluetoothDeviceMac::GetAddress() const { | |
| 77 return GetDeviceAddress(device_); | |
| 78 } | |
| 79 | |
| 80 BluetoothDevice::VendorIDSource BluetoothDeviceMac::GetVendorIDSource() const { | |
| 81 return VENDOR_ID_UNKNOWN; | |
| 82 } | |
| 83 | |
| 84 uint16 BluetoothDeviceMac::GetVendorID() const { | |
| 85 return 0; | |
| 86 } | |
| 87 | |
| 88 uint16 BluetoothDeviceMac::GetProductID() const { | |
| 89 return 0; | |
| 90 } | |
| 91 | |
| 92 uint16 BluetoothDeviceMac::GetDeviceID() const { | |
| 93 return 0; | |
| 94 } | |
| 95 | |
| 96 bool BluetoothDeviceMac::IsPaired() const { | |
| 97 return [device_ isPaired]; | |
| 98 } | |
| 99 | |
| 100 bool BluetoothDeviceMac::IsConnected() const { | |
| 101 return [device_ isConnected]; | |
| 102 } | |
| 103 | |
| 104 bool BluetoothDeviceMac::IsConnectable() const { | |
| 105 return false; | |
| 106 } | |
| 107 | |
| 108 bool BluetoothDeviceMac::IsConnecting() const { | |
| 109 return false; | |
| 110 } | |
| 111 | |
| 112 BluetoothDevice::UUIDList BluetoothDeviceMac::GetUUIDs() const { | |
| 113 UUIDList uuids; | |
| 114 for (IOBluetoothSDPServiceRecord* service_record in [device_ services]) { | |
| 115 IOBluetoothSDPDataElement* service_class_data = | |
| 116 [service_record getAttributeDataElement: | |
| 117 kBluetoothSDPAttributeIdentifierServiceClassIDList]; | |
| 118 if ([service_class_data getTypeDescriptor] == | |
| 119 kBluetoothSDPDataElementTypeDataElementSequence) { | |
| 120 BluetoothUUID uuid = ExtractUuid(service_class_data); | |
| 121 if (uuid.IsValid()) | |
| 122 uuids.push_back(uuid); | |
| 123 } | |
| 124 } | |
| 125 return uuids; | |
| 126 } | |
| 127 | |
| 128 int16 BluetoothDeviceMac::GetInquiryRSSI() const { | |
| 129 return kUnknownPower; | |
| 130 } | |
| 131 | |
| 132 int16 BluetoothDeviceMac::GetInquiryTxPower() const { | |
| 133 NOTIMPLEMENTED(); | |
| 134 return kUnknownPower; | |
| 135 } | |
| 136 | |
| 137 bool BluetoothDeviceMac::ExpectingPinCode() const { | |
| 138 NOTIMPLEMENTED(); | |
| 139 return false; | |
| 140 } | |
| 141 | |
| 142 bool BluetoothDeviceMac::ExpectingPasskey() const { | |
| 143 NOTIMPLEMENTED(); | |
| 144 return false; | |
| 145 } | |
| 146 | |
| 147 bool BluetoothDeviceMac::ExpectingConfirmation() const { | |
| 148 NOTIMPLEMENTED(); | |
| 149 return false; | |
| 150 } | |
| 151 | |
| 152 void BluetoothDeviceMac::GetConnectionInfo( | |
| 153 const ConnectionInfoCallback& callback) { | |
| 154 ConnectionInfo connection_info; | |
| 155 if (![device_ isConnected]) { | |
| 156 callback.Run(connection_info); | |
| 157 return; | |
| 158 } | |
| 159 | |
| 160 connection_info.rssi = [device_ rawRSSI]; | |
| 161 // The API guarantees that +127 is returned in case the RSSI is not readable: | |
| 162 // http://goo.gl/bpURYv | |
| 163 if (connection_info.rssi == 127) | |
| 164 connection_info.rssi = kUnknownPower; | |
| 165 | |
| 166 connection_info.transmit_power = | |
| 167 GetHostTransmitPower(kReadCurrentTransmitPowerLevel); | |
| 168 connection_info.max_transmit_power = | |
| 169 GetHostTransmitPower(kReadMaximumTransmitPowerLevel); | |
| 170 | |
| 171 callback.Run(connection_info); | |
| 172 } | |
| 173 | |
| 174 void BluetoothDeviceMac::Connect( | |
| 175 PairingDelegate* pairing_delegate, | |
| 176 const base::Closure& callback, | |
| 177 const ConnectErrorCallback& error_callback) { | |
| 178 NOTIMPLEMENTED(); | |
| 179 } | |
| 180 | |
| 181 void BluetoothDeviceMac::SetPinCode(const std::string& pincode) { | |
| 182 NOTIMPLEMENTED(); | |
| 183 } | |
| 184 | |
| 185 void BluetoothDeviceMac::SetPasskey(uint32 passkey) { | |
| 186 NOTIMPLEMENTED(); | |
| 187 } | |
| 188 | |
| 189 void BluetoothDeviceMac::ConfirmPairing() { | |
| 190 NOTIMPLEMENTED(); | |
| 191 } | |
| 192 | |
| 193 void BluetoothDeviceMac::RejectPairing() { | |
| 194 NOTIMPLEMENTED(); | |
| 195 } | |
| 196 | |
| 197 void BluetoothDeviceMac::CancelPairing() { | |
| 198 NOTIMPLEMENTED(); | |
| 199 } | |
| 200 | |
| 201 void BluetoothDeviceMac::Disconnect(const base::Closure& callback, | |
| 202 const ErrorCallback& error_callback) { | |
| 203 NOTIMPLEMENTED(); | |
| 204 } | |
| 205 | |
| 206 void BluetoothDeviceMac::Forget(const ErrorCallback& error_callback) { | |
| 207 NOTIMPLEMENTED(); | |
| 208 } | |
| 209 | |
| 210 void BluetoothDeviceMac::ConnectToService( | |
| 211 const BluetoothUUID& uuid, | |
| 212 const ConnectToServiceCallback& callback, | |
| 213 const ConnectToServiceErrorCallback& error_callback) { | |
| 214 scoped_refptr<BluetoothSocketMac> socket = BluetoothSocketMac::CreateSocket(); | |
| 215 socket->Connect( | |
| 216 device_.get(), uuid, base::Bind(callback, socket), error_callback); | |
| 217 } | |
| 218 | |
| 219 void BluetoothDeviceMac::ConnectToServiceInsecurely( | |
| 220 const BluetoothUUID& uuid, | |
| 221 const ConnectToServiceCallback& callback, | |
| 222 const ConnectToServiceErrorCallback& error_callback) { | |
| 223 error_callback.Run(kApiUnavailable); | |
| 224 } | |
| 225 | |
| 226 void BluetoothDeviceMac::CreateGattConnection( | |
| 227 const GattConnectionCallback& callback, | |
| 228 const ConnectErrorCallback& error_callback) { | |
| 229 // TODO(armansito): Implement. | |
| 230 error_callback.Run(ERROR_UNSUPPORTED_DEVICE); | |
| 231 } | |
| 232 | |
| 233 NSDate* BluetoothDeviceMac::GetLastInquiryUpdate() { | |
| 234 return [device_ getLastInquiryUpdate]; | |
| 235 } | |
| 236 | |
| 237 int BluetoothDeviceMac::GetHostTransmitPower( | |
| 238 BluetoothHCITransmitPowerLevelType power_level_type) const { | |
| 239 IOBluetoothHostController* controller = | |
| 240 [IOBluetoothHostController defaultController]; | |
| 241 | |
| 242 // Bail if the undocumented API is unavailable on this machine. | |
| 243 SEL selector = @selector( | |
| 244 BluetoothHCIReadTransmitPowerLevel:inType:outTransmitPowerLevel:); | |
| 245 if (![controller respondsToSelector:selector]) | |
| 246 return kUnknownPower; | |
| 247 | |
| 248 BluetoothHCITransmitPowerLevel power_level; | |
| 249 IOReturn result = | |
| 250 [controller BluetoothHCIReadTransmitPowerLevel:[device_ connectionHandle] | |
| 251 inType:power_level_type | |
| 252 outTransmitPowerLevel:&power_level]; | |
| 253 if (result != kIOReturnSuccess) | |
| 254 return kUnknownPower; | |
| 255 | |
| 256 return power_level; | |
| 257 } | |
| 258 | |
| 259 // static | |
| 260 std::string BluetoothDeviceMac::GetDeviceAddress(IOBluetoothDevice* device) { | |
| 261 return CanonicalizeAddress(base::SysNSStringToUTF8([device addressString])); | |
| 262 } | |
| 263 | |
| 264 } // namespace device | |
| OLD | NEW |