Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(65)

Side by Side Diff: device/bluetooth/bluetooth_remote_gatt_descriptor_mac.mm

Issue 2767813002: Bluetooth: macOS: Implementing read/write for descriptors (Closed)
Patch Set: . Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 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 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_remote_gatt_descriptor_mac.h" 5 #include "device/bluetooth/bluetooth_remote_gatt_descriptor_mac.h"
6 6
7 #include "base/bind.h"
8 #import "base/mac/foundation_util.h"
7 #include "base/strings/sys_string_conversions.h" 9 #include "base/strings/sys_string_conversions.h"
8 #include "device/bluetooth/bluetooth_adapter_mac.h" 10 #include "base/threading/thread_task_runner_handle.h"
9 #include "device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h" 11 #import "device/bluetooth/bluetooth_adapter_mac.h"
12 #import "device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h"
13
14 using base::mac::ObjCCast;
10 15
11 namespace device { 16 namespace device {
12 17
18 std::vector<uint8_t> VectorValueFromObjC(id objc_value) {
19 // According to
20 // https://developer.apple.com/reference/corebluetooth/cbdescriptor some
21 // descriptor values can be NSData, NSString or NSNumber.
22 std::vector<uint8_t> value;
23 NSData* data = ObjCCast<NSData>(objc_value);
24 NSString* as_string = ObjCCast<NSString>(objc_value);
25 NSNumber* as_number = ObjCCast<NSNumber>(objc_value);
26
27 if (as_number) {
28 CFNumberRef number = base::mac::CFCast<CFNumberRef>(objc_value);
29 CFIndex byteSize = CFNumberGetByteSize(number);
tapted 2017/04/07 04:40:43 https://developer.apple.com/reference/corefoundati
jlebel 2017/04/09 22:41:32 This documentation means that if we do +[NSNumber
30 CFNumberType type = CFNumberGetType(number);
tapted 2017/04/07 04:40:43 Maybe I'm overthinking it, but I can't tell from r
jlebel 2017/04/09 22:41:32 Ok, I'm going for the simple version, but at least
31 uint8_t* buffer = (uint8_t*)malloc(byteSize);
tapted 2017/04/07 04:40:43 static_cast<> (style guide prohibits C-style casts
jlebel 2017/04/09 22:41:32 Done.
32 CFNumberGetValue(number, type, buffer);
33 data = [NSData dataWithBytes:buffer length:byteSize];
34 free(buffer);
35 }
36 if (as_string)
37 data = [as_string dataUsingEncoding:NSUTF8StringEncoding];
38
39 DCHECK(data) << "Unexpected value: "
40 << base::SysNSStringToUTF8([objc_value description]);
41 if (data) {
42 value.resize([data length]);
43 [data getBytes:value.data() length:value.size()];
44 }
45 return value;
46 }
47
13 BluetoothRemoteGattDescriptorMac::BluetoothRemoteGattDescriptorMac( 48 BluetoothRemoteGattDescriptorMac::BluetoothRemoteGattDescriptorMac(
14 BluetoothRemoteGattCharacteristicMac* characteristic, 49 BluetoothRemoteGattCharacteristicMac* characteristic,
15 CBDescriptor* descriptor) 50 CBDescriptor* descriptor)
16 : gatt_characteristic_(characteristic), 51 : gatt_characteristic_(characteristic),
17 cb_descriptor_(descriptor, base::scoped_policy::RETAIN) { 52 cb_descriptor_(descriptor, base::scoped_policy::RETAIN),
18 uuid_ = 53 value_read_or_write_in_progress_(false) {
19 BluetoothAdapterMac::BluetoothUUIDWithCBUUID([cb_descriptor_.get() UUID]); 54 uuid_ = BluetoothAdapterMac::BluetoothUUIDWithCBUUID([cb_descriptor_ UUID]);
20 identifier_ = base::SysNSStringToUTF8( 55 identifier_ = base::SysNSStringToUTF8(
21 [NSString stringWithFormat:@"%s-%p", uuid_.canonical_value().c_str(), 56 [NSString stringWithFormat:@"%s-%p", uuid_.canonical_value().c_str(),
22 (void*)cb_descriptor_]); 57 (void*)cb_descriptor_]);
23 } 58 }
24 59
25 std::string BluetoothRemoteGattDescriptorMac::GetIdentifier() const { 60 std::string BluetoothRemoteGattDescriptorMac::GetIdentifier() const {
26 return identifier_; 61 return identifier_;
27 } 62 }
28 63
29 BluetoothUUID BluetoothRemoteGattDescriptorMac::GetUUID() const { 64 BluetoothUUID BluetoothRemoteGattDescriptorMac::GetUUID() const {
30 return uuid_; 65 return uuid_;
31 } 66 }
32 67
33 BluetoothGattCharacteristic::Permissions 68 BluetoothGattCharacteristic::Permissions
34 BluetoothRemoteGattDescriptorMac::GetPermissions() const { 69 BluetoothRemoteGattDescriptorMac::GetPermissions() const {
35 NOTIMPLEMENTED(); 70 NOTIMPLEMENTED();
36 return BluetoothGattCharacteristic::PERMISSION_NONE; 71 return BluetoothGattCharacteristic::PERMISSION_NONE;
37 } 72 }
38 73
39 const std::vector<uint8_t>& BluetoothRemoteGattDescriptorMac::GetValue() const { 74 const std::vector<uint8_t>& BluetoothRemoteGattDescriptorMac::GetValue() const {
40 return value_; 75 return value_;
41 } 76 }
42 77
43 BluetoothRemoteGattDescriptorMac::~BluetoothRemoteGattDescriptorMac() {} 78 BluetoothRemoteGattDescriptorMac::~BluetoothRemoteGattDescriptorMac() {
79 if (!read_value_callbacks_.first.is_null()) {
80 std::pair<ValueCallback, ErrorCallback> callbacks;
81 callbacks.swap(read_value_callbacks_);
82 callbacks.second.Run(BluetoothGattService::GATT_ERROR_FAILED);
83 }
84 if (!write_value_callbacks_.first.is_null()) {
85 std::pair<base::Closure, ErrorCallback> callbacks;
86 callbacks.swap(write_value_callbacks_);
87 callbacks.second.Run(BluetoothGattService::GATT_ERROR_FAILED);
88 }
89 }
44 90
45 // Returns a pointer to the GATT characteristic that this characteristic
46 // descriptor belongs to.
47 BluetoothRemoteGattCharacteristic* 91 BluetoothRemoteGattCharacteristic*
48 BluetoothRemoteGattDescriptorMac::GetCharacteristic() const { 92 BluetoothRemoteGattDescriptorMac::GetCharacteristic() const {
49 return static_cast<BluetoothRemoteGattCharacteristic*>(gatt_characteristic_); 93 return static_cast<BluetoothRemoteGattCharacteristic*>(gatt_characteristic_);
50 } 94 }
51 95
52 // Sends a read request to a remote characteristic descriptor to read its 96 // Sends a read request to a remote characteristic descriptor to read its
53 // value. |callback| is called to return the read value on success and 97 // value. |callback| is called to return the read value on success and
54 // |error_callback| is called for failures. 98 // |error_callback| is called for failures.
55 void BluetoothRemoteGattDescriptorMac::ReadRemoteDescriptor( 99 void BluetoothRemoteGattDescriptorMac::ReadRemoteDescriptor(
56 const ValueCallback& callback, 100 const ValueCallback& callback,
57 const ErrorCallback& error_callback) { 101 const ErrorCallback& error_callback) {
58 NOTIMPLEMENTED(); 102 if (value_read_or_write_in_progress_) {
103 VLOG(1) << *this << ": Read failed, already in progress.";
104 base::ThreadTaskRunnerHandle::Get()->PostTask(
105 FROM_HERE,
106 base::Bind(error_callback,
107 BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS));
108 return;
109 }
110 VLOG(1) << *this << ": Read value.";
111 value_read_or_write_in_progress_ = true;
112 read_value_callbacks_ = std::make_pair(callback, error_callback);
113 [GetCBPeripheral() readValueForDescriptor:cb_descriptor_];
59 } 114 }
60 115
61 // Sends a write request to a remote characteristic descriptor, to modify the
62 // value of the descriptor with the new value |new_value|. |callback| is
63 // called to signal success and |error_callback| for failures. This method
64 // only applies to remote descriptors and will fail for those that are locally
65 // hosted.
66 void BluetoothRemoteGattDescriptorMac::WriteRemoteDescriptor( 116 void BluetoothRemoteGattDescriptorMac::WriteRemoteDescriptor(
67 const std::vector<uint8_t>& new_value, 117 const std::vector<uint8_t>& value,
68 const base::Closure& callback, 118 const base::Closure& callback,
69 const ErrorCallback& error_callback) { 119 const ErrorCallback& error_callback) {
70 NOTIMPLEMENTED(); 120 if (value_read_or_write_in_progress_) {
121 VLOG(1) << *this << ": Write failed, already in progress.";
122 base::ThreadTaskRunnerHandle::Get()->PostTask(
123 FROM_HERE,
124 base::Bind(error_callback,
125 BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS));
126 return;
127 }
128 VLOG(1) << *this << ": Write value.";
129 value_read_or_write_in_progress_ = true;
130 write_value_callbacks_ = std::make_pair(callback, error_callback);
131 base::scoped_nsobject<NSData> nsdata_value(
132 [[NSData alloc] initWithBytes:value.data() length:value.size()]);
133 [GetCBPeripheral() writeValue:nsdata_value forDescriptor:GetCBDescriptor()];
134 }
135
136 void BluetoothRemoteGattDescriptorMac::DidUpdateValueForDescriptor(
137 NSError* error) {
138 if (!value_read_or_write_in_progress_) {
139 VLOG(1) << *this << ": Value updated, no read in progress.";
140 return;
141 }
142 std::pair<ValueCallback, ErrorCallback> callbacks;
143 callbacks.swap(read_value_callbacks_);
144 value_read_or_write_in_progress_ = false;
145 if (error) {
146 BluetoothGattService::GattErrorCode error_code =
147 BluetoothDeviceMac::GetGattErrorCodeFromNSError(error);
148 VLOG(1) << *this << ": Read value failed with error: "
149 << BluetoothAdapterMac::String(error)
150 << ", converted to error code: " << error_code;
151 callbacks.second.Run(error_code);
152 return;
153 }
154 VLOG(1) << *this << ": Value read.";
155 value_ = VectorValueFromObjC([cb_descriptor_ value]);
156 callbacks.first.Run(value_);
157 }
158
159 void BluetoothRemoteGattDescriptorMac::DidWriteValueForDescriptor(
160 NSError* error) {
161 if (!value_read_or_write_in_progress_) {
162 VLOG(1) << *this << ": Value written, no write in progress.";
163 return;
164 }
165 std::pair<base::Closure, ErrorCallback> callbacks;
166 callbacks.swap(write_value_callbacks_);
167 value_read_or_write_in_progress_ = false;
168 if (error) {
169 BluetoothGattService::GattErrorCode error_code =
170 BluetoothDeviceMac::GetGattErrorCodeFromNSError(error);
171 VLOG(1) << *this << ": Write value failed with error: "
172 << BluetoothAdapterMac::String(error)
173 << ", converted to error code: " << error_code;
174 callbacks.second.Run(error_code);
175 return;
176 }
177 VLOG(1) << *this << ": Value written.";
178 callbacks.first.Run();
179 }
180
181 CBPeripheral* BluetoothRemoteGattDescriptorMac::GetCBPeripheral() const {
182 return gatt_characteristic_->GetCBPeripheral();
71 } 183 }
72 184
73 CBDescriptor* BluetoothRemoteGattDescriptorMac::GetCBDescriptor() const { 185 CBDescriptor* BluetoothRemoteGattDescriptorMac::GetCBDescriptor() const {
74 return cb_descriptor_.get(); 186 return cb_descriptor_;
75 } 187 }
76 188
77 DEVICE_BLUETOOTH_EXPORT std::ostream& operator<<( 189 DEVICE_BLUETOOTH_EXPORT std::ostream& operator<<(
78 std::ostream& out, 190 std::ostream& out,
79 const BluetoothRemoteGattDescriptorMac& descriptor) { 191 const BluetoothRemoteGattDescriptorMac& descriptor) {
80 const BluetoothRemoteGattCharacteristicMac* characteristic_mac = 192 const BluetoothRemoteGattCharacteristicMac* characteristic_mac =
81 static_cast<const BluetoothRemoteGattCharacteristicMac*>( 193 static_cast<const BluetoothRemoteGattCharacteristicMac*>(
82 descriptor.GetCharacteristic()); 194 descriptor.GetCharacteristic());
83 return out << "<BluetoothRemoteGattServiceMac " 195 return out << "<BluetoothRemoteGattServiceMac "
84 << descriptor.GetUUID().canonical_value() << "/" << &descriptor 196 << descriptor.GetUUID().canonical_value() << "/" << &descriptor
85 << ", characteristic: " 197 << ", characteristic: "
86 << characteristic_mac->GetUUID().canonical_value() << "/" 198 << characteristic_mac->GetUUID().canonical_value() << "/"
87 << characteristic_mac << ">"; 199 << characteristic_mac << ">";
88 } 200 }
89 201
90 } // namespace device. 202 } // namespace device.
OLDNEW
« no previous file with comments | « device/bluetooth/bluetooth_remote_gatt_descriptor_mac.h ('k') | device/bluetooth/bluetooth_remote_gatt_descriptor_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698