Chromium Code Reviews| OLD | NEW |
|---|---|
| 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/threading/thread_task_runner_handle.h" | 9 #include "base/threading/thread_task_runner_handle.h" |
| 9 #include "device/bluetooth/bluetooth_adapter_mac.h" | 10 #include "device/bluetooth/bluetooth_adapter_mac.h" |
| 10 #include "device/bluetooth/bluetooth_device_mac.h" | 11 #include "device/bluetooth/bluetooth_device_mac.h" |
| 12 #include "device/bluetooth/bluetooth_gatt_notify_session_mac.h" | |
| 11 #include "device/bluetooth/bluetooth_remote_gatt_service_mac.h" | 13 #include "device/bluetooth/bluetooth_remote_gatt_service_mac.h" |
| 12 | 14 |
| 13 namespace device { | 15 namespace device { |
| 14 | 16 |
| 15 namespace { | 17 namespace { |
| 16 | 18 |
| 17 static BluetoothGattCharacteristic::Properties ConvertProperties( | 19 static BluetoothGattCharacteristic::Properties ConvertProperties( |
| 18 CBCharacteristicProperties cb_property) { | 20 CBCharacteristicProperties cb_property) { |
| 19 BluetoothGattCharacteristic::Properties result = | 21 BluetoothGattCharacteristic::Properties result = |
| 20 BluetoothGattCharacteristic::PROPERTY_NONE; | 22 BluetoothGattCharacteristic::PROPERTY_NONE; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 60 } | 62 } |
| 61 return result; | 63 return result; |
| 62 } | 64 } |
| 63 } // namespace | 65 } // namespace |
| 64 | 66 |
| 65 BluetoothRemoteGattCharacteristicMac::BluetoothRemoteGattCharacteristicMac( | 67 BluetoothRemoteGattCharacteristicMac::BluetoothRemoteGattCharacteristicMac( |
| 66 BluetoothRemoteGattServiceMac* gatt_service, | 68 BluetoothRemoteGattServiceMac* gatt_service, |
| 67 CBCharacteristic* cb_characteristic) | 69 CBCharacteristic* cb_characteristic) |
| 68 : gatt_service_(gatt_service), | 70 : gatt_service_(gatt_service), |
| 69 cb_characteristic_(cb_characteristic, base::scoped_policy::RETAIN), | 71 cb_characteristic_(cb_characteristic, base::scoped_policy::RETAIN), |
| 70 characteristic_value_read_or_write_in_progress_(false) { | 72 characteristic_value_read_or_write_in_progress_(false), |
| 73 weak_ptr_factory_(this) { | |
| 71 uuid_ = BluetoothAdapterMac::BluetoothUUIDWithCBUUID( | 74 uuid_ = BluetoothAdapterMac::BluetoothUUIDWithCBUUID( |
| 72 [cb_characteristic_.get() UUID]); | 75 [cb_characteristic_.get() UUID]); |
| 73 identifier_ = | 76 identifier_ = |
| 74 [NSString stringWithFormat:@"%s-%p", uuid_.canonical_value().c_str(), | 77 [NSString stringWithFormat:@"%s-%p", uuid_.canonical_value().c_str(), |
| 75 (void*)cb_characteristic_] | 78 (void*)cb_characteristic_] |
| 76 .UTF8String; | 79 .UTF8String; |
| 77 } | 80 } |
| 78 | 81 |
| 79 BluetoothRemoteGattCharacteristicMac::~BluetoothRemoteGattCharacteristicMac() {} | 82 BluetoothRemoteGattCharacteristicMac::~BluetoothRemoteGattCharacteristicMac() {} |
| 80 | 83 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 102 const { | 105 const { |
| 103 return value_; | 106 return value_; |
| 104 } | 107 } |
| 105 | 108 |
| 106 BluetoothRemoteGattService* BluetoothRemoteGattCharacteristicMac::GetService() | 109 BluetoothRemoteGattService* BluetoothRemoteGattCharacteristicMac::GetService() |
| 107 const { | 110 const { |
| 108 return static_cast<BluetoothRemoteGattService*>(gatt_service_); | 111 return static_cast<BluetoothRemoteGattService*>(gatt_service_); |
| 109 } | 112 } |
| 110 | 113 |
| 111 bool BluetoothRemoteGattCharacteristicMac::IsNotifying() const { | 114 bool BluetoothRemoteGattCharacteristicMac::IsNotifying() const { |
| 112 NOTIMPLEMENTED(); | 115 return cb_characteristic_.get().isNotifying == YES; |
| 113 return false; | |
| 114 } | 116 } |
| 115 | 117 |
| 116 std::vector<BluetoothRemoteGattDescriptor*> | 118 std::vector<BluetoothRemoteGattDescriptor*> |
| 117 BluetoothRemoteGattCharacteristicMac::GetDescriptors() const { | 119 BluetoothRemoteGattCharacteristicMac::GetDescriptors() const { |
| 118 NOTIMPLEMENTED(); | 120 NOTIMPLEMENTED(); |
| 119 return std::vector<BluetoothRemoteGattDescriptor*>(); | 121 return std::vector<BluetoothRemoteGattDescriptor*>(); |
| 120 } | 122 } |
| 121 | 123 |
| 122 BluetoothRemoteGattDescriptor* | 124 BluetoothRemoteGattDescriptor* |
| 123 BluetoothRemoteGattCharacteristicMac::GetDescriptor( | 125 BluetoothRemoteGattCharacteristicMac::GetDescriptor( |
| 124 const std::string& identifier) const { | 126 const std::string& identifier) const { |
| 125 NOTIMPLEMENTED(); | 127 NOTIMPLEMENTED(); |
| 126 return nullptr; | 128 return nullptr; |
| 127 } | 129 } |
| 128 | 130 |
| 129 void BluetoothRemoteGattCharacteristicMac::StartNotifySession( | 131 void BluetoothRemoteGattCharacteristicMac::StartNotifySession( |
| 130 const NotifySessionCallback& callback, | 132 const NotifySessionCallback& callback, |
| 131 const ErrorCallback& error_callback) { | 133 const ErrorCallback& error_callback) { |
| 132 NOTIMPLEMENTED(); | 134 if (IsNotifying()) { |
| 135 std::unique_ptr<BluetoothGattNotifySessionMac> notify_session( | |
| 136 new BluetoothGattNotifySessionMac(weak_ptr_factory_.GetWeakPtr())); | |
| 137 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 138 FROM_HERE, | |
| 139 base::Bind(callback, base::Passed(std::move(notify_session)))); | |
| 140 return; | |
| 141 } | |
| 142 if (!IsNotifiableOrIndicatable()) { | |
| 143 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 144 FROM_HERE, | |
| 145 base::Bind(error_callback, | |
| 146 BluetoothRemoteGattService::GATT_ERROR_NOT_SUPPORTED)); | |
| 147 return; | |
| 148 } | |
| 149 start_notify_session_callbacks_.push_back( | |
| 150 std::make_pair(callback, error_callback)); | |
| 151 if (gatt_event_registeration_in_progress_) | |
| 152 return; | |
| 153 [gatt_service_->GetCBPeripheral() setNotifyValue:YES | |
| 154 forCharacteristic:cb_characteristic_.get()]; | |
| 155 gatt_event_registeration_in_progress_ = true; | |
| 133 } | 156 } |
| 134 | 157 |
| 135 void BluetoothRemoteGattCharacteristicMac::ReadRemoteCharacteristic( | 158 void BluetoothRemoteGattCharacteristicMac::ReadRemoteCharacteristic( |
| 136 const ValueCallback& callback, | 159 const ValueCallback& callback, |
| 137 const ErrorCallback& error_callback) { | 160 const ErrorCallback& error_callback) { |
| 138 if (!IsReadable()) { | 161 if (!IsReadable()) { |
| 139 base::ThreadTaskRunnerHandle::Get()->PostTask( | 162 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 140 FROM_HERE, | 163 FROM_HERE, |
| 141 base::Bind(error_callback, | 164 base::Bind(error_callback, |
| 142 BluetoothRemoteGattService::GATT_ERROR_NOT_SUPPORTED)); | 165 BluetoothRemoteGattService::GATT_ERROR_NOT_SUPPORTED)); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 185 type:write_type]; | 208 type:write_type]; |
| 186 if (write_type == CBCharacteristicWriteWithoutResponse) { | 209 if (write_type == CBCharacteristicWriteWithoutResponse) { |
| 187 base::ThreadTaskRunnerHandle::Get()->PostTask( | 210 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 188 FROM_HERE, | 211 FROM_HERE, |
| 189 base::Bind(&BluetoothRemoteGattCharacteristicMac::DidWriteValue, | 212 base::Bind(&BluetoothRemoteGattCharacteristicMac::DidWriteValue, |
| 190 base::Unretained(this), nil)); | 213 base::Unretained(this), nil)); |
| 191 } | 214 } |
| 192 } | 215 } |
| 193 | 216 |
| 194 void BluetoothRemoteGattCharacteristicMac::DidUpdateValue(NSError* error) { | 217 void BluetoothRemoteGattCharacteristicMac::DidUpdateValue(NSError* error) { |
| 195 if (!characteristic_value_read_or_write_in_progress_) { | 218 // This method is called when the characteristic is read and when a |
| 196 // In case of buggy device, nothing should be done if receiving extra | 219 // notification received. |
| 197 // read confirmation. | 220 if (characteristic_value_read_or_write_in_progress_) { |
| 198 return; | 221 std::pair<ValueCallback, ErrorCallback> callbacks; |
| 222 callbacks.swap(read_characteristic_value_callbacks_); | |
| 223 characteristic_value_read_or_write_in_progress_ = false; | |
| 224 if (error) { | |
| 225 VLOG(1) << "Bluetooth error while reading for characteristic, domain: " | |
| 226 << error.domain.UTF8String << ", error code: " << error.code; | |
| 227 BluetoothGattService::GattErrorCode error_code = | |
| 228 BluetoothDeviceMac::GetGattErrorCodeFromNSError(error); | |
| 229 callbacks.second.Run(error_code); | |
| 230 return; | |
| 231 } | |
| 232 UpdateValueAndNotify(); | |
| 233 callbacks.first.Run(value_); | |
| 234 } else if (IsNotifying()) { | |
| 235 UpdateValueAndNotify(); | |
| 199 } | 236 } |
|
ortuno
2016/06/28 16:24:50
We don't expect both conditions to fail right? Cou
jlebel
2016/06/28 18:09:52
Done.
| |
| 200 std::pair<ValueCallback, ErrorCallback> callbacks; | 237 } |
| 201 callbacks.swap(read_characteristic_value_callbacks_); | 238 |
| 202 characteristic_value_read_or_write_in_progress_ = false; | 239 void BluetoothRemoteGattCharacteristicMac::UpdateValueAndNotify() { |
| 203 if (error) { | |
| 204 VLOG(1) << "Bluetooth error while reading for characteristic, domain: " | |
| 205 << error.domain.UTF8String << ", error code: " << error.code; | |
| 206 BluetoothGattService::GattErrorCode error_code = | |
| 207 BluetoothDeviceMac::GetGattErrorCodeFromNSError(error); | |
| 208 callbacks.second.Run(error_code); | |
| 209 return; | |
| 210 } | |
| 211 NSData* nsdata_value = cb_characteristic_.get().value; | 240 NSData* nsdata_value = cb_characteristic_.get().value; |
| 212 const uint8_t* buffer = static_cast<const uint8_t*>(nsdata_value.bytes); | 241 const uint8_t* buffer = static_cast<const uint8_t*>(nsdata_value.bytes); |
| 213 value_.assign(buffer, buffer + nsdata_value.length); | 242 value_.assign(buffer, buffer + nsdata_value.length); |
| 214 gatt_service_->GetMacAdapter()->NotifyGattCharacteristicValueChanged(this, | 243 gatt_service_->GetMacAdapter()->NotifyGattCharacteristicValueChanged(this, |
| 215 value_); | 244 value_); |
| 216 callbacks.first.Run(value_); | |
| 217 } | 245 } |
| 218 | 246 |
| 219 void BluetoothRemoteGattCharacteristicMac::DidWriteValue(NSError* error) { | 247 void BluetoothRemoteGattCharacteristicMac::DidWriteValue(NSError* error) { |
| 220 if (!characteristic_value_read_or_write_in_progress_) { | 248 if (!characteristic_value_read_or_write_in_progress_) { |
| 221 // In case of buggy device, nothing should be done if receiving extra | 249 // In case of buggy device, nothing should be done if receiving extra |
| 222 // write confirmation. | 250 // write confirmation. |
| 223 return; | 251 return; |
| 224 } | 252 } |
| 225 std::pair<base::Closure, ErrorCallback> callbacks; | 253 std::pair<base::Closure, ErrorCallback> callbacks; |
| 226 callbacks.swap(write_characteristic_value_callbacks_); | 254 callbacks.swap(write_characteristic_value_callbacks_); |
| 227 characteristic_value_read_or_write_in_progress_ = false; | 255 characteristic_value_read_or_write_in_progress_ = false; |
| 228 if (error) { | 256 if (error) { |
| 229 VLOG(1) << "Bluetooth error while writing for characteristic, domain: " | 257 VLOG(1) << "Bluetooth error while writing for characteristic, domain: " |
| 230 << error.domain.UTF8String << ", error code: " << error.code; | 258 << error.domain.UTF8String << ", error code: " << error.code; |
| 231 BluetoothGattService::GattErrorCode error_code = | 259 BluetoothGattService::GattErrorCode error_code = |
| 232 BluetoothDeviceMac::GetGattErrorCodeFromNSError(error); | 260 BluetoothDeviceMac::GetGattErrorCodeFromNSError(error); |
| 233 callbacks.second.Run(error_code); | 261 callbacks.second.Run(error_code); |
| 234 return; | 262 return; |
| 235 } | 263 } |
| 236 NSData* nsdata_value = cb_characteristic_.get().value; | 264 NSData* nsdata_value = cb_characteristic_.get().value; |
| 237 const uint8_t* buffer = static_cast<const uint8_t*>(nsdata_value.bytes); | 265 const uint8_t* buffer = static_cast<const uint8_t*>(nsdata_value.bytes); |
| 238 std::vector<uint8_t> gatt_value(buffer, buffer + nsdata_value.length); | 266 std::vector<uint8_t> gatt_value(buffer, buffer + nsdata_value.length); |
| 239 gatt_service_->GetMacAdapter()->NotifyGattCharacteristicValueChanged(this, | 267 gatt_service_->GetMacAdapter()->NotifyGattCharacteristicValueChanged(this, |
| 240 value_); | 268 value_); |
| 241 callbacks.first.Run(); | 269 callbacks.first.Run(); |
| 242 } | 270 } |
| 243 | 271 |
| 272 void BluetoothRemoteGattCharacteristicMac::DidUpdateNotificationState( | |
| 273 NSError* error) { | |
| 274 std::vector<std::pair<NotifySessionCallback, ErrorCallback>> callbacks; | |
|
ortuno
2016/06/28 16:24:50
nit: call this reentrant_safe_callbacks
jlebel
2016/06/28 18:09:52
Done.
| |
| 275 callbacks.swap(start_notify_session_callbacks_); | |
| 276 gatt_event_registeration_in_progress_ = false; | |
| 277 if (error) { | |
| 278 VLOG(1) << "Bluetooth error while modifying notification state for " | |
| 279 "characteristic, domain: " | |
| 280 << error.domain.UTF8String << ", error code: " << error.code | |
| 281 << ", localized description: " | |
| 282 << error.localizedDescription.UTF8String; | |
| 283 BluetoothGattService::GattErrorCode error_code = | |
| 284 BluetoothDeviceMac::GetGattErrorCodeFromNSError(error); | |
| 285 for (const auto& callback : callbacks) { | |
| 286 callback.second.Run(error_code); | |
| 287 } | |
| 288 return; | |
| 289 } | |
| 290 for (const auto& callback : callbacks) { | |
| 291 callback.first.Run(base::WrapUnique( | |
|
ortuno
2016/06/28 16:24:50
This should be:
base::MakeUnique<BluetoothGattNot
jlebel
2016/06/28 18:09:52
Done.
| |
| 292 new BluetoothGattNotifySessionMac(weak_ptr_factory_.GetWeakPtr()))); | |
| 293 } | |
| 294 } | |
| 295 | |
| 244 bool BluetoothRemoteGattCharacteristicMac::IsReadable() const { | 296 bool BluetoothRemoteGattCharacteristicMac::IsReadable() const { |
| 245 return GetProperties() & BluetoothGattCharacteristic::PROPERTY_READ; | 297 return GetProperties() & BluetoothGattCharacteristic::PROPERTY_READ; |
| 246 } | 298 } |
| 247 | 299 |
| 248 bool BluetoothRemoteGattCharacteristicMac::IsWritable() const { | 300 bool BluetoothRemoteGattCharacteristicMac::IsWritable() const { |
| 249 BluetoothGattCharacteristic::Properties properties = GetProperties(); | 301 BluetoothGattCharacteristic::Properties properties = GetProperties(); |
| 250 return (properties & BluetoothGattCharacteristic::PROPERTY_WRITE) || | 302 return (properties & BluetoothGattCharacteristic::PROPERTY_WRITE) || |
| 251 (properties & PROPERTY_WRITE_WITHOUT_RESPONSE); | 303 (properties & PROPERTY_WRITE_WITHOUT_RESPONSE); |
| 252 } | 304 } |
| 253 | 305 |
| 306 bool BluetoothRemoteGattCharacteristicMac::IsNotifiableOrIndicatable() const { | |
| 307 BluetoothGattCharacteristic::Properties properties = GetProperties(); | |
| 308 return (properties & PROPERTY_NOTIFY) || (properties & PROPERTY_INDICATE); | |
| 309 } | |
| 310 | |
| 254 CBCharacteristicWriteType BluetoothRemoteGattCharacteristicMac::GetCBWriteType() | 311 CBCharacteristicWriteType BluetoothRemoteGattCharacteristicMac::GetCBWriteType() |
| 255 const { | 312 const { |
| 256 return (GetProperties() & BluetoothGattCharacteristic::PROPERTY_WRITE) | 313 return (GetProperties() & BluetoothGattCharacteristic::PROPERTY_WRITE) |
| 257 ? CBCharacteristicWriteWithResponse | 314 ? CBCharacteristicWriteWithResponse |
| 258 : CBCharacteristicWriteWithoutResponse; | 315 : CBCharacteristicWriteWithoutResponse; |
| 259 } | 316 } |
| 260 | 317 |
| 261 CBCharacteristic* BluetoothRemoteGattCharacteristicMac::GetCBCharacteristic() | 318 CBCharacteristic* BluetoothRemoteGattCharacteristicMac::GetCBCharacteristic() |
| 262 const { | 319 const { |
| 263 return cb_characteristic_.get(); | 320 return cb_characteristic_.get(); |
| 264 } | 321 } |
| 265 } // namespace device. | 322 } // namespace device. |
| OLD | NEW |