gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 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 |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "device/bluetooth/bluetooth_remote_gatt_characteristic_win.h" |
| 6 | |
thakis | 08c9d69b0 | 2016-04-11 04:37:25 | [diff] [blame] | 7 | #include <memory> |
| 8 | |
gogerald | 74459ac | 2016-03-01 20:45:36 | [diff] [blame] | 9 | #include "base/bind.h" |
thakis | 08c9d69b0 | 2016-04-11 04:37:25 | [diff] [blame] | 10 | #include "base/memory/ptr_util.h" |
Giovanni Ortuño Urquidi | 36a75a16 | 2017-06-25 23:48:01 | [diff] [blame] | 11 | #include "base/threading/thread_task_runner_handle.h" |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 12 | #include "device/bluetooth/bluetooth_adapter_win.h" |
tommyt | ad8462b | 2016-08-22 08:09:39 | [diff] [blame] | 13 | #include "device/bluetooth/bluetooth_gatt_notify_session.h" |
gogerald | 74459ac | 2016-03-01 20:45:36 | [diff] [blame] | 14 | #include "device/bluetooth/bluetooth_remote_gatt_descriptor_win.h" |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 15 | #include "device/bluetooth/bluetooth_remote_gatt_service_win.h" |
| 16 | #include "device/bluetooth/bluetooth_task_manager_win.h" |
| 17 | |
| 18 | namespace device { |
| 19 | |
| 20 | BluetoothRemoteGattCharacteristicWin::BluetoothRemoteGattCharacteristicWin( |
| 21 | BluetoothRemoteGattServiceWin* parent_service, |
| 22 | BTH_LE_GATT_CHARACTERISTIC* characteristic_info, |
| 23 | scoped_refptr<base::SequencedTaskRunner>& ui_task_runner) |
| 24 | : parent_service_(parent_service), |
| 25 | characteristic_info_(characteristic_info), |
| 26 | ui_task_runner_(ui_task_runner), |
gogerald | 74459ac | 2016-03-01 20:45:36 | [diff] [blame] | 27 | characteristic_added_notified_(false), |
gogerald | 50818ce5 | 2016-03-03 21:55:48 | [diff] [blame] | 28 | characteristic_value_read_or_write_in_progress_(false), |
gogerald | 08539da | 2016-04-08 18:51:49 | [diff] [blame] | 29 | gatt_event_handle_(nullptr), |
Conley Owens | 2f3d6fd3 | 2017-11-18 02:00:04 | [diff] [blame] | 30 | discovery_pending_count_(0), |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 31 | weak_ptr_factory_(this) { |
peary2 | 0bd3d49f | 2017-05-19 10:09:41 | [diff] [blame] | 32 | DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 33 | DCHECK(parent_service_); |
| 34 | DCHECK(characteristic_info_); |
| 35 | |
gogerald | 74459ac | 2016-03-01 20:45:36 | [diff] [blame] | 36 | task_manager_ = |
| 37 | parent_service_->GetWinAdapter()->GetWinBluetoothTaskManager(); |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 38 | DCHECK(task_manager_); |
gogerald | 74459ac | 2016-03-01 20:45:36 | [diff] [blame] | 39 | characteristic_uuid_ = |
| 40 | BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid( |
| 41 | characteristic_info_->CharacteristicUuid); |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 42 | characteristic_identifier_ = |
gogerald | 74459ac | 2016-03-01 20:45:36 | [diff] [blame] | 43 | parent_service_->GetIdentifier() + "_" + |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 44 | std::to_string(characteristic_info_->AttributeHandle); |
| 45 | Update(); |
| 46 | } |
| 47 | |
| 48 | BluetoothRemoteGattCharacteristicWin::~BluetoothRemoteGattCharacteristicWin() { |
peary2 | 0bd3d49f | 2017-05-19 10:09:41 | [diff] [blame] | 49 | DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 50 | |
gogerald | 08539da | 2016-04-08 18:51:49 | [diff] [blame] | 51 | ClearIncludedDescriptors(); |
| 52 | |
| 53 | if (gatt_event_handle_ != nullptr) { |
| 54 | task_manager_->PostUnregisterGattCharacteristicValueChangedEvent( |
| 55 | gatt_event_handle_); |
| 56 | gatt_event_handle_ = nullptr; |
| 57 | } |
gogerald | 74459ac | 2016-03-01 20:45:36 | [diff] [blame] | 58 | parent_service_->GetWinAdapter()->NotifyGattCharacteristicRemoved(this); |
gogerald | 08539da | 2016-04-08 18:51:49 | [diff] [blame] | 59 | |
ortuno | 650a52d | 2016-11-08 01:36:30 | [diff] [blame] | 60 | if (!read_characteristic_value_callbacks_.first.is_null()) { |
| 61 | DCHECK(!read_characteristic_value_callbacks_.second.is_null()); |
| 62 | read_characteristic_value_callbacks_.second.Run( |
| 63 | BluetoothRemoteGattService::GATT_ERROR_FAILED); |
| 64 | } |
| 65 | |
| 66 | if (!write_characteristic_value_callbacks_.first.is_null()) { |
| 67 | DCHECK(!write_characteristic_value_callbacks_.second.is_null()); |
| 68 | write_characteristic_value_callbacks_.second.Run( |
| 69 | BluetoothRemoteGattService::GATT_ERROR_FAILED); |
| 70 | } |
| 71 | |
gogerald | 08539da | 2016-04-08 18:51:49 | [diff] [blame] | 72 | // Clear pending StartNotifySession callbacks. |
| 73 | for (const auto& callback : start_notify_session_callbacks_) |
rkc | 12223975 | 2016-04-20 23:59:08 | [diff] [blame] | 74 | callback.second.Run(BluetoothRemoteGattService::GATT_ERROR_FAILED); |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 75 | } |
| 76 | |
| 77 | std::string BluetoothRemoteGattCharacteristicWin::GetIdentifier() const { |
| 78 | return characteristic_identifier_; |
| 79 | } |
| 80 | |
| 81 | BluetoothUUID BluetoothRemoteGattCharacteristicWin::GetUUID() const { |
| 82 | return characteristic_uuid_; |
| 83 | } |
| 84 | |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 85 | std::vector<uint8_t>& BluetoothRemoteGattCharacteristicWin::GetValue() const { |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 86 | return const_cast<std::vector<uint8_t>&>(characteristic_value_); |
| 87 | } |
| 88 | |
rkc | 12223975 | 2016-04-20 23:59:08 | [diff] [blame] | 89 | BluetoothRemoteGattService* BluetoothRemoteGattCharacteristicWin::GetService() |
| 90 | const { |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 91 | return parent_service_; |
| 92 | } |
| 93 | |
rkc | 12223975 | 2016-04-20 23:59:08 | [diff] [blame] | 94 | BluetoothRemoteGattCharacteristic::Properties |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 95 | BluetoothRemoteGattCharacteristicWin::GetProperties() const { |
rkc | 12223975 | 2016-04-20 23:59:08 | [diff] [blame] | 96 | BluetoothRemoteGattCharacteristic::Properties properties = PROPERTY_NONE; |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 97 | |
| 98 | if (characteristic_info_->IsBroadcastable) |
| 99 | properties = properties | PROPERTY_BROADCAST; |
| 100 | if (characteristic_info_->IsReadable) |
| 101 | properties = properties | PROPERTY_READ; |
| 102 | if (characteristic_info_->IsWritableWithoutResponse) |
| 103 | properties = properties | PROPERTY_WRITE_WITHOUT_RESPONSE; |
| 104 | if (characteristic_info_->IsWritable) |
| 105 | properties = properties | PROPERTY_WRITE; |
| 106 | if (characteristic_info_->IsNotifiable) |
| 107 | properties = properties | PROPERTY_NOTIFY; |
| 108 | if (characteristic_info_->IsIndicatable) |
| 109 | properties = properties | PROPERTY_INDICATE; |
| 110 | if (characteristic_info_->IsSignedWritable) |
| 111 | properties = properties | PROPERTY_AUTHENTICATED_SIGNED_WRITES; |
| 112 | if (characteristic_info_->HasExtendedProperties) |
| 113 | properties = properties | PROPERTY_EXTENDED_PROPERTIES; |
| 114 | |
| 115 | // TODO(crbug.com/589304): Information about PROPERTY_RELIABLE_WRITE and |
| 116 | // PROPERTY_WRITABLE_AUXILIARIES is not available in characteristic_info_ |
| 117 | // (BTH_LE_GATT_CHARACTERISTIC). |
| 118 | |
| 119 | return properties; |
| 120 | } |
| 121 | |
rkc | 12223975 | 2016-04-20 23:59:08 | [diff] [blame] | 122 | BluetoothRemoteGattCharacteristic::Permissions |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 123 | BluetoothRemoteGattCharacteristicWin::GetPermissions() const { |
rkc | 12223975 | 2016-04-20 23:59:08 | [diff] [blame] | 124 | BluetoothRemoteGattCharacteristic::Permissions permissions = PERMISSION_NONE; |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 125 | |
| 126 | if (characteristic_info_->IsReadable) |
| 127 | permissions = permissions | PERMISSION_READ; |
| 128 | if (characteristic_info_->IsWritable) |
| 129 | permissions = permissions | PERMISSION_WRITE; |
| 130 | |
| 131 | return permissions; |
| 132 | } |
| 133 | |
| 134 | bool BluetoothRemoteGattCharacteristicWin::IsNotifying() const { |
gogerald | 08539da | 2016-04-08 18:51:49 | [diff] [blame] | 135 | return gatt_event_handle_ != nullptr; |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 136 | } |
| 137 | |
rkc | 12223975 | 2016-04-20 23:59:08 | [diff] [blame] | 138 | std::vector<BluetoothRemoteGattDescriptor*> |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 139 | BluetoothRemoteGattCharacteristicWin::GetDescriptors() const { |
rkc | 12223975 | 2016-04-20 23:59:08 | [diff] [blame] | 140 | std::vector<BluetoothRemoteGattDescriptor*> descriptors; |
gogerald | 74459ac | 2016-03-01 20:45:36 | [diff] [blame] | 141 | for (const auto& descriptor : included_descriptors_) |
| 142 | descriptors.push_back(descriptor.second.get()); |
| 143 | return descriptors; |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 144 | } |
| 145 | |
rkc | 12223975 | 2016-04-20 23:59:08 | [diff] [blame] | 146 | BluetoothRemoteGattDescriptor* |
| 147 | BluetoothRemoteGattCharacteristicWin::GetDescriptor( |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 148 | const std::string& identifier) const { |
gogerald | 74459ac | 2016-03-01 20:45:36 | [diff] [blame] | 149 | GattDescriptorMap::const_iterator it = included_descriptors_.find(identifier); |
| 150 | if (it != included_descriptors_.end()) |
| 151 | return it->second.get(); |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 152 | return nullptr; |
| 153 | } |
| 154 | |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 155 | void BluetoothRemoteGattCharacteristicWin::ReadRemoteCharacteristic( |
| 156 | const ValueCallback& callback, |
| 157 | const ErrorCallback& error_callback) { |
peary2 | 0bd3d49f | 2017-05-19 10:09:41 | [diff] [blame] | 158 | DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); |
gogerald | 50818ce5 | 2016-03-03 21:55:48 | [diff] [blame] | 159 | |
| 160 | if (!characteristic_info_.get()->IsReadable) { |
rkc | 12223975 | 2016-04-20 23:59:08 | [diff] [blame] | 161 | error_callback.Run(BluetoothRemoteGattService::GATT_ERROR_NOT_PERMITTED); |
gogerald | 50818ce5 | 2016-03-03 21:55:48 | [diff] [blame] | 162 | return; |
| 163 | } |
| 164 | |
| 165 | if (characteristic_value_read_or_write_in_progress_) { |
rkc | 12223975 | 2016-04-20 23:59:08 | [diff] [blame] | 166 | error_callback.Run(BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS); |
gogerald | 50818ce5 | 2016-03-03 21:55:48 | [diff] [blame] | 167 | return; |
| 168 | } |
| 169 | |
| 170 | characteristic_value_read_or_write_in_progress_ = true; |
| 171 | read_characteristic_value_callbacks_ = |
| 172 | std::make_pair(callback, error_callback); |
| 173 | task_manager_->PostReadGattCharacteristicValue( |
| 174 | parent_service_->GetServicePath(), characteristic_info_.get(), |
| 175 | base::Bind(&BluetoothRemoteGattCharacteristicWin:: |
| 176 | OnReadRemoteCharacteristicValueCallback, |
| 177 | weak_ptr_factory_.GetWeakPtr())); |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 178 | } |
| 179 | |
| 180 | void BluetoothRemoteGattCharacteristicWin::WriteRemoteCharacteristic( |
tommyt | 73e0d4d | 2016-09-01 20:06:24 | [diff] [blame] | 181 | const std::vector<uint8_t>& value, |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 182 | const base::Closure& callback, |
| 183 | const ErrorCallback& error_callback) { |
peary2 | 0bd3d49f | 2017-05-19 10:09:41 | [diff] [blame] | 184 | DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); |
gogerald | 50818ce5 | 2016-03-03 21:55:48 | [diff] [blame] | 185 | |
Conley Owens | dce81a6 | 2017-11-22 21:08:13 | [diff] [blame] | 186 | if (!characteristic_info_->IsWritable && |
| 187 | !characteristic_info_->IsWritableWithoutResponse) { |
rkc | 12223975 | 2016-04-20 23:59:08 | [diff] [blame] | 188 | error_callback.Run(BluetoothRemoteGattService::GATT_ERROR_NOT_PERMITTED); |
gogerald | 50818ce5 | 2016-03-03 21:55:48 | [diff] [blame] | 189 | return; |
| 190 | } |
| 191 | |
| 192 | if (characteristic_value_read_or_write_in_progress_) { |
rkc | 12223975 | 2016-04-20 23:59:08 | [diff] [blame] | 193 | error_callback.Run(BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS); |
gogerald | 50818ce5 | 2016-03-03 21:55:48 | [diff] [blame] | 194 | return; |
| 195 | } |
| 196 | |
| 197 | characteristic_value_read_or_write_in_progress_ = true; |
| 198 | write_characteristic_value_callbacks_ = |
| 199 | std::make_pair(callback, error_callback); |
| 200 | task_manager_->PostWriteGattCharacteristicValue( |
tommyt | 73e0d4d | 2016-09-01 20:06:24 | [diff] [blame] | 201 | parent_service_->GetServicePath(), characteristic_info_.get(), value, |
gogerald | 50818ce5 | 2016-03-03 21:55:48 | [diff] [blame] | 202 | base::Bind(&BluetoothRemoteGattCharacteristicWin:: |
| 203 | OnWriteRemoteCharacteristicValueCallback, |
| 204 | weak_ptr_factory_.GetWeakPtr())); |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 205 | } |
| 206 | |
| 207 | void BluetoothRemoteGattCharacteristicWin::Update() { |
peary2 | 0bd3d49f | 2017-05-19 10:09:41 | [diff] [blame] | 208 | DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); |
gogerald | 74459ac | 2016-03-01 20:45:36 | [diff] [blame] | 209 | |
Conley Owens | 2f3d6fd3 | 2017-11-18 02:00:04 | [diff] [blame] | 210 | ++discovery_pending_count_; |
gogerald | 74459ac | 2016-03-01 20:45:36 | [diff] [blame] | 211 | task_manager_->PostGetGattIncludedDescriptors( |
| 212 | parent_service_->GetServicePath(), characteristic_info_.get(), |
| 213 | base::Bind(&BluetoothRemoteGattCharacteristicWin:: |
| 214 | OnGetIncludedDescriptorsCallback, |
| 215 | weak_ptr_factory_.GetWeakPtr())); |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 216 | } |
| 217 | |
| 218 | uint16_t BluetoothRemoteGattCharacteristicWin::GetAttributeHandle() const { |
| 219 | return characteristic_info_->AttributeHandle; |
| 220 | } |
| 221 | |
tommyt | ad8462b | 2016-08-22 08:09:39 | [diff] [blame] | 222 | void BluetoothRemoteGattCharacteristicWin::SubscribeToNotifications( |
| 223 | BluetoothRemoteGattDescriptor* ccc_descriptor, |
| 224 | const base::Closure& callback, |
| 225 | const ErrorCallback& error_callback) { |
Giovanni Ortuño Urquidi | 36a75a16 | 2017-06-25 23:48:01 | [diff] [blame] | 226 | task_manager_->PostRegisterGattCharacteristicValueChangedEvent( |
| 227 | parent_service_->GetServicePath(), characteristic_info_.get(), |
| 228 | static_cast<BluetoothRemoteGattDescriptorWin*>(ccc_descriptor) |
| 229 | ->GetWinDescriptorInfo(), |
| 230 | base::Bind( |
| 231 | &BluetoothRemoteGattCharacteristicWin::GattEventRegistrationCallback, |
| 232 | weak_ptr_factory_.GetWeakPtr(), callback, error_callback), |
| 233 | base::Bind(&BluetoothRemoteGattCharacteristicWin:: |
| 234 | OnGattCharacteristicValueChanged, |
| 235 | weak_ptr_factory_.GetWeakPtr())); |
tommyt | ad8462b | 2016-08-22 08:09:39 | [diff] [blame] | 236 | } |
| 237 | |
| 238 | void BluetoothRemoteGattCharacteristicWin::UnsubscribeFromNotifications( |
| 239 | BluetoothRemoteGattDescriptor* ccc_descriptor, |
| 240 | const base::Closure& callback, |
| 241 | const ErrorCallback& error_callback) { |
Giovanni Ortuño Urquidi | 36a75a16 | 2017-06-25 23:48:01 | [diff] [blame] | 242 | // TODO(crbug.com/735828): Implement this method. |
| 243 | base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback); |
tommyt | ad8462b | 2016-08-22 08:09:39 | [diff] [blame] | 244 | } |
| 245 | |
gogerald | 74459ac | 2016-03-01 20:45:36 | [diff] [blame] | 246 | void BluetoothRemoteGattCharacteristicWin::OnGetIncludedDescriptorsCallback( |
thakis | 08c9d69b0 | 2016-04-11 04:37:25 | [diff] [blame] | 247 | std::unique_ptr<BTH_LE_GATT_DESCRIPTOR> descriptors, |
gogerald | 74459ac | 2016-03-01 20:45:36 | [diff] [blame] | 248 | uint16_t num, |
| 249 | HRESULT hr) { |
peary2 | 0bd3d49f | 2017-05-19 10:09:41 | [diff] [blame] | 250 | DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); |
gogerald | 74459ac | 2016-03-01 20:45:36 | [diff] [blame] | 251 | |
| 252 | UpdateIncludedDescriptors(descriptors.get(), num); |
| 253 | if (!characteristic_added_notified_) { |
| 254 | characteristic_added_notified_ = true; |
| 255 | parent_service_->GetWinAdapter()->NotifyGattCharacteristicAdded(this); |
| 256 | } |
Conley Owens | 2f3d6fd3 | 2017-11-18 02:00:04 | [diff] [blame] | 257 | |
| 258 | // Report discovery complete. |
| 259 | if (--discovery_pending_count_ == 0) |
| 260 | parent_service_->GattCharacteristicDiscoveryComplete(this); |
gogerald | 74459ac | 2016-03-01 20:45:36 | [diff] [blame] | 261 | } |
| 262 | |
| 263 | void BluetoothRemoteGattCharacteristicWin::UpdateIncludedDescriptors( |
| 264 | PBTH_LE_GATT_DESCRIPTOR descriptors, |
| 265 | uint16_t num) { |
| 266 | if (num == 0) { |
| 267 | included_descriptors_.clear(); |
| 268 | return; |
| 269 | } |
| 270 | |
| 271 | // First, remove descriptors that no longer exist. |
| 272 | std::vector<std::string> to_be_removed; |
| 273 | for (const auto& d : included_descriptors_) { |
| 274 | if (!DoesDescriptorExist(descriptors, num, d.second.get())) |
| 275 | to_be_removed.push_back(d.second->GetIdentifier()); |
| 276 | } |
gogerald | 08539da | 2016-04-08 18:51:49 | [diff] [blame] | 277 | for (auto id : to_be_removed) { |
| 278 | included_descriptors_[id].reset(); |
gogerald | 74459ac | 2016-03-01 20:45:36 | [diff] [blame] | 279 | included_descriptors_.erase(id); |
gogerald | 08539da | 2016-04-08 18:51:49 | [diff] [blame] | 280 | } |
gogerald | 74459ac | 2016-03-01 20:45:36 | [diff] [blame] | 281 | |
| 282 | // Return if no new descriptors have been added. |
| 283 | if (included_descriptors_.size() == num) |
| 284 | return; |
| 285 | |
| 286 | // Add new descriptors. |
| 287 | for (uint16_t i = 0; i < num; i++) { |
| 288 | if (!IsDescriptorDiscovered(descriptors[i].DescriptorUuid, |
| 289 | descriptors[i].AttributeHandle)) { |
| 290 | PBTH_LE_GATT_DESCRIPTOR win_descriptor_info = |
| 291 | new BTH_LE_GATT_DESCRIPTOR(); |
| 292 | *win_descriptor_info = descriptors[i]; |
| 293 | BluetoothRemoteGattDescriptorWin* descriptor = |
| 294 | new BluetoothRemoteGattDescriptorWin(this, win_descriptor_info, |
| 295 | ui_task_runner_); |
| 296 | included_descriptors_[descriptor->GetIdentifier()] = |
thakis | 08c9d69b0 | 2016-04-11 04:37:25 | [diff] [blame] | 297 | base::WrapUnique(descriptor); |
gogerald | 74459ac | 2016-03-01 20:45:36 | [diff] [blame] | 298 | } |
| 299 | } |
| 300 | } |
| 301 | |
| 302 | bool BluetoothRemoteGattCharacteristicWin::IsDescriptorDiscovered( |
| 303 | BTH_LE_UUID& uuid, |
| 304 | uint16_t attribute_handle) { |
| 305 | BluetoothUUID bt_uuid = |
| 306 | BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid(uuid); |
| 307 | for (const auto& d : included_descriptors_) { |
| 308 | if (bt_uuid == d.second->GetUUID() && |
| 309 | attribute_handle == d.second->GetAttributeHandle()) { |
| 310 | return true; |
| 311 | } |
| 312 | } |
| 313 | return false; |
| 314 | } |
| 315 | |
| 316 | bool BluetoothRemoteGattCharacteristicWin::DoesDescriptorExist( |
| 317 | PBTH_LE_GATT_DESCRIPTOR descriptors, |
| 318 | uint16_t num, |
| 319 | BluetoothRemoteGattDescriptorWin* descriptor) { |
| 320 | for (uint16_t i = 0; i < num; i++) { |
| 321 | BluetoothUUID uuid = |
| 322 | BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid( |
| 323 | descriptors[i].DescriptorUuid); |
| 324 | if (descriptor->GetUUID() == uuid && |
| 325 | descriptor->GetAttributeHandle() == descriptors[i].AttributeHandle) { |
| 326 | return true; |
| 327 | } |
| 328 | } |
| 329 | return false; |
| 330 | } |
| 331 | |
gogerald | 50818ce5 | 2016-03-03 21:55:48 | [diff] [blame] | 332 | void BluetoothRemoteGattCharacteristicWin:: |
| 333 | OnReadRemoteCharacteristicValueCallback( |
thakis | 08c9d69b0 | 2016-04-11 04:37:25 | [diff] [blame] | 334 | std::unique_ptr<BTH_LE_GATT_CHARACTERISTIC_VALUE> value, |
gogerald | 50818ce5 | 2016-03-03 21:55:48 | [diff] [blame] | 335 | HRESULT hr) { |
peary2 | 0bd3d49f | 2017-05-19 10:09:41 | [diff] [blame] | 336 | DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); |
jdoerrie | cad402e3 | 2018-01-17 13:55:17 | [diff] [blame] | 337 | characteristic_value_read_or_write_in_progress_ = false; |
gogerald | 50818ce5 | 2016-03-03 21:55:48 | [diff] [blame] | 338 | |
| 339 | std::pair<ValueCallback, ErrorCallback> callbacks; |
| 340 | callbacks.swap(read_characteristic_value_callbacks_); |
| 341 | if (FAILED(hr)) { |
| 342 | callbacks.second.Run(HRESULTToGattErrorCode(hr)); |
| 343 | } else { |
| 344 | characteristic_value_.clear(); |
| 345 | for (ULONG i = 0; i < value->DataSize; i++) |
| 346 | characteristic_value_.push_back(value->Data[i]); |
ortuno | 32321de | 2016-06-24 18:35:31 | [diff] [blame] | 347 | |
gogerald | 50818ce5 | 2016-03-03 21:55:48 | [diff] [blame] | 348 | callbacks.first.Run(characteristic_value_); |
| 349 | } |
gogerald | 50818ce5 | 2016-03-03 21:55:48 | [diff] [blame] | 350 | } |
| 351 | |
| 352 | void BluetoothRemoteGattCharacteristicWin:: |
| 353 | OnWriteRemoteCharacteristicValueCallback(HRESULT hr) { |
peary2 | 0bd3d49f | 2017-05-19 10:09:41 | [diff] [blame] | 354 | DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); |
jdoerrie | cad402e3 | 2018-01-17 13:55:17 | [diff] [blame] | 355 | characteristic_value_read_or_write_in_progress_ = false; |
gogerald | 50818ce5 | 2016-03-03 21:55:48 | [diff] [blame] | 356 | |
| 357 | std::pair<base::Closure, ErrorCallback> callbacks; |
| 358 | callbacks.swap(write_characteristic_value_callbacks_); |
| 359 | if (FAILED(hr)) { |
| 360 | callbacks.second.Run(HRESULTToGattErrorCode(hr)); |
| 361 | } else { |
| 362 | callbacks.first.Run(); |
| 363 | } |
gogerald | 50818ce5 | 2016-03-03 21:55:48 | [diff] [blame] | 364 | } |
| 365 | |
rkc | 12223975 | 2016-04-20 23:59:08 | [diff] [blame] | 366 | BluetoothRemoteGattService::GattErrorCode |
gogerald | 50818ce5 | 2016-03-03 21:55:48 | [diff] [blame] | 367 | BluetoothRemoteGattCharacteristicWin::HRESULTToGattErrorCode(HRESULT hr) { |
gogerald | 08539da | 2016-04-08 18:51:49 | [diff] [blame] | 368 | if (HRESULT_FROM_WIN32(ERROR_INVALID_USER_BUFFER) == hr) |
rkc | 12223975 | 2016-04-20 23:59:08 | [diff] [blame] | 369 | return BluetoothRemoteGattService::GATT_ERROR_INVALID_LENGTH; |
gogerald | 08539da | 2016-04-08 18:51:49 | [diff] [blame] | 370 | |
gogerald | 50818ce5 | 2016-03-03 21:55:48 | [diff] [blame] | 371 | switch (hr) { |
| 372 | case E_BLUETOOTH_ATT_READ_NOT_PERMITTED: |
| 373 | case E_BLUETOOTH_ATT_WRITE_NOT_PERMITTED: |
rkc | 12223975 | 2016-04-20 23:59:08 | [diff] [blame] | 374 | return BluetoothRemoteGattService::GATT_ERROR_NOT_PERMITTED; |
gogerald | 50818ce5 | 2016-03-03 21:55:48 | [diff] [blame] | 375 | case E_BLUETOOTH_ATT_UNKNOWN_ERROR: |
rkc | 12223975 | 2016-04-20 23:59:08 | [diff] [blame] | 376 | return BluetoothRemoteGattService::GATT_ERROR_UNKNOWN; |
gogerald | 50818ce5 | 2016-03-03 21:55:48 | [diff] [blame] | 377 | case E_BLUETOOTH_ATT_INVALID_ATTRIBUTE_VALUE_LENGTH: |
rkc | 12223975 | 2016-04-20 23:59:08 | [diff] [blame] | 378 | return BluetoothRemoteGattService::GATT_ERROR_INVALID_LENGTH; |
gogerald | 08539da | 2016-04-08 18:51:49 | [diff] [blame] | 379 | case E_BLUETOOTH_ATT_REQUEST_NOT_SUPPORTED: |
rkc | 12223975 | 2016-04-20 23:59:08 | [diff] [blame] | 380 | return BluetoothRemoteGattService::GATT_ERROR_NOT_SUPPORTED; |
gogerald | 50818ce5 | 2016-03-03 21:55:48 | [diff] [blame] | 381 | default: |
rkc | 12223975 | 2016-04-20 23:59:08 | [diff] [blame] | 382 | return BluetoothRemoteGattService::GATT_ERROR_FAILED; |
gogerald | 50818ce5 | 2016-03-03 21:55:48 | [diff] [blame] | 383 | } |
| 384 | } |
| 385 | |
gogerald | 08539da | 2016-04-08 18:51:49 | [diff] [blame] | 386 | void BluetoothRemoteGattCharacteristicWin::OnGattCharacteristicValueChanged( |
thakis | 08c9d69b0 | 2016-04-11 04:37:25 | [diff] [blame] | 387 | std::unique_ptr<std::vector<uint8_t>> new_value) { |
peary2 | 0bd3d49f | 2017-05-19 10:09:41 | [diff] [blame] | 388 | DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); |
gogerald | 08539da | 2016-04-08 18:51:49 | [diff] [blame] | 389 | |
| 390 | characteristic_value_.assign(new_value->begin(), new_value->end()); |
| 391 | parent_service_->GetWinAdapter()->NotifyGattCharacteristicValueChanged( |
| 392 | this, characteristic_value_); |
| 393 | } |
| 394 | |
| 395 | void BluetoothRemoteGattCharacteristicWin::GattEventRegistrationCallback( |
Giovanni Ortuño Urquidi | 36a75a16 | 2017-06-25 23:48:01 | [diff] [blame] | 396 | const base::Closure& callback, |
| 397 | const ErrorCallback& error_callback, |
gogerald | 08539da | 2016-04-08 18:51:49 | [diff] [blame] | 398 | BLUETOOTH_GATT_EVENT_HANDLE event_handle, |
| 399 | HRESULT hr) { |
peary2 | 0bd3d49f | 2017-05-19 10:09:41 | [diff] [blame] | 400 | DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); |
gogerald | 08539da | 2016-04-08 18:51:49 | [diff] [blame] | 401 | if (SUCCEEDED(hr)) { |
| 402 | gatt_event_handle_ = event_handle; |
Giovanni Ortuño Urquidi | 36a75a16 | 2017-06-25 23:48:01 | [diff] [blame] | 403 | callback.Run(); |
gogerald | 08539da | 2016-04-08 18:51:49 | [diff] [blame] | 404 | } else { |
Giovanni Ortuño Urquidi | 36a75a16 | 2017-06-25 23:48:01 | [diff] [blame] | 405 | error_callback.Run(HRESULTToGattErrorCode(hr)); |
gogerald | 08539da | 2016-04-08 18:51:49 | [diff] [blame] | 406 | } |
| 407 | } |
| 408 | |
| 409 | void BluetoothRemoteGattCharacteristicWin::ClearIncludedDescriptors() { |
| 410 | // Explicitly reset to null to ensure that calling GetDescriptor() on the |
| 411 | // removed descriptor in GattDescriptorRemoved() returns null. |
| 412 | for (auto& entry : included_descriptors_) |
| 413 | entry.second.reset(); |
| 414 | included_descriptors_.clear(); |
| 415 | } |
| 416 | |
gogerald | e069a45 | 2016-02-26 15:36:09 | [diff] [blame] | 417 | } // namespace device. |