[go: nahoru, domu]

blob: caefb2c3eff3088d566cd40d4b1dcc2eab79dc6d [file] [log] [blame]
Avi Drissman0db84842022-09-13 19:47:041// Copyright 2018 The Chromium Authors
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:162// 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_descriptor_winrt.h"
6
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:577#include <utility>
8
Sebastien Marchand6d0558fd2019-01-25 16:49:379#include "base/bind.h"
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:1610#include "base/logging.h"
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5711#include "base/memory/ptr_util.h"
12#include "base/strings/stringprintf.h"
Jan Wilken Dörried0a3dc62018-08-06 10:15:4513#include "base/threading/thread_task_runner_handle.h"
Reilly Grant4bc137c2018-12-13 22:55:1514#include "base/win/post_async_results.h"
Jan Wilken Dörried0a3dc62018-08-06 10:15:4515#include "base/win/winrt_storage_util.h"
Martin Kreichgauerc8a70012020-01-31 01:08:5216#include "components/device_event_log/device_event_log.h"
Jan Wilken Dörried0a3dc62018-08-06 10:15:4517#include "device/bluetooth/bluetooth_remote_gatt_service_winrt.h"
18#include "device/bluetooth/event_utils_winrt.h"
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:1619
20namespace device {
21
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5722namespace {
23
Reilly Grantdc08cac2018-12-07 01:11:0124using ABI::Windows::Devices::Bluetooth::BluetoothCacheMode_Uncached;
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5725using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
Jan Wilken Dörried0a3dc62018-08-06 10:15:4526 GattCommunicationStatus;
27using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
28 GattCommunicationStatus_Success;
29using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::GattReadResult;
30using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
31 GattWriteResult;
32using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5733 IGattDescriptor;
Jan Wilken Dörried0a3dc62018-08-06 10:15:4534using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
Reilly Grantdc08cac2018-12-07 01:11:0135 IGattDescriptor2;
Jan Wilken Dörried0a3dc62018-08-06 10:15:4536using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
37 IGattReadResult;
38using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
Reilly Grantdc08cac2018-12-07 01:11:0139 IGattReadResult2;
40using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
Jan Wilken Dörried0a3dc62018-08-06 10:15:4541 IGattWriteResult;
42using ABI::Windows::Foundation::IAsyncOperation;
43using ABI::Windows::Storage::Streams::IBuffer;
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5744using Microsoft::WRL::ComPtr;
45
46} // namespace
47
48// static
49std::unique_ptr<BluetoothRemoteGattDescriptorWinrt>
50BluetoothRemoteGattDescriptorWinrt::Create(
51 BluetoothRemoteGattCharacteristic* characteristic,
52 ComPtr<IGattDescriptor> descriptor) {
53 DCHECK(descriptor);
54 GUID guid;
55 HRESULT hr = descriptor->get_Uuid(&guid);
56 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:5257 BLUETOOTH_LOG(ERROR) << "Getting UUID failed: "
58 << logging::SystemErrorCodeToString(hr);
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5759 return nullptr;
60 }
61
62 uint16_t attribute_handle;
63 hr = descriptor->get_AttributeHandle(&attribute_handle);
64 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:5265 BLUETOOTH_LOG(ERROR) << "Getting AttributeHandle failed: "
66 << logging::SystemErrorCodeToString(hr);
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5767 return nullptr;
68 }
69
70 return base::WrapUnique(new BluetoothRemoteGattDescriptorWinrt(
71 characteristic, std::move(descriptor), BluetoothUUID(guid),
72 attribute_handle));
73}
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:1674
75BluetoothRemoteGattDescriptorWinrt::~BluetoothRemoteGattDescriptorWinrt() =
76 default;
77
78std::string BluetoothRemoteGattDescriptorWinrt::GetIdentifier() const {
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5779 return identifier_;
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:1680}
81
82BluetoothUUID BluetoothRemoteGattDescriptorWinrt::GetUUID() const {
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5783 return uuid_;
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:1684}
85
86BluetoothGattCharacteristic::Permissions
87BluetoothRemoteGattDescriptorWinrt::GetPermissions() const {
88 NOTIMPLEMENTED();
89 return BluetoothGattCharacteristic::Permissions();
90}
91
92const std::vector<uint8_t>& BluetoothRemoteGattDescriptorWinrt::GetValue()
93 const {
94 return value_;
95}
96
97BluetoothRemoteGattCharacteristic*
98BluetoothRemoteGattDescriptorWinrt::GetCharacteristic() const {
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5799 return characteristic_;
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:16100}
101
102void BluetoothRemoteGattDescriptorWinrt::ReadRemoteDescriptor(
Chris Mumford6627ae42021-05-03 18:54:40103 ValueCallback callback) {
104 if (pending_read_callback_ || pending_write_callbacks_) {
Jan Wilken Dörried0a3dc62018-08-06 10:15:45105 base::ThreadTaskRunnerHandle::Get()->PostTask(
Chris Mumford860d05e2021-05-12 17:08:51106 FROM_HERE, base::BindOnce(std::move(callback),
107 BluetoothGattService::GATT_ERROR_IN_PROGRESS,
108 /*value=*/std::vector<uint8_t>()));
Jan Wilken Dörried0a3dc62018-08-06 10:15:45109 return;
110 }
111
112 ComPtr<IAsyncOperation<GattReadResult*>> read_value_op;
Reilly Grantdc08cac2018-12-07 01:11:01113 HRESULT hr = descriptor_->ReadValueWithCacheModeAsync(
114 BluetoothCacheMode_Uncached, &read_value_op);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45115 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52116 BLUETOOTH_LOG(ERROR)
117 << "GattDescriptor::ReadValueWithCacheModeAsync failed: "
118 << logging::SystemErrorCodeToString(hr);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45119 base::ThreadTaskRunnerHandle::Get()->PostTask(
Chris Mumford6627ae42021-05-03 18:54:40120 FROM_HERE, base::BindOnce(std::move(callback),
Chris Mumford860d05e2021-05-12 17:08:51121 BluetoothGattService::GATT_ERROR_FAILED,
Chris Mumford6627ae42021-05-03 18:54:40122 /*value=*/std::vector<uint8_t>()));
Jan Wilken Dörried0a3dc62018-08-06 10:15:45123 return;
124 }
125
Reilly Grant4bc137c2018-12-13 22:55:15126 hr = base::win::PostAsyncResults(
Jan Wilken Dörried0a3dc62018-08-06 10:15:45127 std::move(read_value_op),
128 base::BindOnce(&BluetoothRemoteGattDescriptorWinrt::OnReadValue,
129 weak_ptr_factory_.GetWeakPtr()));
130
131 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52132 BLUETOOTH_LOG(ERROR) << "PostAsyncResults failed: "
133 << logging::SystemErrorCodeToString(hr);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45134 base::ThreadTaskRunnerHandle::Get()->PostTask(
Chris Mumford6627ae42021-05-03 18:54:40135 FROM_HERE, base::BindOnce(std::move(callback),
Chris Mumford860d05e2021-05-12 17:08:51136 BluetoothGattService::GATT_ERROR_FAILED,
Chris Mumford6627ae42021-05-03 18:54:40137 /*value=*/std::vector<uint8_t>()));
Jan Wilken Dörried0a3dc62018-08-06 10:15:45138 return;
139 }
140
Chris Mumford6627ae42021-05-03 18:54:40141 pending_read_callback_ = std::move(callback);
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:16142}
143
144void BluetoothRemoteGattDescriptorWinrt::WriteRemoteDescriptor(
145 const std::vector<uint8_t>& value,
danakjfcba225f2019-04-23 17:06:49146 base::OnceClosure callback,
danakj056b93572019-04-23 16:04:45147 ErrorCallback error_callback) {
Chris Mumford6627ae42021-05-03 18:54:40148 if (pending_read_callback_ || pending_write_callbacks_) {
Jan Wilken Dörried0a3dc62018-08-06 10:15:45149 base::ThreadTaskRunnerHandle::Get()->PostTask(
150 FROM_HERE,
danakj056b93572019-04-23 16:04:45151 base::BindOnce(std::move(error_callback),
Chris Mumford860d05e2021-05-12 17:08:51152 BluetoothGattService::GATT_ERROR_IN_PROGRESS));
Jan Wilken Dörried0a3dc62018-08-06 10:15:45153 return;
154 }
155
156 ComPtr<IGattDescriptor2> descriptor_2;
157 HRESULT hr = descriptor_.As(&descriptor_2);
158 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52159 BLUETOOTH_LOG(ERROR) << "As IGattDescriptor2 failed: "
160 << logging::SystemErrorCodeToString(hr);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45161 base::ThreadTaskRunnerHandle::Get()->PostTask(
Chris Mumford860d05e2021-05-12 17:08:51162 FROM_HERE, base::BindOnce(std::move(error_callback),
163 BluetoothGattService::GATT_ERROR_FAILED));
Jan Wilken Dörried0a3dc62018-08-06 10:15:45164 return;
165 }
166
167 ComPtr<IBuffer> buffer;
168 hr = base::win::CreateIBufferFromData(value.data(), value.size(), &buffer);
169 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52170 BLUETOOTH_LOG(ERROR) << "base::win::CreateIBufferFromData failed: "
171 << logging::SystemErrorCodeToString(hr);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45172 base::ThreadTaskRunnerHandle::Get()->PostTask(
Chris Mumford860d05e2021-05-12 17:08:51173 FROM_HERE, base::BindOnce(std::move(error_callback),
174 BluetoothGattService::GATT_ERROR_FAILED));
Jan Wilken Dörried0a3dc62018-08-06 10:15:45175 return;
176 }
177
178 ComPtr<IAsyncOperation<GattWriteResult*>> write_value_op;
179 hr = descriptor_2->WriteValueWithResultAsync(buffer.Get(), &write_value_op);
180 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52181 BLUETOOTH_LOG(ERROR) << "GattDescriptor::WriteValueWithResultAsync failed: "
182 << logging::SystemErrorCodeToString(hr);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45183 base::ThreadTaskRunnerHandle::Get()->PostTask(
Chris Mumford860d05e2021-05-12 17:08:51184 FROM_HERE, base::BindOnce(std::move(error_callback),
185 BluetoothGattService::GATT_ERROR_FAILED));
Jan Wilken Dörried0a3dc62018-08-06 10:15:45186 return;
187 }
188
Reilly Grant4bc137c2018-12-13 22:55:15189 hr = base::win::PostAsyncResults(
Jan Wilken Dörried0a3dc62018-08-06 10:15:45190 std::move(write_value_op),
191 base::BindOnce(
192 &BluetoothRemoteGattDescriptorWinrt::OnWriteValueWithResult,
193 weak_ptr_factory_.GetWeakPtr()));
194
195 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52196 BLUETOOTH_LOG(ERROR) << "PostAsyncResults failed: "
197 << logging::SystemErrorCodeToString(hr);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45198 base::ThreadTaskRunnerHandle::Get()->PostTask(
Chris Mumford860d05e2021-05-12 17:08:51199 FROM_HERE, base::BindOnce(std::move(error_callback),
200 BluetoothGattService::GATT_ERROR_FAILED));
Jan Wilken Dörried0a3dc62018-08-06 10:15:45201 return;
202 }
203
danakj056b93572019-04-23 16:04:45204 pending_write_callbacks_ = std::make_unique<PendingWriteCallbacks>(
danakjfcba225f2019-04-23 17:06:49205 std::move(callback), std::move(error_callback));
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:16206}
207
Jan Wilken Dörried0a3dc62018-08-06 10:15:45208IGattDescriptor* BluetoothRemoteGattDescriptorWinrt::GetDescriptorForTesting() {
209 return descriptor_.Get();
210}
211
Jan Wilken Dörried0a3dc62018-08-06 10:15:45212BluetoothRemoteGattDescriptorWinrt::PendingWriteCallbacks::
213 PendingWriteCallbacks(base::OnceClosure callback,
214 ErrorCallback error_callback)
215 : callback(std::move(callback)),
216 error_callback(std::move(error_callback)) {}
217
218BluetoothRemoteGattDescriptorWinrt::PendingWriteCallbacks::
219 ~PendingWriteCallbacks() = default;
220
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:57221BluetoothRemoteGattDescriptorWinrt::BluetoothRemoteGattDescriptorWinrt(
222 BluetoothRemoteGattCharacteristic* characteristic,
223 Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::
224 GenericAttributeProfile::IGattDescriptor>
225 descriptor,
226 BluetoothUUID uuid,
227 uint16_t attribute_handle)
228 : characteristic_(characteristic),
229 descriptor_(std::move(descriptor)),
230 uuid_(std::move(uuid)),
231 identifier_(base::StringPrintf("%s/%s_%04x",
232 characteristic_->GetIdentifier().c_str(),
233 uuid_.value().c_str(),
Jeremy Roman2b7c9502019-08-21 22:34:08234 attribute_handle)) {}
Jan Wilken Dörried0a3dc62018-08-06 10:15:45235
236void BluetoothRemoteGattDescriptorWinrt::OnReadValue(
237 ComPtr<IGattReadResult> read_result) {
Chris Mumford6627ae42021-05-03 18:54:40238 DCHECK(pending_read_callback_);
239 auto pending_read_callback = std::move(pending_read_callback_);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45240
241 if (!read_result) {
Martin Kreichgauerc8a70012020-01-31 01:08:52242 BLUETOOTH_LOG(ERROR)
243 << "GattDescriptor::ReadValueWithCacheModeAsync returned no result";
Chris Mumford6627ae42021-05-03 18:54:40244 std::move(pending_read_callback)
245 .Run(BluetoothGattService::GATT_ERROR_FAILED,
246 /*value=*/std::vector<uint8_t>());
Jan Wilken Dörried0a3dc62018-08-06 10:15:45247 return;
248 }
249
250 GattCommunicationStatus status;
251 HRESULT hr = read_result->get_Status(&status);
252 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52253 BLUETOOTH_LOG(ERROR) << "Getting GATT Communication Status failed: "
254 << logging::SystemErrorCodeToString(hr);
Chris Mumford6627ae42021-05-03 18:54:40255 std::move(pending_read_callback)
256 .Run(BluetoothGattService::GATT_ERROR_FAILED,
257 /*value=*/std::vector<uint8_t>());
Jan Wilken Dörried0a3dc62018-08-06 10:15:45258 return;
259 }
260
261 if (status != GattCommunicationStatus_Success) {
Martin Kreichgauerc8a70012020-01-31 01:08:52262 BLUETOOTH_LOG(ERROR) << "Unexpected GattCommunicationStatus: " << status;
Jan Wilken Dörried0a3dc62018-08-06 10:15:45263 ComPtr<IGattReadResult2> read_result_2;
264 hr = read_result.As(&read_result_2);
265 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52266 BLUETOOTH_LOG(ERROR) << "As IGattReadResult2 failed: "
267 << logging::SystemErrorCodeToString(hr);
Chris Mumford6627ae42021-05-03 18:54:40268 std::move(pending_read_callback)
269 .Run(BluetoothGattService::GATT_ERROR_FAILED,
270 /*value=*/std::vector<uint8_t>());
Jan Wilken Dörried0a3dc62018-08-06 10:15:45271 return;
272 }
273
Chris Mumford6627ae42021-05-03 18:54:40274 std::move(pending_read_callback)
danakj056b93572019-04-23 16:04:45275 .Run(BluetoothRemoteGattServiceWinrt::GetGattErrorCode(
Chris Mumford6627ae42021-05-03 18:54:40276 read_result_2.Get()),
277 /*value=*/std::vector<uint8_t>());
Jan Wilken Dörried0a3dc62018-08-06 10:15:45278 return;
279 }
280
281 ComPtr<IBuffer> value;
282 hr = read_result->get_Value(&value);
283 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52284 BLUETOOTH_LOG(ERROR) << "Getting Descriptor Value failed: "
285 << logging::SystemErrorCodeToString(hr);
Chris Mumford6627ae42021-05-03 18:54:40286 std::move(pending_read_callback)
287 .Run(BluetoothGattService::GATT_ERROR_FAILED,
288 /*value=*/std::vector<uint8_t>());
Jan Wilken Dörried0a3dc62018-08-06 10:15:45289 return;
290 }
291
292 uint8_t* data = nullptr;
293 uint32_t length = 0;
294 hr = base::win::GetPointerToBufferData(value.Get(), &data, &length);
295 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52296 BLUETOOTH_LOG(ERROR) << "Getting Pointer To Buffer Data failed: "
297 << logging::SystemErrorCodeToString(hr);
Chris Mumford6627ae42021-05-03 18:54:40298 std::move(pending_read_callback)
299 .Run(BluetoothGattService::GATT_ERROR_FAILED,
300 /*value=*/std::vector<uint8_t>());
Jan Wilken Dörried0a3dc62018-08-06 10:15:45301 return;
302 }
303
304 value_.assign(data, data + length);
Anton Bikineev15c07002021-05-15 17:55:02305 std::move(pending_read_callback).Run(/*error_code=*/absl::nullopt, value_);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45306}
307
308void BluetoothRemoteGattDescriptorWinrt::OnWriteValueWithResult(
309 ComPtr<IGattWriteResult> write_result) {
310 DCHECK(pending_write_callbacks_);
311 auto pending_write_callbacks = std::move(pending_write_callbacks_);
312
313 if (!write_result) {
Martin Kreichgauerc8a70012020-01-31 01:08:52314 BLUETOOTH_LOG(ERROR)
315 << "GattDescriptor::WriteValueWithResultAsync returned no result";
danakj056b93572019-04-23 16:04:45316 std::move(pending_write_callbacks->error_callback)
317 .Run(BluetoothGattService::GATT_ERROR_FAILED);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45318 return;
319 }
320
321 GattCommunicationStatus status;
322 HRESULT hr = write_result->get_Status(&status);
323 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52324 BLUETOOTH_LOG(ERROR) << "Getting GATT Communication Status failed: "
325 << logging::SystemErrorCodeToString(hr);
danakj056b93572019-04-23 16:04:45326 std::move(pending_write_callbacks->error_callback)
327 .Run(BluetoothGattService::GATT_ERROR_FAILED);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45328 return;
329 }
330
331 if (status != GattCommunicationStatus_Success) {
Martin Kreichgauerc8a70012020-01-31 01:08:52332 BLUETOOTH_LOG(ERROR) << "Unexpected GattCommunicationStatus: " << status;
danakj056b93572019-04-23 16:04:45333 std::move(pending_write_callbacks->error_callback)
334 .Run(BluetoothRemoteGattServiceWinrt::GetGattErrorCode(
335 write_result.Get()));
Jan Wilken Dörried0a3dc62018-08-06 10:15:45336 return;
337 }
338
339 std::move(pending_write_callbacks->callback).Run();
340}
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:57341
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:16342} // namespace device