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 (!SupportsNotificationsOrIndications()) { | |
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 (start_notifications_in_progress_) | |
152 return; | |
153 [gatt_service_->GetCBPeripheral() setNotifyValue:YES | |
154 forCharacteristic:cb_characteristic_.get()]; | |
155 start_notifications_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 |
219 // notification received. | |
220 if (characteristic_value_read_or_write_in_progress_) { | |
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(); | |
236 } else { | |
196 // In case of buggy device, nothing should be done if receiving extra | 237 // In case of buggy device, nothing should be done if receiving extra |
197 // read confirmation. | 238 // read confirmation. |
198 return; | 239 VLOG(1) << "Characteristic value updated while having no pending read nor " |
240 "notification"; | |
ortuno
2016/06/28 19:18:58
grammar nit: "." at the end of sentence.
jlebel
2016/06/28 21:09:33
Done.
| |
199 } | 241 } |
200 std::pair<ValueCallback, ErrorCallback> callbacks; | 242 } |
201 callbacks.swap(read_characteristic_value_callbacks_); | 243 |
202 characteristic_value_read_or_write_in_progress_ = false; | 244 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; | 245 NSData* nsdata_value = cb_characteristic_.get().value; |
212 const uint8_t* buffer = static_cast<const uint8_t*>(nsdata_value.bytes); | 246 const uint8_t* buffer = static_cast<const uint8_t*>(nsdata_value.bytes); |
213 value_.assign(buffer, buffer + nsdata_value.length); | 247 value_.assign(buffer, buffer + nsdata_value.length); |
214 gatt_service_->GetMacAdapter()->NotifyGattCharacteristicValueChanged(this, | 248 gatt_service_->GetMacAdapter()->NotifyGattCharacteristicValueChanged(this, |
215 value_); | 249 value_); |
216 callbacks.first.Run(value_); | |
217 } | 250 } |
218 | 251 |
219 void BluetoothRemoteGattCharacteristicMac::DidWriteValue(NSError* error) { | 252 void BluetoothRemoteGattCharacteristicMac::DidWriteValue(NSError* error) { |
220 if (!characteristic_value_read_or_write_in_progress_) { | 253 if (!characteristic_value_read_or_write_in_progress_) { |
221 // In case of buggy device, nothing should be done if receiving extra | 254 // In case of buggy device, nothing should be done if receiving extra |
222 // write confirmation. | 255 // write confirmation. |
256 VLOG(1) << "Write notification while no write operation pending"; | |
ortuno
2016/06/28 19:18:58
grammar nit: missing colon.
jlebel
2016/06/28 21:09:33
Done.
| |
223 return; | 257 return; |
224 } | 258 } |
225 std::pair<base::Closure, ErrorCallback> callbacks; | 259 std::pair<base::Closure, ErrorCallback> callbacks; |
226 callbacks.swap(write_characteristic_value_callbacks_); | 260 callbacks.swap(write_characteristic_value_callbacks_); |
227 characteristic_value_read_or_write_in_progress_ = false; | 261 characteristic_value_read_or_write_in_progress_ = false; |
228 if (error) { | 262 if (error) { |
229 VLOG(1) << "Bluetooth error while writing for characteristic, domain: " | 263 VLOG(1) << "Bluetooth error while writing for characteristic, domain: " |
230 << error.domain.UTF8String << ", error code: " << error.code; | 264 << error.domain.UTF8String << ", error code: " << error.code; |
231 BluetoothGattService::GattErrorCode error_code = | 265 BluetoothGattService::GattErrorCode error_code = |
232 BluetoothDeviceMac::GetGattErrorCodeFromNSError(error); | 266 BluetoothDeviceMac::GetGattErrorCodeFromNSError(error); |
233 callbacks.second.Run(error_code); | 267 callbacks.second.Run(error_code); |
234 return; | 268 return; |
235 } | 269 } |
236 NSData* nsdata_value = cb_characteristic_.get().value; | 270 NSData* nsdata_value = cb_characteristic_.get().value; |
237 const uint8_t* buffer = static_cast<const uint8_t*>(nsdata_value.bytes); | 271 const uint8_t* buffer = static_cast<const uint8_t*>(nsdata_value.bytes); |
238 std::vector<uint8_t> gatt_value(buffer, buffer + nsdata_value.length); | 272 std::vector<uint8_t> gatt_value(buffer, buffer + nsdata_value.length); |
239 gatt_service_->GetMacAdapter()->NotifyGattCharacteristicValueChanged(this, | 273 gatt_service_->GetMacAdapter()->NotifyGattCharacteristicValueChanged(this, |
240 value_); | 274 value_); |
241 callbacks.first.Run(); | 275 callbacks.first.Run(); |
242 } | 276 } |
243 | 277 |
278 void BluetoothRemoteGattCharacteristicMac::DidUpdateNotificationState( | |
279 NSError* error) { | |
280 std::vector<std::pair<NotifySessionCallback, ErrorCallback>> | |
281 reentrant_safe_callbacks; | |
282 reentrant_safe_callbacks.swap(start_notify_session_callbacks_); | |
283 start_notifications_in_progress_ = false; | |
284 if (error) { | |
285 VLOG(1) << "Bluetooth error while modifying notification state for " | |
286 "characteristic, domain: " | |
287 << error.domain.UTF8String << ", error code: " << error.code | |
288 << ", localized description: " | |
289 << error.localizedDescription.UTF8String; | |
290 BluetoothGattService::GattErrorCode error_code = | |
291 BluetoothDeviceMac::GetGattErrorCodeFromNSError(error); | |
292 for (const auto& callback : reentrant_safe_callbacks) { | |
293 callback.second.Run(error_code); | |
294 } | |
295 return; | |
296 } | |
297 for (const auto& callback : reentrant_safe_callbacks) { | |
298 callback.first.Run(base::MakeUnique<BluetoothGattNotifySessionMac>( | |
299 weak_ptr_factory_.GetWeakPtr())); | |
300 } | |
301 } | |
302 | |
244 bool BluetoothRemoteGattCharacteristicMac::IsReadable() const { | 303 bool BluetoothRemoteGattCharacteristicMac::IsReadable() const { |
245 return GetProperties() & BluetoothGattCharacteristic::PROPERTY_READ; | 304 return GetProperties() & BluetoothGattCharacteristic::PROPERTY_READ; |
246 } | 305 } |
247 | 306 |
248 bool BluetoothRemoteGattCharacteristicMac::IsWritable() const { | 307 bool BluetoothRemoteGattCharacteristicMac::IsWritable() const { |
249 BluetoothGattCharacteristic::Properties properties = GetProperties(); | 308 BluetoothGattCharacteristic::Properties properties = GetProperties(); |
250 return (properties & BluetoothGattCharacteristic::PROPERTY_WRITE) || | 309 return (properties & BluetoothGattCharacteristic::PROPERTY_WRITE) || |
251 (properties & PROPERTY_WRITE_WITHOUT_RESPONSE); | 310 (properties & PROPERTY_WRITE_WITHOUT_RESPONSE); |
252 } | 311 } |
253 | 312 |
313 bool BluetoothRemoteGattCharacteristicMac::SupportsNotificationsOrIndications() | |
314 const { | |
315 BluetoothGattCharacteristic::Properties properties = GetProperties(); | |
316 return (properties & PROPERTY_NOTIFY) || (properties & PROPERTY_INDICATE); | |
317 } | |
318 | |
254 CBCharacteristicWriteType BluetoothRemoteGattCharacteristicMac::GetCBWriteType() | 319 CBCharacteristicWriteType BluetoothRemoteGattCharacteristicMac::GetCBWriteType() |
255 const { | 320 const { |
256 return (GetProperties() & BluetoothGattCharacteristic::PROPERTY_WRITE) | 321 return (GetProperties() & BluetoothGattCharacteristic::PROPERTY_WRITE) |
257 ? CBCharacteristicWriteWithResponse | 322 ? CBCharacteristicWriteWithResponse |
258 : CBCharacteristicWriteWithoutResponse; | 323 : CBCharacteristicWriteWithoutResponse; |
259 } | 324 } |
260 | 325 |
261 CBCharacteristic* BluetoothRemoteGattCharacteristicMac::GetCBCharacteristic() | 326 CBCharacteristic* BluetoothRemoteGattCharacteristicMac::GetCBCharacteristic() |
262 const { | 327 const { |
263 return cb_characteristic_.get(); | 328 return cb_characteristic_.get(); |
264 } | 329 } |
265 } // namespace device. | 330 } // namespace device. |
OLD | NEW |