bluetooth_remote_gatt_descriptor_mac.mm 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. // Copyright 2017 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_descriptor_mac.h"
  5. #include "base/bind.h"
  6. #import "base/mac/foundation_util.h"
  7. #include "base/strings/sys_string_conversions.h"
  8. #include "base/threading/thread_task_runner_handle.h"
  9. #import "device/bluetooth/bluetooth_adapter_mac.h"
  10. #include "device/bluetooth/bluetooth_adapter_mac_metrics.h"
  11. #import "device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h"
  12. using base::mac::ObjCCast;
  13. namespace device {
  14. std::vector<uint8_t> VectorValueFromObjC(id objc_value) {
  15. // According to
  16. // https://developer.apple.com/reference/corebluetooth/cbdescriptor some
  17. // descriptor values can be NSData, NSString or NSNumber.
  18. std::vector<uint8_t> value;
  19. NSData* data = ObjCCast<NSData>(objc_value);
  20. NSString* as_string = ObjCCast<NSString>(objc_value);
  21. NSNumber* as_number = ObjCCast<NSNumber>(objc_value);
  22. if (!data && !as_string && as_number) {
  23. unsigned short descriptor = [as_number shortValue];
  24. data = [NSData dataWithBytes:&descriptor length:sizeof(descriptor)];
  25. }
  26. if (!data && as_string)
  27. data = [as_string dataUsingEncoding:NSUTF8StringEncoding];
  28. if (data) {
  29. value.resize([data length]);
  30. [data getBytes:value.data() length:value.size()];
  31. } else {
  32. LOG(WARNING) << "Unexpected value: "
  33. << base::SysNSStringToUTF8([objc_value description]);
  34. }
  35. return value;
  36. }
  37. BluetoothRemoteGattDescriptorMac::BluetoothRemoteGattDescriptorMac(
  38. BluetoothRemoteGattCharacteristicMac* characteristic,
  39. CBDescriptor* descriptor)
  40. : gatt_characteristic_(characteristic),
  41. cb_descriptor_(descriptor, base::scoped_policy::RETAIN) {
  42. uuid_ = BluetoothAdapterMac::BluetoothUUIDWithCBUUID([cb_descriptor_ UUID]);
  43. identifier_ = base::SysNSStringToUTF8(
  44. [NSString stringWithFormat:@"%s-%p", uuid_.canonical_value().c_str(),
  45. cb_descriptor_.get()]);
  46. }
  47. std::string BluetoothRemoteGattDescriptorMac::GetIdentifier() const {
  48. return identifier_;
  49. }
  50. BluetoothUUID BluetoothRemoteGattDescriptorMac::GetUUID() const {
  51. return uuid_;
  52. }
  53. BluetoothGattCharacteristic::Permissions
  54. BluetoothRemoteGattDescriptorMac::GetPermissions() const {
  55. NOTIMPLEMENTED();
  56. return BluetoothGattCharacteristic::PERMISSION_NONE;
  57. }
  58. const std::vector<uint8_t>& BluetoothRemoteGattDescriptorMac::GetValue() const {
  59. return value_;
  60. }
  61. BluetoothRemoteGattDescriptorMac::~BluetoothRemoteGattDescriptorMac() {
  62. destructor_called_ = true;
  63. if (HasPendingRead()) {
  64. std::move(read_value_callback_)
  65. .Run(BluetoothGattService::GATT_ERROR_FAILED,
  66. /*value=*/std::vector<uint8_t>());
  67. }
  68. if (HasPendingWrite()) {
  69. std::move(write_value_callbacks_)
  70. .second.Run(BluetoothGattService::GATT_ERROR_FAILED);
  71. }
  72. }
  73. BluetoothRemoteGattCharacteristic*
  74. BluetoothRemoteGattDescriptorMac::GetCharacteristic() const {
  75. return static_cast<BluetoothRemoteGattCharacteristic*>(gatt_characteristic_);
  76. }
  77. // Sends a read request to a remote characteristic descriptor to read its
  78. // value. |callback| is called to return the read value on success and
  79. // |error_callback| is called for failures.
  80. void BluetoothRemoteGattDescriptorMac::ReadRemoteDescriptor(
  81. ValueCallback callback) {
  82. if (destructor_called_ || HasPendingRead() || HasPendingWrite()) {
  83. DVLOG(1) << *this << ": Read failed, already in progress.";
  84. base::ThreadTaskRunnerHandle::Get()->PostTask(
  85. FROM_HERE, base::BindOnce(std::move(callback),
  86. BluetoothGattService::GATT_ERROR_IN_PROGRESS,
  87. /*value=*/std::vector<uint8_t>()));
  88. return;
  89. }
  90. DVLOG(1) << *this << ": Read value.";
  91. read_value_callback_ = std::move(callback);
  92. [GetCBPeripheral() readValueForDescriptor:cb_descriptor_];
  93. }
  94. void BluetoothRemoteGattDescriptorMac::WriteRemoteDescriptor(
  95. const std::vector<uint8_t>& value,
  96. base::OnceClosure callback,
  97. ErrorCallback error_callback) {
  98. if (destructor_called_ || HasPendingRead() || HasPendingWrite()) {
  99. DVLOG(1) << *this << ": Write failed, already in progress.";
  100. base::ThreadTaskRunnerHandle::Get()->PostTask(
  101. FROM_HERE,
  102. base::BindOnce(std::move(error_callback),
  103. BluetoothGattService::GATT_ERROR_IN_PROGRESS));
  104. return;
  105. }
  106. DVLOG(1) << *this << ": Write value.";
  107. write_value_callbacks_ =
  108. std::make_pair(std::move(callback), std::move(error_callback));
  109. base::scoped_nsobject<NSData> nsdata_value(
  110. [[NSData alloc] initWithBytes:value.data() length:value.size()]);
  111. [GetCBPeripheral() writeValue:nsdata_value forDescriptor:GetCBDescriptor()];
  112. }
  113. void BluetoothRemoteGattDescriptorMac::DidUpdateValueForDescriptor(
  114. NSError* error) {
  115. if (!HasPendingRead()) {
  116. DVLOG(1) << *this << ": Value updated, no read in progress.";
  117. return;
  118. }
  119. RecordDidUpdateValueForDescriptorResult(error);
  120. if (error) {
  121. BluetoothGattService::GattErrorCode error_code =
  122. BluetoothDeviceMac::GetGattErrorCodeFromNSError(error);
  123. DVLOG(1) << *this << ": Read value failed with error: "
  124. << BluetoothAdapterMac::String(error)
  125. << ", converted to error code: " << error_code;
  126. std::move(read_value_callback_)
  127. .Run(error_code,
  128. /*value=*/std::vector<uint8_t>());
  129. return;
  130. }
  131. DVLOG(1) << *this << ": Value read.";
  132. value_ = VectorValueFromObjC([cb_descriptor_ value]);
  133. std::move(read_value_callback_).Run(/*error_code=*/absl::nullopt, value_);
  134. }
  135. void BluetoothRemoteGattDescriptorMac::DidWriteValueForDescriptor(
  136. NSError* error) {
  137. if (!HasPendingWrite()) {
  138. DVLOG(1) << *this << ": Value written, no write in progress.";
  139. return;
  140. }
  141. std::pair<base::OnceClosure, ErrorCallback> callbacks;
  142. callbacks.swap(write_value_callbacks_);
  143. RecordDidWriteValueForDescriptorResult(error);
  144. if (error) {
  145. BluetoothGattService::GattErrorCode error_code =
  146. BluetoothDeviceMac::GetGattErrorCodeFromNSError(error);
  147. DVLOG(1) << *this << ": Write value failed with error: "
  148. << BluetoothAdapterMac::String(error)
  149. << ", converted to error code: " << error_code;
  150. std::move(callbacks.second).Run(error_code);
  151. return;
  152. }
  153. DVLOG(1) << *this << ": Value written.";
  154. std::move(callbacks.first).Run();
  155. }
  156. CBPeripheral* BluetoothRemoteGattDescriptorMac::GetCBPeripheral() const {
  157. return gatt_characteristic_->GetCBPeripheral();
  158. }
  159. CBDescriptor* BluetoothRemoteGattDescriptorMac::GetCBDescriptor() const {
  160. return cb_descriptor_;
  161. }
  162. DEVICE_BLUETOOTH_EXPORT std::ostream& operator<<(
  163. std::ostream& out,
  164. const BluetoothRemoteGattDescriptorMac& descriptor) {
  165. const BluetoothRemoteGattCharacteristicMac* characteristic_mac =
  166. static_cast<const BluetoothRemoteGattCharacteristicMac*>(
  167. descriptor.GetCharacteristic());
  168. return out << "<BluetoothRemoteGattDescriptorMac "
  169. << descriptor.GetUUID().canonical_value() << "/" << &descriptor
  170. << ", characteristic: "
  171. << characteristic_mac->GetUUID().canonical_value() << "/"
  172. << characteristic_mac << ">";
  173. }
  174. } // namespace device.