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 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 186 void BluetoothLowEnergyDeviceMac::DidDiscoverPrimaryServices(NSError* error) { | 187 void BluetoothLowEnergyDeviceMac::DidDiscoverPrimaryServices(NSError* error) { |
| 187 if (error) { | 188 if (error) { |
| 188 // TODO(http://crbug.com/609320): Need to pass the error. | 189 // TODO(http://crbug.com/609320): Need to pass the error. |
| 189 // TODO(http://crbug.com/609844): Decide what to do if discover failed | 190 // TODO(http://crbug.com/609844): Decide what to do if discover failed |
| 190 // a device services. | 191 // a device services. |
| 191 VLOG(1) << "Can't discover primary services: " | 192 VLOG(1) << "Can't discover primary services: " |
| 192 << error.localizedDescription.UTF8String << " (" << error.domain | 193 << error.localizedDescription.UTF8String << " (" << error.domain |
| 193 << ": " << error.code << ")"; | 194 << ": " << error.code << ")"; |
| 194 return; | 195 return; |
| 195 } | 196 } |
| 196 VLOG(1) << "DidDiscoverPrimaryServices."; | 197 VLOG(1) << "DidDiscoverPrimaryServices, pending count: " |
| 198 << discovery_pending_count_; | |
| 197 | 199 |
| 198 if (!IsGattConnected()) { | 200 if (!IsGattConnected()) { |
| 199 // Don't create services if the device disconnected. | 201 // Don't create services if the device disconnected. |
| 200 return; | 202 return; |
| 201 } | 203 } |
| 202 | 204 |
| 203 for (CBService* cb_service in GetPeripheral().services) { | 205 for (CBService* cb_service in GetPeripheral().services) { |
| 204 BluetoothRemoteGattServiceMac* gatt_service = | 206 BluetoothRemoteGattServiceMac* gatt_service = |
| 205 GetBluetoothRemoteGattService(cb_service); | 207 GetBluetoothRemoteGattService(cb_service); |
| 206 if (!gatt_service) { | 208 if (!gatt_service) { |
| 207 gatt_service = new BluetoothRemoteGattServiceMac(this, cb_service, | 209 gatt_service = new BluetoothRemoteGattServiceMac(this, cb_service, |
| 208 true /* is_primary */); | 210 true /* is_primary */); |
| 209 auto result_iter = gatt_services_.insert(std::make_pair( | 211 auto result_iter = gatt_services_.insert(std::make_pair( |
| 210 gatt_service->GetIdentifier(), base::WrapUnique(gatt_service))); | 212 gatt_service->GetIdentifier(), base::WrapUnique(gatt_service))); |
| 211 DCHECK(result_iter.second); | 213 DCHECK(result_iter.second); |
| 212 adapter_->NotifyGattServiceAdded(gatt_service); | 214 adapter_->NotifyGattServiceAdded(gatt_service); |
| 213 } | 215 } |
| 214 } | 216 } |
| 215 for (auto it = gatt_services_.begin(); it != gatt_services_.end(); ++it) { | 217 --discovery_pending_count_; |
| 216 device::BluetoothRemoteGattService* gatt_service = it->second.get(); | 218 DCHECK(discovery_pending_count_ >= 0); |
| 217 device::BluetoothRemoteGattServiceMac* gatt_service_mac = | 219 if (discovery_pending_count_ == 0) { |
| 218 static_cast<BluetoothRemoteGattServiceMac*>(gatt_service); | 220 for (auto it = gatt_services_.begin(); it != gatt_services_.end(); ++it) { |
| 219 gatt_service_mac->DiscoverCharacteristics(); | 221 device::BluetoothRemoteGattService* gatt_service = it->second.get(); |
| 222 device::BluetoothRemoteGattServiceMac* gatt_service_mac = | |
| 223 static_cast<BluetoothRemoteGattServiceMac*>(gatt_service); | |
| 224 gatt_service_mac->DiscoverCharacteristics(); | |
| 225 } | |
| 226 SendNotificationIfDiscoveryComplete(); | |
| 220 } | 227 } |
| 221 } | 228 } |
| 222 | 229 |
| 223 void BluetoothLowEnergyDeviceMac::DidDiscoverCharacteristics( | 230 void BluetoothLowEnergyDeviceMac::DidDiscoverCharacteristics( |
| 224 CBService* cb_service, | 231 CBService* cb_service, |
| 225 NSError* error) { | 232 NSError* error) { |
| 226 if (error) { | 233 if (error) { |
| 227 // TODO(http://crbug.com/609320): Need to pass the error. | 234 // TODO(http://crbug.com/609320): Need to pass the error. |
| 228 // TODO(http://crbug.com/609844): Decide what to do if discover failed | 235 // TODO(http://crbug.com/609844): Decide what to do if discover failed |
| 229 VLOG(1) << "Can't discover characteristics: " | 236 VLOG(1) << "Can't discover characteristics: " |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 254 DCHECK(gatt_service); | 261 DCHECK(gatt_service); |
| 255 VLOG(1) << gatt_service->GetUUID().canonical_value(); | 262 VLOG(1) << gatt_service->GetUUID().canonical_value(); |
| 256 std::unique_ptr<BluetoothRemoteGattService> scoped_service = | 263 std::unique_ptr<BluetoothRemoteGattService> scoped_service = |
| 257 std::move(gatt_services_[gatt_service->GetIdentifier()]); | 264 std::move(gatt_services_[gatt_service->GetIdentifier()]); |
| 258 gatt_services_.erase(gatt_service->GetIdentifier()); | 265 gatt_services_.erase(gatt_service->GetIdentifier()); |
| 259 adapter_->NotifyGattServiceRemoved(scoped_service.get()); | 266 adapter_->NotifyGattServiceRemoved(scoped_service.get()); |
| 260 } | 267 } |
| 261 device_uuids_.ClearServiceUUIDs(); | 268 device_uuids_.ClearServiceUUIDs(); |
| 262 SetGattServicesDiscoveryComplete(false); | 269 SetGattServicesDiscoveryComplete(false); |
| 263 adapter_->NotifyDeviceChanged(this); | 270 adapter_->NotifyDeviceChanged(this); |
| 264 [GetPeripheral() discoverServices:nil]; | 271 DiscoverPrimaryServices(); |
| 265 } | 272 } |
| 266 | 273 |
| 267 void BluetoothLowEnergyDeviceMac::DidUpdateValue( | 274 void BluetoothLowEnergyDeviceMac::DidUpdateValue( |
| 268 CBCharacteristic* characteristic, | 275 CBCharacteristic* characteristic, |
| 269 NSError* error) { | 276 NSError* error) { |
| 270 VLOG(1) << "DidUpdateValue."; | 277 VLOG(1) << "DidUpdateValue."; |
| 271 BluetoothRemoteGattServiceMac* gatt_service = | 278 BluetoothRemoteGattServiceMac* gatt_service = |
| 272 GetBluetoothRemoteGattService(characteristic.service); | 279 GetBluetoothRemoteGattService(characteristic.service); |
| 273 DCHECK(gatt_service); | 280 DCHECK(gatt_service); |
| 274 gatt_service->DidUpdateValue(characteristic, error); | 281 gatt_service->DidUpdateValue(characteristic, error); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 330 std::string BluetoothLowEnergyDeviceMac::GetPeripheralHashAddress( | 337 std::string BluetoothLowEnergyDeviceMac::GetPeripheralHashAddress( |
| 331 CBPeripheral* peripheral) { | 338 CBPeripheral* peripheral) { |
| 332 const size_t kCanonicalAddressNumberOfBytes = 6; | 339 const size_t kCanonicalAddressNumberOfBytes = 6; |
| 333 char raw[kCanonicalAddressNumberOfBytes]; | 340 char raw[kCanonicalAddressNumberOfBytes]; |
| 334 crypto::SHA256HashString(GetPeripheralIdentifier(peripheral), raw, | 341 crypto::SHA256HashString(GetPeripheralIdentifier(peripheral), raw, |
| 335 sizeof(raw)); | 342 sizeof(raw)); |
| 336 std::string hash = base::HexEncode(raw, sizeof(raw)); | 343 std::string hash = base::HexEncode(raw, sizeof(raw)); |
| 337 return BluetoothDevice::CanonicalizeAddress(hash); | 344 return BluetoothDevice::CanonicalizeAddress(hash); |
| 338 } | 345 } |
| 339 | 346 |
| 347 void BluetoothLowEnergyDeviceMac::DiscoverPrimaryServices() { | |
| 348 [GetPeripheral() discoverServices:nil]; | |
|
ortuno
2017/01/23 20:44:02
nit: Move this to the end of the function.
jlebel
2017/01/26 00:36:54
Done.
| |
| 349 VLOG(1) << "DidDiscoverDescriptors pending count" << discovery_pending_count_; | |
| 350 ++discovery_pending_count_; | |
| 351 } | |
| 352 | |
| 340 void BluetoothLowEnergyDeviceMac::SendNotificationIfDiscoveryComplete() { | 353 void BluetoothLowEnergyDeviceMac::SendNotificationIfDiscoveryComplete() { |
| 341 // Notify when all services have been discovered. | 354 // Notify when all services have been discovered. |
| 342 bool discovery_complete = | 355 bool discovery_complete = |
| 356 discovery_pending_count_ == 0 && | |
| 343 std::find_if_not( | 357 std::find_if_not( |
| 344 gatt_services_.begin(), gatt_services_.end(), | 358 gatt_services_.begin(), gatt_services_.end(), |
| 345 [](GattServiceMap::value_type& pair) { | 359 [](GattServiceMap::value_type& pair) { |
| 346 BluetoothRemoteGattService* gatt_service = pair.second.get(); | 360 BluetoothRemoteGattService* gatt_service = pair.second.get(); |
| 347 return static_cast<BluetoothRemoteGattServiceMac*>(gatt_service) | 361 return static_cast<BluetoothRemoteGattServiceMac*>(gatt_service) |
| 348 ->IsDiscoveryComplete(); | 362 ->IsDiscoveryComplete(); |
| 349 }) == gatt_services_.end(); | 363 }) == gatt_services_.end(); |
| 350 if (discovery_complete) { | 364 if (discovery_complete) { |
| 351 device_uuids_.ReplaceServiceUUIDs(gatt_services_); | 365 device_uuids_.ReplaceServiceUUIDs(gatt_services_); |
| 352 SetGattServicesDiscoveryComplete(true); | 366 SetGattServicesDiscoveryComplete(true); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 390 // 2. When we cancel a pending connection request. | 404 // 2. When we cancel a pending connection request. |
| 391 if (create_gatt_connection_error_callbacks_.empty()) { | 405 if (create_gatt_connection_error_callbacks_.empty()) { |
| 392 // If there are no pending callbacks then the connection broke (#1). | 406 // If there are no pending callbacks then the connection broke (#1). |
| 393 DidDisconnectGatt(true /* notifyDeviceChanged */); | 407 DidDisconnectGatt(true /* notifyDeviceChanged */); |
| 394 return; | 408 return; |
| 395 } | 409 } |
| 396 // Else we canceled the connection request (#2). | 410 // Else we canceled the connection request (#2). |
| 397 // TODO(http://crbug.com/585897): Need to pass the error. | 411 // TODO(http://crbug.com/585897): Need to pass the error. |
| 398 DidFailToConnectGatt(BluetoothDevice::ConnectErrorCode::ERROR_FAILED); | 412 DidFailToConnectGatt(BluetoothDevice::ConnectErrorCode::ERROR_FAILED); |
| 399 } | 413 } |
| OLD | NEW |