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

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

Issue 2767813002: Bluetooth: macOS: Implementing read/write for descriptors (Closed)
Patch Set: NSString/NSNumber type for descriptor value 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 #include "base/mac/foundation_util.h"
tapted 2017/04/05 00:38:37 nit: #import
jlebel 2017/04/06 17:48:49 Done.
7 #include "base/strings/sys_string_conversions.h" 9 #include "base/strings/sys_string_conversions.h"
10 #include "base/threading/thread_task_runner_handle.h"
8 #include "device/bluetooth/bluetooth_adapter_mac.h" 11 #include "device/bluetooth/bluetooth_adapter_mac.h"
tapted 2017/04/05 00:38:37 #import
jlebel 2017/04/06 17:48:49 Done.
9 #include "device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h" 12 #include "device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h"
tapted 2017/04/05 00:38:37 #import as well
jlebel 2017/04/06 17:48:49 Done.
10 13
14 using base::mac::ObjCCast;
15
11 namespace device { 16 namespace device {
12 17
18 std::vector<uint8_t> VectorValueFromObjC(id objcValue) {
tapted 2017/04/05 00:38:37 objcValue -> objc_value (or just value) - we only
jlebel 2017/04/06 17:48:49 Done.
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 if ([objcValue isKindOfClass:[NSString class]]) {
24 NSString* string = ObjCCast<NSString>(objcValue);
tapted 2017/04/05 00:38:37 ObjCCast also does isKindOfClass, so there's a bit
jlebel 2017/04/06 17:48:49 about the first "if": I don't understand why we ne
tapted 2017/04/07 04:40:43 Yep - it would be an error if more than one is set
25 const uint8_t* buffer = (const uint8_t*)(string.UTF8String);
tapted 2017/04/05 00:38:37 note style guide prohibits C-style casts (use rein
jlebel 2017/04/06 17:48:49 Done.
26 value.assign(buffer, buffer + string.length);
27 } else if ([objcValue isKindOfClass:[NSNumber class]]) {
28 CFNumberRef number = base::mac::CFCast<CFNumberRef>(objcValue);
29 CFIndex byteSize = CFNumberGetByteSize(number);
30 CFNumberType type = CFNumberGetType(number);
31 uint8_t* buffer = (uint8_t*)malloc(byteSize);
tapted 2017/04/05 00:38:37 memory leak? - nothing frees |buffer|
jlebel 2017/04/06 17:48:49 Done.
32 CFNumberGetValue(number, type, buffer);
33 value.assign(buffer, buffer + byteSize);
34 } else if ([objcValue isKindOfClass:[NSData class]]) {
35 DCHECK([objcValue isKindOfClass:[NSData class]]);
36 NSData* data = ObjCCast<NSData>(objcValue);
37 const uint8_t* buffer = (const uint8_t*)(data.bytes);
tapted 2017/04/05 00:38:37 data.bytes may return nil - this is really dangero
jlebel 2017/04/06 17:48:49 According to the documentation, -[NSData bytes] ca
tapted 2017/04/07 04:40:43 Hm - maybe you're safe with C++ vectors. It scares
38 value.assign(buffer, buffer + data.length);
39 } else {
40 VLOG(1) << "Unexpected value: "
41 << base::SysNSStringToUTF8([objcValue description]);
42 NOTREACHED();
43 }
44 return value;
45 }
46
13 BluetoothRemoteGattDescriptorMac::BluetoothRemoteGattDescriptorMac( 47 BluetoothRemoteGattDescriptorMac::BluetoothRemoteGattDescriptorMac(
14 BluetoothRemoteGattCharacteristicMac* characteristic, 48 BluetoothRemoteGattCharacteristicMac* characteristic,
15 CBDescriptor* descriptor) 49 CBDescriptor* descriptor)
16 : gatt_characteristic_(characteristic), 50 : gatt_characteristic_(characteristic),
17 cb_descriptor_(descriptor, base::scoped_policy::RETAIN) { 51 cb_descriptor_(descriptor, base::scoped_policy::RETAIN),
52 value_read_or_write_in_progress_(false) {
18 uuid_ = 53 uuid_ =
19 BluetoothAdapterMac::BluetoothUUIDWithCBUUID([cb_descriptor_.get() UUID]); 54 BluetoothAdapterMac::BluetoothUUIDWithCBUUID([cb_descriptor_.get() 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()) {
ortuno 2017/04/04 23:39:43 We need tests like [1] to test that this is gettin
jlebel 2017/04/06 17:48:49 crbug.com/709066
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 91 // Returns a pointer to the GATT characteristic that this characteristic
46 // descriptor belongs to. 92 // descriptor belongs to.
47 BluetoothRemoteGattCharacteristic* 93 BluetoothRemoteGattCharacteristic*
48 BluetoothRemoteGattDescriptorMac::GetCharacteristic() const { 94 BluetoothRemoteGattDescriptorMac::GetCharacteristic() const {
49 return static_cast<BluetoothRemoteGattCharacteristic*>(gatt_characteristic_); 95 return static_cast<BluetoothRemoteGattCharacteristic*>(gatt_characteristic_);
50 } 96 }
51 97
52 // Sends a read request to a remote characteristic descriptor to read its 98 // 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 99 // value. |callback| is called to return the read value on success and
54 // |error_callback| is called for failures. 100 // |error_callback| is called for failures.
55 void BluetoothRemoteGattDescriptorMac::ReadRemoteDescriptor( 101 void BluetoothRemoteGattDescriptorMac::ReadRemoteDescriptor(
56 const ValueCallback& callback, 102 const ValueCallback& callback,
57 const ErrorCallback& error_callback) { 103 const ErrorCallback& error_callback) {
58 NOTIMPLEMENTED(); 104 if (value_read_or_write_in_progress_) {
105 VLOG(1) << *this << ": Read failed, already in progress.";
106 base::ThreadTaskRunnerHandle::Get()->PostTask(
107 FROM_HERE,
108 base::Bind(error_callback,
109 BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS));
110 return;
111 }
112 VLOG(1) << *this << ": Read value.";
113 value_read_or_write_in_progress_ = true;
114 read_value_callbacks_ = std::make_pair(callback, error_callback);
115 [GetCBPeripheral() readValueForDescriptor:cb_descriptor_];
59 } 116 }
60 117
61 // Sends a write request to a remote characteristic descriptor, to modify the 118 // Sends a write request to a remote characteristic descriptor. |callback| is
ortuno 2017/04/04 23:39:43 I think its weird to have these comments in the .m
jlebel 2017/04/06 17:48:49 Done.
62 // value of the descriptor with the new value |new_value|. |callback| is 119 // called to signal success or |error_callback| for failures.
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( 120 void BluetoothRemoteGattDescriptorMac::WriteRemoteDescriptor(
67 const std::vector<uint8_t>& new_value, 121 const std::vector<uint8_t>& value,
68 const base::Closure& callback, 122 const base::Closure& callback,
69 const ErrorCallback& error_callback) { 123 const ErrorCallback& error_callback) {
70 NOTIMPLEMENTED(); 124 if (value_read_or_write_in_progress_) {
125 VLOG(1) << *this << ": Write failed, already in progress.";
126 base::ThreadTaskRunnerHandle::Get()->PostTask(
127 FROM_HERE,
128 base::Bind(error_callback,
129 BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS));
130 return;
131 }
132 VLOG(1) << *this << ": Write value.";
133 value_read_or_write_in_progress_ = true;
134 write_value_callbacks_ = std::make_pair(callback, error_callback);
135 base::scoped_nsobject<NSData> nsdata_value(
136 [[NSData alloc] initWithBytes:value.data() length:value.size()]);
137 [GetCBPeripheral() writeValue:nsdata_value forDescriptor:GetCBDescriptor()];
138 }
139
140 void BluetoothRemoteGattDescriptorMac::DidUpdateValueForDescriptor(
141 NSError* error) {
142 if (!value_read_or_write_in_progress_) {
143 VLOG(1) << *this << ": Value updated, no read in progress.";
144 return;
145 }
146 std::pair<ValueCallback, ErrorCallback> callbacks;
147 callbacks.swap(read_value_callbacks_);
148 value_read_or_write_in_progress_ = false;
149 if (error) {
150 BluetoothGattService::GattErrorCode error_code =
151 BluetoothDeviceMac::GetGattErrorCodeFromNSError(error);
152 VLOG(1) << *this << ": Read value failed with error: "
153 << BluetoothAdapterMac::String(error)
154 << ", converted to error code: " << error_code;
155 callbacks.second.Run(error_code);
156 return;
157 }
158 VLOG(1) << *this << ": Value read.";
159 value_ = VectorValueFromObjC(cb_descriptor_.get().value);
tapted 2017/04/05 00:38:37 we don't use ObjC dot notation for NSObjects in Ch
jlebel 2017/04/06 17:48:49 Done. For the code I wrote in other files: crbug.
160 callbacks.first.Run(value_);
161 }
162
163 void BluetoothRemoteGattDescriptorMac::DidWriteValueForDescriptor(
164 NSError* error) {
165 if (!value_read_or_write_in_progress_) {
166 VLOG(1) << *this << ": Value written, no write in progress.";
167 return;
168 }
169 std::pair<base::Closure, ErrorCallback> callbacks;
170 callbacks.swap(write_value_callbacks_);
171 value_read_or_write_in_progress_ = false;
172 if (error) {
173 BluetoothGattService::GattErrorCode error_code =
174 BluetoothDeviceMac::GetGattErrorCodeFromNSError(error);
175 VLOG(1) << *this << ": Write value failed with error: "
176 << BluetoothAdapterMac::String(error)
177 << ", converted to error code: " << error_code;
178 callbacks.second.Run(error_code);
179 return;
180 }
181 VLOG(1) << *this << ": Value written.";
182 callbacks.first.Run();
183 }
184
185 CBPeripheral* BluetoothRemoteGattDescriptorMac::GetCBPeripheral() const {
186 return gatt_characteristic_->GetCBPeripheral();
71 } 187 }
72 188
73 CBDescriptor* BluetoothRemoteGattDescriptorMac::GetCBDescriptor() const { 189 CBDescriptor* BluetoothRemoteGattDescriptorMac::GetCBDescriptor() const {
74 return cb_descriptor_.get(); 190 return cb_descriptor_.get();
75 } 191 }
76 192
77 DEVICE_BLUETOOTH_EXPORT std::ostream& operator<<( 193 DEVICE_BLUETOOTH_EXPORT std::ostream& operator<<(
78 std::ostream& out, 194 std::ostream& out,
79 const BluetoothRemoteGattDescriptorMac& descriptor) { 195 const BluetoothRemoteGattDescriptorMac& descriptor) {
80 const BluetoothRemoteGattCharacteristicMac* characteristic_mac = 196 const BluetoothRemoteGattCharacteristicMac* characteristic_mac =
81 static_cast<const BluetoothRemoteGattCharacteristicMac*>( 197 static_cast<const BluetoothRemoteGattCharacteristicMac*>(
82 descriptor.GetCharacteristic()); 198 descriptor.GetCharacteristic());
83 return out << "<BluetoothRemoteGattServiceMac " 199 return out << "<BluetoothRemoteGattServiceMac "
84 << descriptor.GetUUID().canonical_value() << "/" << &descriptor 200 << descriptor.GetUUID().canonical_value() << "/" << &descriptor
85 << ", characteristic: " 201 << ", characteristic: "
86 << characteristic_mac->GetUUID().canonical_value() << "/" 202 << characteristic_mac->GetUUID().canonical_value() << "/"
87 << characteristic_mac << ">"; 203 << characteristic_mac << ">";
88 } 204 }
89 205
90 } // namespace device. 206 } // namespace device.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698