bluetooth_remote_gatt_service_mac.mm 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. // Copyright 2016 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. #include "device/bluetooth/bluetooth_remote_gatt_service_mac.h"
  5. #import <CoreBluetooth/CoreBluetooth.h>
  6. #include <vector>
  7. #include "base/logging.h"
  8. #include "base/memory/ptr_util.h"
  9. #include "base/strings/sys_string_conversions.h"
  10. #include "device/bluetooth/bluetooth_adapter_mac.h"
  11. #include "device/bluetooth/bluetooth_low_energy_device_mac.h"
  12. #include "device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h"
  13. #include "device/bluetooth/public/cpp/bluetooth_uuid.h"
  14. namespace device {
  15. BluetoothRemoteGattServiceMac::BluetoothRemoteGattServiceMac(
  16. BluetoothLowEnergyDeviceMac* bluetooth_device_mac,
  17. CBService* service,
  18. bool is_primary)
  19. : bluetooth_device_mac_(bluetooth_device_mac),
  20. service_(service, base::scoped_policy::RETAIN),
  21. is_primary_(is_primary),
  22. discovery_pending_count_(0) {
  23. uuid_ = BluetoothAdapterMac::BluetoothUUIDWithCBUUID([service_ UUID]);
  24. identifier_ = base::SysNSStringToUTF8(
  25. [NSString stringWithFormat:@"%s-%p", uuid_.canonical_value().c_str(),
  26. service_.get()]);
  27. }
  28. BluetoothRemoteGattServiceMac::~BluetoothRemoteGattServiceMac() {}
  29. std::string BluetoothRemoteGattServiceMac::GetIdentifier() const {
  30. return identifier_;
  31. }
  32. BluetoothUUID BluetoothRemoteGattServiceMac::GetUUID() const {
  33. return uuid_;
  34. }
  35. bool BluetoothRemoteGattServiceMac::IsPrimary() const {
  36. return is_primary_;
  37. }
  38. BluetoothDevice* BluetoothRemoteGattServiceMac::GetDevice() const {
  39. return bluetooth_device_mac_;
  40. }
  41. std::vector<BluetoothRemoteGattService*>
  42. BluetoothRemoteGattServiceMac::GetIncludedServices() const {
  43. NOTIMPLEMENTED();
  44. return std::vector<BluetoothRemoteGattService*>();
  45. }
  46. void BluetoothRemoteGattServiceMac::DiscoverCharacteristics() {
  47. DVLOG(1) << *this << ": DiscoverCharacteristics.";
  48. SetDiscoveryComplete(false);
  49. ++discovery_pending_count_;
  50. [GetCBPeripheral() discoverCharacteristics:nil forService:GetService()];
  51. }
  52. void BluetoothRemoteGattServiceMac::DidDiscoverCharacteristics() {
  53. if (IsDiscoveryComplete() || discovery_pending_count_ == 0) {
  54. // This should never happen, just in case it happens with a device, this
  55. // notification should be ignored.
  56. DVLOG(1)
  57. << *this
  58. << ": Unmatch DiscoverCharacteristics and DidDiscoverCharacteristics.";
  59. return;
  60. }
  61. DVLOG(1) << *this << ": DidDiscoverCharacteristics.";
  62. --discovery_pending_count_;
  63. std::unordered_set<std::string> characteristic_identifier_to_remove;
  64. for (const auto& iter : characteristics_) {
  65. characteristic_identifier_to_remove.insert(iter.first);
  66. }
  67. for (CBCharacteristic* cb_characteristic in GetService().characteristics) {
  68. BluetoothRemoteGattCharacteristicMac* gatt_characteristic_mac =
  69. GetBluetoothRemoteGattCharacteristicMac(cb_characteristic);
  70. if (gatt_characteristic_mac) {
  71. DVLOG(1) << *gatt_characteristic_mac
  72. << ": Known characteristic, properties "
  73. << gatt_characteristic_mac->GetProperties();
  74. const std::string& identifier = gatt_characteristic_mac->GetIdentifier();
  75. characteristic_identifier_to_remove.erase(identifier);
  76. gatt_characteristic_mac->DiscoverDescriptors();
  77. continue;
  78. }
  79. gatt_characteristic_mac =
  80. new BluetoothRemoteGattCharacteristicMac(this, cb_characteristic);
  81. bool result = AddCharacteristic(base::WrapUnique(gatt_characteristic_mac));
  82. DCHECK(result);
  83. DVLOG(1) << *gatt_characteristic_mac << ": New characteristic, properties "
  84. << gatt_characteristic_mac->GetProperties();
  85. if (discovery_pending_count_ == 0) {
  86. gatt_characteristic_mac->DiscoverDescriptors();
  87. }
  88. GetMacAdapter()->NotifyGattCharacteristicAdded(gatt_characteristic_mac);
  89. }
  90. for (const std::string& identifier : characteristic_identifier_to_remove) {
  91. auto pair_to_remove = characteristics_.find(identifier);
  92. auto characteristic_to_remove = std::move(pair_to_remove->second);
  93. DVLOG(1) << static_cast<BluetoothRemoteGattCharacteristicMac&>(
  94. *characteristic_to_remove)
  95. << ": Removed characteristic.";
  96. characteristics_.erase(pair_to_remove);
  97. GetMacAdapter()->NotifyGattCharacteristicRemoved(
  98. characteristic_to_remove.get());
  99. }
  100. SendNotificationIfComplete();
  101. }
  102. void BluetoothRemoteGattServiceMac::DidDiscoverDescriptors(
  103. CBCharacteristic* characteristic) {
  104. if (IsDiscoveryComplete()) {
  105. // This should never happen, just in case it happens with a device, this
  106. // notification should be ignored.
  107. DVLOG(1) << *this
  108. << ": Discovery complete, ignoring DidDiscoverDescriptors.";
  109. return;
  110. }
  111. BluetoothRemoteGattCharacteristicMac* gatt_characteristic =
  112. GetBluetoothRemoteGattCharacteristicMac(characteristic);
  113. DCHECK(gatt_characteristic);
  114. gatt_characteristic->DidDiscoverDescriptors();
  115. SendNotificationIfComplete();
  116. }
  117. void BluetoothRemoteGattServiceMac::SendNotificationIfComplete() {
  118. DCHECK(!IsDiscoveryComplete());
  119. // Notify when all characteristics have been fully discovered.
  120. SetDiscoveryComplete(
  121. discovery_pending_count_ == 0 &&
  122. std::all_of(characteristics_.begin(), characteristics_.end(),
  123. [](const auto& pair) {
  124. return static_cast<BluetoothRemoteGattCharacteristicMac*>(
  125. pair.second.get())
  126. ->IsDiscoveryComplete();
  127. }));
  128. if (IsDiscoveryComplete()) {
  129. DVLOG(1) << *this << ": Discovery complete.";
  130. GetMacAdapter()->NotifyGattServiceChanged(this);
  131. }
  132. }
  133. BluetoothAdapterMac* BluetoothRemoteGattServiceMac::GetMacAdapter() const {
  134. return bluetooth_device_mac_->GetMacAdapter();
  135. }
  136. CBPeripheral* BluetoothRemoteGattServiceMac::GetCBPeripheral() const {
  137. return bluetooth_device_mac_->GetPeripheral();
  138. }
  139. CBService* BluetoothRemoteGattServiceMac::GetService() const {
  140. return service_;
  141. }
  142. BluetoothRemoteGattCharacteristicMac*
  143. BluetoothRemoteGattServiceMac::GetBluetoothRemoteGattCharacteristicMac(
  144. CBCharacteristic* cb_characteristic) const {
  145. for (const auto& pair : characteristics_) {
  146. auto* characteristic_mac =
  147. static_cast<BluetoothRemoteGattCharacteristicMac*>(pair.second.get());
  148. if (characteristic_mac->GetCBCharacteristic() == cb_characteristic)
  149. return characteristic_mac;
  150. }
  151. return nullptr;
  152. }
  153. BluetoothRemoteGattDescriptorMac*
  154. BluetoothRemoteGattServiceMac::GetBluetoothRemoteGattDescriptorMac(
  155. CBDescriptor* cb_descriptor) const {
  156. CBCharacteristic* cb_characteristic = [cb_descriptor characteristic];
  157. BluetoothRemoteGattCharacteristicMac* gatt_characteristic_mac =
  158. GetBluetoothRemoteGattCharacteristicMac(cb_characteristic);
  159. if (!gatt_characteristic_mac) {
  160. return nullptr;
  161. }
  162. return gatt_characteristic_mac->GetBluetoothRemoteGattDescriptorMac(
  163. cb_descriptor);
  164. }
  165. DEVICE_BLUETOOTH_EXPORT std::ostream& operator<<(
  166. std::ostream& out,
  167. const BluetoothRemoteGattServiceMac& service) {
  168. const BluetoothLowEnergyDeviceMac* bluetooth_device_mac_ =
  169. static_cast<const BluetoothLowEnergyDeviceMac*>(service.GetDevice());
  170. return out << "<BluetoothRemoteGattServiceMac "
  171. << service.GetUUID().canonical_value() << "/" << &service
  172. << ", device: " << bluetooth_device_mac_->GetAddress() << "/"
  173. << bluetooth_device_mac_ << ">";
  174. }
  175. } // namespace device