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 |