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

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

Issue 2595373003: Bluetooth: mac: Working on macOS descriptor implementation. (Closed)
Patch Set: Fixes Created 3 years, 11 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 2016 The Chromium Authors. All rights reserved. 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 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_characteristic_mac.h" 5 #include "device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/memory/ptr_util.h" 8 #include "base/memory/ptr_util.h"
9 #include "base/strings/sys_string_conversions.h" 9 #include "base/strings/sys_string_conversions.h"
10 #include "base/threading/thread_task_runner_handle.h" 10 #include "base/threading/thread_task_runner_handle.h"
11 #include "device/bluetooth/bluetooth_adapter_mac.h" 11 #include "device/bluetooth/bluetooth_adapter_mac.h"
12 #include "device/bluetooth/bluetooth_device_mac.h" 12 #include "device/bluetooth/bluetooth_device_mac.h"
13 #include "device/bluetooth/bluetooth_gatt_notify_session.h" 13 #include "device/bluetooth/bluetooth_gatt_notify_session.h"
14 #include "device/bluetooth/bluetooth_remote_gatt_descriptor_mac.h"
14 #include "device/bluetooth/bluetooth_remote_gatt_service_mac.h" 15 #include "device/bluetooth/bluetooth_remote_gatt_service_mac.h"
15 16
16 namespace device { 17 namespace device {
17 18
18 namespace { 19 namespace {
19 20
20 static BluetoothGattCharacteristic::Properties ConvertProperties( 21 static BluetoothGattCharacteristic::Properties ConvertProperties(
21 CBCharacteristicProperties cb_property) { 22 CBCharacteristicProperties cb_property) {
22 BluetoothGattCharacteristic::Properties result = 23 BluetoothGattCharacteristic::Properties result =
23 BluetoothGattCharacteristic::PROPERTY_NONE; 24 BluetoothGattCharacteristic::PROPERTY_NONE;
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 const { 123 const {
123 return static_cast<BluetoothRemoteGattService*>(gatt_service_); 124 return static_cast<BluetoothRemoteGattService*>(gatt_service_);
124 } 125 }
125 126
126 bool BluetoothRemoteGattCharacteristicMac::IsNotifying() const { 127 bool BluetoothRemoteGattCharacteristicMac::IsNotifying() const {
127 return cb_characteristic_.get().isNotifying == YES; 128 return cb_characteristic_.get().isNotifying == YES;
128 } 129 }
129 130
130 std::vector<BluetoothRemoteGattDescriptor*> 131 std::vector<BluetoothRemoteGattDescriptor*>
131 BluetoothRemoteGattCharacteristicMac::GetDescriptors() const { 132 BluetoothRemoteGattCharacteristicMac::GetDescriptors() const {
132 NOTIMPLEMENTED(); 133 std::vector<BluetoothRemoteGattDescriptor*> gatt_descriptors;
133 return std::vector<BluetoothRemoteGattDescriptor*>(); 134 for (const auto& iter : gatt_descriptor_macs_) {
135 BluetoothRemoteGattDescriptor* gatt_descriptor =
136 static_cast<BluetoothRemoteGattDescriptor*>(iter.second.get());
137 gatt_descriptors.push_back(gatt_descriptor);
138 }
139 return gatt_descriptors;
134 } 140 }
135 141
136 BluetoothRemoteGattDescriptor* 142 BluetoothRemoteGattDescriptor*
137 BluetoothRemoteGattCharacteristicMac::GetDescriptor( 143 BluetoothRemoteGattCharacteristicMac::GetDescriptor(
138 const std::string& identifier) const { 144 const std::string& identifier) const {
139 NOTIMPLEMENTED(); 145 auto searched_pair = gatt_descriptor_macs_.find(identifier);
140 return nullptr; 146 if (searched_pair == gatt_descriptor_macs_.end()) {
147 return nullptr;
148 }
149 return static_cast<BluetoothRemoteGattDescriptor*>(
150 searched_pair->second.get());
141 } 151 }
142 152
143 void BluetoothRemoteGattCharacteristicMac::StartNotifySession( 153 void BluetoothRemoteGattCharacteristicMac::StartNotifySession(
144 const NotifySessionCallback& callback, 154 const NotifySessionCallback& callback,
145 const ErrorCallback& error_callback) { 155 const ErrorCallback& error_callback) {
146 if (IsNotifying()) { 156 if (IsNotifying()) {
147 VLOG(2) << "Already notifying. Creating notify session."; 157 VLOG(2) << "Already notifying. Creating notify session.";
148 std::unique_ptr<BluetoothGattNotifySession> notify_session( 158 std::unique_ptr<BluetoothGattNotifySession> notify_session(
149 new BluetoothGattNotifySession(weak_ptr_factory_.GetWeakPtr())); 159 new BluetoothGattNotifySession(weak_ptr_factory_.GetWeakPtr()));
150 base::ThreadTaskRunnerHandle::Get()->PostTask( 160 base::ThreadTaskRunnerHandle::Get()->PostTask(
(...skipping 12 matching lines...) Expand all
163 173
164 start_notify_session_callbacks_.push_back( 174 start_notify_session_callbacks_.push_back(
165 std::make_pair(callback, error_callback)); 175 std::make_pair(callback, error_callback));
166 176
167 if (start_notifications_in_progress_) { 177 if (start_notifications_in_progress_) {
168 VLOG(2) << "Start Notifications already in progress. " 178 VLOG(2) << "Start Notifications already in progress. "
169 << "Request has been queued."; 179 << "Request has been queued.";
170 return; 180 return;
171 } 181 }
172 182
173 [gatt_service_->GetCBPeripheral() setNotifyValue:YES 183 [GetCBPeripheral() setNotifyValue:YES
174 forCharacteristic:cb_characteristic_.get()]; 184 forCharacteristic:cb_characteristic_.get()];
175 start_notifications_in_progress_ = true; 185 start_notifications_in_progress_ = true;
176 } 186 }
177 187
178 void BluetoothRemoteGattCharacteristicMac::StopNotifySession( 188 void BluetoothRemoteGattCharacteristicMac::StopNotifySession(
179 BluetoothGattNotifySession* session, 189 BluetoothGattNotifySession* session,
180 const base::Closure& callback) { 190 const base::Closure& callback) {
181 // TODO(http://crbug.com/633191): Remove this method and use the base version. 191 // TODO(http://crbug.com/633191): Remove this method and use the base version.
182 // Instead, we should implement SubscribeToNotifications and 192 // Instead, we should implement SubscribeToNotifications and
183 // UnsubscribeFromNotifications. 193 // UnsubscribeFromNotifications.
184 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback); 194 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
(...skipping 12 matching lines...) Expand all
197 if (characteristic_value_read_or_write_in_progress_) { 207 if (characteristic_value_read_or_write_in_progress_) {
198 base::ThreadTaskRunnerHandle::Get()->PostTask( 208 base::ThreadTaskRunnerHandle::Get()->PostTask(
199 FROM_HERE, 209 FROM_HERE,
200 base::Bind(error_callback, 210 base::Bind(error_callback,
201 BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS)); 211 BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS));
202 return; 212 return;
203 } 213 }
204 characteristic_value_read_or_write_in_progress_ = true; 214 characteristic_value_read_or_write_in_progress_ = true;
205 read_characteristic_value_callbacks_ = 215 read_characteristic_value_callbacks_ =
206 std::make_pair(callback, error_callback); 216 std::make_pair(callback, error_callback);
207 [gatt_service_->GetCBPeripheral() 217 [GetCBPeripheral() readValueForCharacteristic:cb_characteristic_];
208 readValueForCharacteristic:cb_characteristic_];
209 } 218 }
210 219
211 void BluetoothRemoteGattCharacteristicMac::WriteRemoteCharacteristic( 220 void BluetoothRemoteGattCharacteristicMac::WriteRemoteCharacteristic(
212 const std::vector<uint8_t>& value, 221 const std::vector<uint8_t>& value,
213 const base::Closure& callback, 222 const base::Closure& callback,
214 const ErrorCallback& error_callback) { 223 const ErrorCallback& error_callback) {
215 if (!IsWritable()) { 224 if (!IsWritable()) {
216 base::ThreadTaskRunnerHandle::Get()->PostTask( 225 base::ThreadTaskRunnerHandle::Get()->PostTask(
217 FROM_HERE, 226 FROM_HERE,
218 base::Bind(error_callback, 227 base::Bind(error_callback,
219 BluetoothRemoteGattService::GATT_ERROR_NOT_PERMITTED)); 228 BluetoothRemoteGattService::GATT_ERROR_NOT_PERMITTED));
220 return; 229 return;
221 } 230 }
222 if (characteristic_value_read_or_write_in_progress_) { 231 if (characteristic_value_read_or_write_in_progress_) {
223 base::ThreadTaskRunnerHandle::Get()->PostTask( 232 base::ThreadTaskRunnerHandle::Get()->PostTask(
224 FROM_HERE, 233 FROM_HERE,
225 base::Bind(error_callback, 234 base::Bind(error_callback,
226 BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS)); 235 BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS));
227 return; 236 return;
228 } 237 }
229 characteristic_value_read_or_write_in_progress_ = true; 238 characteristic_value_read_or_write_in_progress_ = true;
230 write_characteristic_value_callbacks_ = 239 write_characteristic_value_callbacks_ =
231 std::make_pair(callback, error_callback); 240 std::make_pair(callback, error_callback);
232 base::scoped_nsobject<NSData> nsdata_value( 241 base::scoped_nsobject<NSData> nsdata_value(
233 [[NSData alloc] initWithBytes:value.data() length:value.size()]); 242 [[NSData alloc] initWithBytes:value.data() length:value.size()]);
234 CBCharacteristicWriteType write_type = GetCBWriteType(); 243 CBCharacteristicWriteType write_type = GetCBWriteType();
235 [gatt_service_->GetCBPeripheral() writeValue:nsdata_value 244 [GetCBPeripheral() writeValue:nsdata_value
236 forCharacteristic:cb_characteristic_ 245 forCharacteristic:cb_characteristic_
237 type:write_type]; 246 type:write_type];
238 if (write_type == CBCharacteristicWriteWithoutResponse) { 247 if (write_type == CBCharacteristicWriteWithoutResponse) {
239 base::ThreadTaskRunnerHandle::Get()->PostTask( 248 base::ThreadTaskRunnerHandle::Get()->PostTask(
240 FROM_HERE, 249 FROM_HERE,
241 base::Bind(&BluetoothRemoteGattCharacteristicMac::DidWriteValue, 250 base::Bind(&BluetoothRemoteGattCharacteristicMac::DidWriteValue,
242 base::Unretained(this), nil)); 251 base::Unretained(this), nil));
243 } 252 }
244 } 253 }
245 254
246 void BluetoothRemoteGattCharacteristicMac::SubscribeToNotifications( 255 void BluetoothRemoteGattCharacteristicMac::SubscribeToNotifications(
247 BluetoothRemoteGattDescriptor* ccc_descriptor, 256 BluetoothRemoteGattDescriptor* ccc_descriptor,
248 const base::Closure& callback, 257 const base::Closure& callback,
249 const ErrorCallback& error_callback) { 258 const ErrorCallback& error_callback) {
250 // TODO(http://crbug.com/633191): Implement this method 259 // TODO(http://crbug.com/633191): Implement this method
251 NOTIMPLEMENTED(); 260 NOTIMPLEMENTED();
252 } 261 }
253 262
254 void BluetoothRemoteGattCharacteristicMac::UnsubscribeFromNotifications( 263 void BluetoothRemoteGattCharacteristicMac::UnsubscribeFromNotifications(
255 BluetoothRemoteGattDescriptor* ccc_descriptor, 264 BluetoothRemoteGattDescriptor* ccc_descriptor,
256 const base::Closure& callback, 265 const base::Closure& callback,
257 const ErrorCallback& error_callback) { 266 const ErrorCallback& error_callback) {
258 // TODO(http://crbug.com/633191): Implement this method 267 // TODO(http://crbug.com/633191): Implement this method
259 NOTIMPLEMENTED(); 268 NOTIMPLEMENTED();
260 } 269 }
261 270
271 void BluetoothRemoteGattCharacteristicMac::DiscoverDescriptors() {
272 is_discovery_complete_ = false;
273 [GetCBPeripheral()
274 discoverDescriptorsForCharacteristic:cb_characteristic_.get()];
275 }
276
262 void BluetoothRemoteGattCharacteristicMac::DidUpdateValue(NSError* error) { 277 void BluetoothRemoteGattCharacteristicMac::DidUpdateValue(NSError* error) {
263 CHECK_EQ(gatt_service_->GetCBPeripheral().state, CBPeripheralStateConnected); 278 CHECK_EQ(GetCBPeripheral().state, CBPeripheralStateConnected);
264 // This method is called when the characteristic is read and when a 279 // This method is called when the characteristic is read and when a
265 // notification is received. 280 // notification is received.
266 if (characteristic_value_read_or_write_in_progress_) { 281 if (characteristic_value_read_or_write_in_progress_) {
267 std::pair<ValueCallback, ErrorCallback> callbacks; 282 std::pair<ValueCallback, ErrorCallback> callbacks;
268 callbacks.swap(read_characteristic_value_callbacks_); 283 callbacks.swap(read_characteristic_value_callbacks_);
269 characteristic_value_read_or_write_in_progress_ = false; 284 characteristic_value_read_or_write_in_progress_ = false;
270 if (error) { 285 if (error) {
271 VLOG(1) << "Bluetooth error while reading for characteristic, domain: " 286 VLOG(1) << "Bluetooth error while reading for characteristic, domain: "
272 << base::SysNSStringToUTF8(error.domain) 287 << base::SysNSStringToUTF8(error.domain)
273 << ", error code: " << error.code; 288 << ", error code: " << error.code;
(...skipping 16 matching lines...) Expand all
290 305
291 void BluetoothRemoteGattCharacteristicMac::UpdateValueAndNotify() { 306 void BluetoothRemoteGattCharacteristicMac::UpdateValueAndNotify() {
292 NSData* nsdata_value = cb_characteristic_.get().value; 307 NSData* nsdata_value = cb_characteristic_.get().value;
293 const uint8_t* buffer = static_cast<const uint8_t*>(nsdata_value.bytes); 308 const uint8_t* buffer = static_cast<const uint8_t*>(nsdata_value.bytes);
294 value_.assign(buffer, buffer + nsdata_value.length); 309 value_.assign(buffer, buffer + nsdata_value.length);
295 gatt_service_->GetMacAdapter()->NotifyGattCharacteristicValueChanged(this, 310 gatt_service_->GetMacAdapter()->NotifyGattCharacteristicValueChanged(this,
296 value_); 311 value_);
297 } 312 }
298 313
299 void BluetoothRemoteGattCharacteristicMac::DidWriteValue(NSError* error) { 314 void BluetoothRemoteGattCharacteristicMac::DidWriteValue(NSError* error) {
300 CHECK_EQ(gatt_service_->GetCBPeripheral().state, CBPeripheralStateConnected); 315 CHECK_EQ(GetCBPeripheral().state, CBPeripheralStateConnected);
301 if (!characteristic_value_read_or_write_in_progress_) { 316 if (!characteristic_value_read_or_write_in_progress_) {
302 // In case of buggy device, nothing should be done if receiving extra 317 // In case of buggy device, nothing should be done if receiving extra
303 // write confirmation. 318 // write confirmation.
304 VLOG(1) << "Write notification while no write operation pending."; 319 VLOG(1) << "Write notification while no write operation pending.";
305 return; 320 return;
306 } 321 }
307 std::pair<base::Closure, ErrorCallback> callbacks; 322 std::pair<base::Closure, ErrorCallback> callbacks;
308 callbacks.swap(write_characteristic_value_callbacks_); 323 callbacks.swap(write_characteristic_value_callbacks_);
309 characteristic_value_read_or_write_in_progress_ = false; 324 characteristic_value_read_or_write_in_progress_ = false;
310 if (error) { 325 if (error) {
(...skipping 26 matching lines...) Expand all
337 callback.second.Run(error_code); 352 callback.second.Run(error_code);
338 } 353 }
339 return; 354 return;
340 } 355 }
341 for (const auto& callback : reentrant_safe_callbacks) { 356 for (const auto& callback : reentrant_safe_callbacks) {
342 callback.first.Run(base::MakeUnique<BluetoothGattNotifySession>( 357 callback.first.Run(base::MakeUnique<BluetoothGattNotifySession>(
343 weak_ptr_factory_.GetWeakPtr())); 358 weak_ptr_factory_.GetWeakPtr()));
344 } 359 }
345 } 360 }
346 361
362 void BluetoothRemoteGattCharacteristicMac::DidDiscoverDescriptors() {
363 DCHECK(!is_discovery_complete_);
364 std::unordered_set<std::string> descriptor_identifier_to_remove;
365 for (const auto& iter : gatt_descriptor_macs_) {
366 descriptor_identifier_to_remove.insert(iter.first);
367 }
368
369 for (CBDescriptor* cb_descriptor in cb_characteristic_.get().descriptors) {
370 BluetoothRemoteGattDescriptorMac* gatt_descriptor_mac =
371 GetBluetoothRemoteGattDescriptorMac(cb_descriptor);
372 if (gatt_descriptor_mac) {
373 const std::string& identifier = gatt_descriptor_mac->GetIdentifier();
374 descriptor_identifier_to_remove.erase(identifier);
375 continue;
376 }
377 gatt_descriptor_mac =
378 new BluetoothRemoteGattDescriptorMac(this, cb_descriptor);
379 const std::string& identifier = gatt_descriptor_mac->GetIdentifier();
380 auto result_iter = gatt_descriptor_macs_.insert(
381 {identifier, base::WrapUnique(gatt_descriptor_mac)});
382 DCHECK(result_iter.second);
383 GetMacAdapter()->NotifyGattDescriptorAdded(gatt_descriptor_mac);
384 }
385
386 for (const std::string& identifier : descriptor_identifier_to_remove) {
387 auto pair_to_remove = gatt_descriptor_macs_.find(identifier);
388 std::unique_ptr<BluetoothRemoteGattDescriptorMac> descriptor_to_remove;
389 pair_to_remove->second.swap(descriptor_to_remove);
390 gatt_descriptor_macs_.erase(pair_to_remove);
391 GetMacAdapter()->NotifyGattDescriptorRemoved(descriptor_to_remove.get());
392 }
393 is_discovery_complete_ = true;
394 }
395
347 bool BluetoothRemoteGattCharacteristicMac::IsReadable() const { 396 bool BluetoothRemoteGattCharacteristicMac::IsReadable() const {
348 return GetProperties() & BluetoothGattCharacteristic::PROPERTY_READ; 397 return GetProperties() & BluetoothGattCharacteristic::PROPERTY_READ;
349 } 398 }
350 399
351 bool BluetoothRemoteGattCharacteristicMac::IsWritable() const { 400 bool BluetoothRemoteGattCharacteristicMac::IsWritable() const {
352 BluetoothGattCharacteristic::Properties properties = GetProperties(); 401 BluetoothGattCharacteristic::Properties properties = GetProperties();
353 return (properties & BluetoothGattCharacteristic::PROPERTY_WRITE) || 402 return (properties & BluetoothGattCharacteristic::PROPERTY_WRITE) ||
354 (properties & PROPERTY_WRITE_WITHOUT_RESPONSE); 403 (properties & PROPERTY_WRITE_WITHOUT_RESPONSE);
355 } 404 }
356 405
357 bool BluetoothRemoteGattCharacteristicMac::SupportsNotificationsOrIndications() 406 bool BluetoothRemoteGattCharacteristicMac::SupportsNotificationsOrIndications()
358 const { 407 const {
359 BluetoothGattCharacteristic::Properties properties = GetProperties(); 408 BluetoothGattCharacteristic::Properties properties = GetProperties();
360 return (properties & PROPERTY_NOTIFY) || (properties & PROPERTY_INDICATE); 409 return (properties & PROPERTY_NOTIFY) || (properties & PROPERTY_INDICATE);
361 } 410 }
362 411
363 CBCharacteristicWriteType BluetoothRemoteGattCharacteristicMac::GetCBWriteType() 412 CBCharacteristicWriteType BluetoothRemoteGattCharacteristicMac::GetCBWriteType()
364 const { 413 const {
365 return (GetProperties() & BluetoothGattCharacteristic::PROPERTY_WRITE) 414 return (GetProperties() & BluetoothGattCharacteristic::PROPERTY_WRITE)
366 ? CBCharacteristicWriteWithResponse 415 ? CBCharacteristicWriteWithResponse
367 : CBCharacteristicWriteWithoutResponse; 416 : CBCharacteristicWriteWithoutResponse;
368 } 417 }
369 418
370 CBCharacteristic* BluetoothRemoteGattCharacteristicMac::GetCBCharacteristic() 419 CBCharacteristic* BluetoothRemoteGattCharacteristicMac::GetCBCharacteristic()
371 const { 420 const {
372 return cb_characteristic_.get(); 421 return cb_characteristic_.get();
373 } 422 }
374 423
375 bool BluetoothRemoteGattCharacteristicMac::IsDiscoveryComplete() const { 424 BluetoothAdapterMac* BluetoothRemoteGattCharacteristicMac::GetMacAdapter()
376 // TODO: Needs to replace this implementation with a boolean to monitor when 425 const {
377 // descriptors are discovered. Right now, the characteristic is fully 426 return gatt_service_->GetMacAdapter();
378 // discovered as soon as it has been created.
379 return true;
380 } 427 }
381 428
429 CBPeripheral* BluetoothRemoteGattCharacteristicMac::GetCBPeripheral() const {
430 return gatt_service_->GetCBPeripheral();
431 }
432
433 bool BluetoothRemoteGattCharacteristicMac::IsDiscoveryComplete() const {
434 return is_discovery_complete_;
435 }
436
437 BluetoothRemoteGattDescriptorMac*
438 BluetoothRemoteGattCharacteristicMac::GetBluetoothRemoteGattDescriptorMac(
439 CBDescriptor* cb_descriptor) const {
440 auto found = std::find_if(
441 gatt_descriptor_macs_.begin(), gatt_descriptor_macs_.end(),
442 [cb_descriptor](
443 const std::pair<const std::string,
444 std::unique_ptr<BluetoothRemoteGattDescriptorMac>>&
445 pair) {
446 return pair.second->GetCBDescriptor() == cb_descriptor;
447 });
448 if (found == gatt_descriptor_macs_.end()) {
449 return nullptr;
450 } else {
451 return found->second.get();
452 }
453 }
382 } // namespace device. 454 } // namespace device.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698