Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "device/bluetooth/bluetooth_low_energy_device_mac.h" | 5 #include "device/bluetooth/bluetooth_low_energy_device_mac.h" |
| 6 | 6 |
| 7 #import <CoreFoundation/CoreFoundation.h> | 7 #import <CoreFoundation/CoreFoundation.h> |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 | 9 |
| 10 #include "base/mac/mac_util.h" | 10 #include "base/mac/mac_util.h" |
| 11 #include "base/mac/scoped_cftyperef.h" | 11 #include "base/mac/scoped_cftyperef.h" |
| 12 #include "base/mac/sdk_forward_declarations.h" | 12 #include "base/mac/sdk_forward_declarations.h" |
| 13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 14 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
| 15 #include "base/strings/sys_string_conversions.h" | 15 #include "base/strings/sys_string_conversions.h" |
| 16 #include "device/bluetooth/bluetooth_adapter_mac.h" | 16 #include "device/bluetooth/bluetooth_adapter_mac.h" |
| 17 #include "device/bluetooth/bluetooth_device.h" | 17 #include "device/bluetooth/bluetooth_device.h" |
| 18 #include "device/bluetooth/bluetooth_low_energy_peripheral_delegate.h" | 18 #include "device/bluetooth/bluetooth_low_energy_peripheral_delegate.h" |
| 19 #include "device/bluetooth/bluetooth_remote_gatt_service_mac.h" | 19 #include "device/bluetooth/bluetooth_remote_gatt_service_mac.h" |
| 20 | 20 |
| 21 using device::BluetoothDevice; | 21 using device::BluetoothDevice; |
| 22 using device::BluetoothLowEnergyDeviceMac; | 22 using device::BluetoothLowEnergyDeviceMac; |
| 23 | 23 |
| 24 BluetoothLowEnergyDeviceMac::BluetoothLowEnergyDeviceMac( | 24 BluetoothLowEnergyDeviceMac::BluetoothLowEnergyDeviceMac( |
| 25 BluetoothAdapterMac* adapter, | 25 BluetoothAdapterMac* adapter, |
| 26 CBPeripheral* peripheral) | 26 CBPeripheral* peripheral) |
| 27 : BluetoothDeviceMac(adapter), | 27 : BluetoothDeviceMac(adapter), |
| 28 peripheral_(peripheral, base::scoped_policy::RETAIN) { | 28 peripheral_(peripheral, base::scoped_policy::RETAIN), |
| 29 discovery_pending_count_(0) { | |
| 29 DCHECK(BluetoothAdapterMac::IsLowEnergyAvailable()); | 30 DCHECK(BluetoothAdapterMac::IsLowEnergyAvailable()); |
| 30 DCHECK(peripheral_.get()); | 31 DCHECK(peripheral_.get()); |
| 31 peripheral_delegate_.reset([[BluetoothLowEnergyPeripheralDelegate alloc] | 32 peripheral_delegate_.reset([[BluetoothLowEnergyPeripheralDelegate alloc] |
| 32 initWithBluetoothLowEnergyDeviceMac:this]); | 33 initWithBluetoothLowEnergyDeviceMac:this]); |
| 33 [peripheral_ setDelegate:peripheral_delegate_]; | 34 [peripheral_ setDelegate:peripheral_delegate_]; |
| 34 identifier_ = GetPeripheralIdentifier(peripheral); | 35 identifier_ = GetPeripheralIdentifier(peripheral); |
| 35 hash_address_ = GetPeripheralHashAddress(peripheral); | 36 hash_address_ = GetPeripheralHashAddress(peripheral); |
| 36 UpdateTimestamp(); | 37 UpdateTimestamp(); |
| 37 } | 38 } |
| 38 | 39 |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 177 if (!IsGattConnected()) { | 178 if (!IsGattConnected()) { |
| 178 GetMacAdapter()->CreateGattConnection(this); | 179 GetMacAdapter()->CreateGattConnection(this); |
| 179 } | 180 } |
| 180 } | 181 } |
| 181 | 182 |
| 182 void BluetoothLowEnergyDeviceMac::DisconnectGatt() { | 183 void BluetoothLowEnergyDeviceMac::DisconnectGatt() { |
| 183 GetMacAdapter()->DisconnectGatt(this); | 184 GetMacAdapter()->DisconnectGatt(this); |
| 184 } | 185 } |
| 185 | 186 |
| 186 void BluetoothLowEnergyDeviceMac::DidDiscoverPrimaryServices(NSError* error) { | 187 void BluetoothLowEnergyDeviceMac::DidDiscoverPrimaryServices(NSError* error) { |
| 188 --discovery_pending_count_; | |
| 189 if (discovery_pending_count_ < 0) { | |
| 190 // This should never happens, just in case it happens with a device, | |
| 191 // discovery_pending_count_ is set back to 0. | |
| 192 VLOG(1) << GetName()->c_str() | |
| 193 << ": BluetoothLowEnergyDeviceMac::discovery_pending_count_ " | |
| 194 << discovery_pending_count_; | |
| 195 discovery_pending_count_ = 0; | |
|
ortuno
2017/02/28 02:06:50
I think just return. I don't think we want to star
jlebel
2017/02/28 23:16:18
ok.
| |
| 196 } | |
| 187 if (error) { | 197 if (error) { |
| 188 // TODO(http://crbug.com/609320): Need to pass the error. | 198 // TODO(http://crbug.com/609320): Need to pass the error. |
| 189 // TODO(http://crbug.com/609844): Decide what to do if discover failed | 199 // TODO(http://crbug.com/609844): Decide what to do if discover failed |
| 190 // a device services. | 200 // a device services. |
| 191 VLOG(1) << "Can't discover primary services: " | 201 VLOG(1) << "Can't discover primary services: " |
| 192 << error.localizedDescription.UTF8String << " (" << error.domain | 202 << error.localizedDescription.UTF8String << " (" << error.domain |
| 193 << ": " << error.code << ")"; | 203 << ": " << error.code << ")"; |
| 194 return; | 204 return; |
| 195 } | 205 } |
| 196 VLOG(1) << "DidDiscoverPrimaryServices."; | 206 VLOG(1) << "DidDiscoverPrimaryServices, pending count: " |
| 207 << discovery_pending_count_; | |
| 197 | 208 |
| 198 if (!IsGattConnected()) { | 209 if (!IsGattConnected()) { |
| 199 // Don't create services if the device disconnected. | 210 // Don't create services if the device disconnected. |
| 200 return; | 211 return; |
| 201 } | 212 } |
| 202 | 213 |
| 203 for (CBService* cb_service in GetPeripheral().services) { | 214 for (CBService* cb_service in GetPeripheral().services) { |
| 204 BluetoothRemoteGattServiceMac* gatt_service = | 215 BluetoothRemoteGattServiceMac* gatt_service = |
| 205 GetBluetoothRemoteGattService(cb_service); | 216 GetBluetoothRemoteGattService(cb_service); |
| 206 if (!gatt_service) { | 217 if (!gatt_service) { |
| 207 gatt_service = new BluetoothRemoteGattServiceMac(this, cb_service, | 218 gatt_service = new BluetoothRemoteGattServiceMac(this, cb_service, |
| 208 true /* is_primary */); | 219 true /* is_primary */); |
| 209 auto result_iter = gatt_services_.insert(std::make_pair( | 220 auto result_iter = gatt_services_.insert(std::make_pair( |
| 210 gatt_service->GetIdentifier(), base::WrapUnique(gatt_service))); | 221 gatt_service->GetIdentifier(), base::WrapUnique(gatt_service))); |
| 211 DCHECK(result_iter.second); | 222 DCHECK(result_iter.second); |
| 212 adapter_->NotifyGattServiceAdded(gatt_service); | 223 adapter_->NotifyGattServiceAdded(gatt_service); |
| 213 } | 224 } |
| 214 } | 225 } |
| 215 for (auto it = gatt_services_.begin(); it != gatt_services_.end(); ++it) { | 226 if (discovery_pending_count_ == 0) { |
| 216 device::BluetoothRemoteGattService* gatt_service = it->second.get(); | 227 for (auto it = gatt_services_.begin(); it != gatt_services_.end(); ++it) { |
| 217 device::BluetoothRemoteGattServiceMac* gatt_service_mac = | 228 device::BluetoothRemoteGattService* gatt_service = it->second.get(); |
| 218 static_cast<BluetoothRemoteGattServiceMac*>(gatt_service); | 229 device::BluetoothRemoteGattServiceMac* gatt_service_mac = |
| 219 gatt_service_mac->DiscoverCharacteristics(); | 230 static_cast<BluetoothRemoteGattServiceMac*>(gatt_service); |
| 231 gatt_service_mac->DiscoverCharacteristics(); | |
| 232 } | |
| 233 SendNotificationIfDiscoveryComplete(); | |
| 220 } | 234 } |
| 221 } | 235 } |
| 222 | 236 |
| 223 void BluetoothLowEnergyDeviceMac::DidDiscoverCharacteristics( | 237 void BluetoothLowEnergyDeviceMac::DidDiscoverCharacteristics( |
| 224 CBService* cb_service, | 238 CBService* cb_service, |
| 225 NSError* error) { | 239 NSError* error) { |
| 226 if (error) { | 240 if (error) { |
| 227 // TODO(http://crbug.com/609320): Need to pass the error. | 241 // TODO(http://crbug.com/609320): Need to pass the error. |
| 228 // TODO(http://crbug.com/609844): Decide what to do if discover failed | 242 // TODO(http://crbug.com/609844): Decide what to do if discover failed |
| 229 VLOG(1) << "Can't discover characteristics: " | 243 VLOG(1) << "Can't discover characteristics: " |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 254 DCHECK(gatt_service); | 268 DCHECK(gatt_service); |
| 255 VLOG(1) << gatt_service->GetUUID().canonical_value(); | 269 VLOG(1) << gatt_service->GetUUID().canonical_value(); |
| 256 std::unique_ptr<BluetoothRemoteGattService> scoped_service = | 270 std::unique_ptr<BluetoothRemoteGattService> scoped_service = |
| 257 std::move(gatt_services_[gatt_service->GetIdentifier()]); | 271 std::move(gatt_services_[gatt_service->GetIdentifier()]); |
| 258 gatt_services_.erase(gatt_service->GetIdentifier()); | 272 gatt_services_.erase(gatt_service->GetIdentifier()); |
| 259 adapter_->NotifyGattServiceRemoved(scoped_service.get()); | 273 adapter_->NotifyGattServiceRemoved(scoped_service.get()); |
| 260 } | 274 } |
| 261 device_uuids_.ClearServiceUUIDs(); | 275 device_uuids_.ClearServiceUUIDs(); |
| 262 SetGattServicesDiscoveryComplete(false); | 276 SetGattServicesDiscoveryComplete(false); |
| 263 adapter_->NotifyDeviceChanged(this); | 277 adapter_->NotifyDeviceChanged(this); |
| 264 [GetPeripheral() discoverServices:nil]; | 278 DiscoverPrimaryServices(); |
| 265 } | 279 } |
| 266 | 280 |
| 267 void BluetoothLowEnergyDeviceMac::DidUpdateValue( | 281 void BluetoothLowEnergyDeviceMac::DidUpdateValue( |
| 268 CBCharacteristic* characteristic, | 282 CBCharacteristic* characteristic, |
| 269 NSError* error) { | 283 NSError* error) { |
| 270 VLOG(1) << "DidUpdateValue."; | 284 VLOG(1) << "DidUpdateValue."; |
| 271 BluetoothRemoteGattServiceMac* gatt_service = | 285 BluetoothRemoteGattServiceMac* gatt_service = |
| 272 GetBluetoothRemoteGattService(characteristic.service); | 286 GetBluetoothRemoteGattService(characteristic.service); |
| 273 DCHECK(gatt_service); | 287 DCHECK(gatt_service); |
| 274 gatt_service->DidUpdateValue(characteristic, error); | 288 gatt_service->DidUpdateValue(characteristic, error); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 330 std::string BluetoothLowEnergyDeviceMac::GetPeripheralHashAddress( | 344 std::string BluetoothLowEnergyDeviceMac::GetPeripheralHashAddress( |
| 331 CBPeripheral* peripheral) { | 345 CBPeripheral* peripheral) { |
| 332 const size_t kCanonicalAddressNumberOfBytes = 6; | 346 const size_t kCanonicalAddressNumberOfBytes = 6; |
| 333 char raw[kCanonicalAddressNumberOfBytes]; | 347 char raw[kCanonicalAddressNumberOfBytes]; |
| 334 crypto::SHA256HashString(GetPeripheralIdentifier(peripheral), raw, | 348 crypto::SHA256HashString(GetPeripheralIdentifier(peripheral), raw, |
| 335 sizeof(raw)); | 349 sizeof(raw)); |
| 336 std::string hash = base::HexEncode(raw, sizeof(raw)); | 350 std::string hash = base::HexEncode(raw, sizeof(raw)); |
| 337 return BluetoothDevice::CanonicalizeAddress(hash); | 351 return BluetoothDevice::CanonicalizeAddress(hash); |
| 338 } | 352 } |
| 339 | 353 |
| 354 void BluetoothLowEnergyDeviceMac::DiscoverPrimaryServices() { | |
| 355 VLOG(1) << "DidDiscoverDescriptors pending count" << discovery_pending_count_; | |
| 356 ++discovery_pending_count_; | |
| 357 [GetPeripheral() discoverServices:nil]; | |
| 358 } | |
| 359 | |
| 340 void BluetoothLowEnergyDeviceMac::SendNotificationIfDiscoveryComplete() { | 360 void BluetoothLowEnergyDeviceMac::SendNotificationIfDiscoveryComplete() { |
| 341 // Notify when all services have been discovered. | 361 // Notify when all services have been discovered. |
| 342 bool discovery_complete = | 362 bool discovery_complete = |
| 363 discovery_pending_count_ == 0 && | |
| 343 std::find_if_not( | 364 std::find_if_not( |
| 344 gatt_services_.begin(), gatt_services_.end(), | 365 gatt_services_.begin(), |
| 345 [](GattServiceMap::value_type& pair) { | 366 gatt_services_.end(), [](GattServiceMap::value_type & pair) { |
| 346 BluetoothRemoteGattService* gatt_service = pair.second.get(); | 367 BluetoothRemoteGattService* gatt_service = pair.second.get(); |
| 347 return static_cast<BluetoothRemoteGattServiceMac*>(gatt_service) | 368 return static_cast<BluetoothRemoteGattServiceMac*>(gatt_service) |
| 348 ->IsDiscoveryComplete(); | 369 ->IsDiscoveryComplete(); |
| 349 }) == gatt_services_.end(); | 370 }) == gatt_services_.end(); |
| 350 if (discovery_complete) { | 371 if (discovery_complete) { |
| 351 device_uuids_.ReplaceServiceUUIDs(gatt_services_); | 372 device_uuids_.ReplaceServiceUUIDs(gatt_services_); |
| 352 SetGattServicesDiscoveryComplete(true); | 373 SetGattServicesDiscoveryComplete(true); |
| 353 adapter_->NotifyGattServicesDiscovered(this); | 374 adapter_->NotifyGattServicesDiscovered(this); |
| 354 adapter_->NotifyDeviceChanged(this); | 375 adapter_->NotifyDeviceChanged(this); |
| 355 } | 376 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 390 // 2. When we cancel a pending connection request. | 411 // 2. When we cancel a pending connection request. |
| 391 if (create_gatt_connection_error_callbacks_.empty()) { | 412 if (create_gatt_connection_error_callbacks_.empty()) { |
| 392 // If there are no pending callbacks then the connection broke (#1). | 413 // If there are no pending callbacks then the connection broke (#1). |
| 393 DidDisconnectGatt(true /* notifyDeviceChanged */); | 414 DidDisconnectGatt(true /* notifyDeviceChanged */); |
| 394 return; | 415 return; |
| 395 } | 416 } |
| 396 // Else we canceled the connection request (#2). | 417 // Else we canceled the connection request (#2). |
| 397 // TODO(http://crbug.com/585897): Need to pass the error. | 418 // TODO(http://crbug.com/585897): Need to pass the error. |
| 398 DidFailToConnectGatt(BluetoothDevice::ConnectErrorCode::ERROR_FAILED); | 419 DidFailToConnectGatt(BluetoothDevice::ConnectErrorCode::ERROR_FAILED); |
| 399 } | 420 } |
| OLD | NEW |